When applying a downgrade package on a Virtual A/B device
(to a non-Virtual A/B build), source slot partitions must
be kept in the metadata.
Test: liblp_test
Bug: 138258570
Change-Id: I87afe68bcfa768bdc015f5966b593758b856c741
Add CreateCowForUpdate / MapSnapshotDevicesForUpdate
that update_engine and init can call them directly.
Bug: 134536978
Test: libsnapshot_test
Change-Id: If53c48855931db27454fd2893745915c77fd37f8
- Open up GetFreeRegions() API.
- Add a new argument, free_region_hint, to ResizePartitions(). It
indicates the regions that extents can be allocated to.
- Expose Interval::Intersect functions. libsnapshot needs the algorithm
to intersect extents to find out the free regions for COW partitions.
Test: liblp_test
Change-Id: I0c079c0e919aa7b0627eb76a071a7cc2a281d692
When the bootloader (or fastbootd) flashes the super partition, we need
to make sure that init doesn't re-map any snapshot or snapshot-merge targets.
A simple way to do this is to introduce an attribute that is only added
by update_engine. When this flag is present, we know the partition has
not been flashed.
This bumps the minor version of LpMetadata. To make this as uninvasive
as possible, the new minor version is only used when MetadataBuilder
detects the new attribute. The new liblp can read older metadata, but will
reject it if it contains an illegal attribute set.
Bug: 139154795
Test: liblp_test gtest
Change-Id: I5ae15d11219b41575a9f71d7dbdb43cbf07a3529
For Virtual A/B devices, rename partitions / groups ending in
source slot to target slot, so that the metadata can later
be written to target metadata slot.
Test: liblp_test_static
Bug: 135752105
Change-Id: I6a7b25e8da2808b1831f317760f4345df6b22689
For Virtual A/B devices, we snapshot the partitions. Hence
there is no need to prioritize using the second half of super
partition for _b partitions.
Test: liblp_test_static
Bug: 135752105
Change-Id: I8bd669e6ffa0a4d114a1b386133179bd2819099b
Allow to retrieve name of a block device partition at
a certain index. If the index is out of range, return
empty string.
This is needed for an hypothetical edge case when an
intersection of two LinearExtent needs to be computed,
and the two metadata have a different list of block
device names. In reality, Virtual A/B devices are always
launched with dynamic partitions, so it will always return
"super" for index 0 and "" otherwise.
Test: liblp_test_static
Bug: 135752105
Change-Id: I9ea59edefdc41d0e69e3644aa2452676372938b4
Converting all of them to string_view requires some
non-trivial amount of refactoring (because there is not
an implicit conversion from string_view to string), and
hence may be done later if necessary.
Test: builds
Bug: 135752105
Change-Id: I936ae7117500fadc7b34a5b91b279bc863d9919d
Move the logic for retrofit DAP to its new function. The new flow
in NewForUpdate is:
metadata = ReadMetadata();
if (retrofit dap) UpdateMetadataForOtherSuper(metadata)
return metadata;
Test: liblp_test_static
Change-Id: I6890fff3a7c44ebe2004de96b2ccbe1e8ce37546
kDefaultGroup is the 'default' group that is never deleted
and has no size constraints. During a virtual a/b update,
the following series of action happens:
- move partitions out of groups that will be shrunk / deleted
(into default)
- shrink / delete these groups
- grow / add other groups
- move those partitions to their destination group.
Otherwise, the metadata is inconsistent.
Bug: 138816109
Test: builds
Change-Id: I57cf4b44dda948377c6b3153756f469caa4652bc
Use dependency injection so that GetProperty / GetBoolProperty
can be mocked in tests.
Test: run liblp_test_static
Change-Id: I8efa85fbbd7aebce2541f748f840e512f3729c30
Changing the type of kDefaultGroup from std::string to std::string_view
allows us to make it a constexpr object. Since kDefaultGroup is the
only dirty object in liblp .bss at runtime, this change turns the .bss
page clean and thus saves 4KB per library load.
Bug: 138856262
Test: Boot cuttlefish and check liblp bss is clean for all 5 processes
that are using it.
Change-Id: I7d7c0992e0ab769f070807f24e1275ffed424b5b
Check the value of ro.boot.dynamic_partitions_retrofit instead of
checking the name of the super partition being 'super' is a more
reliable way of determining retrofit DAP devices.
Some devices launch with DAP (e.g. cuttlefish) doesn't have "super"
as the super partition name. When Virtual A/B is implemented on
cuttlefish, update_engine calls NewForUpdate for the current super
partition metadata. Hence, this code needs to check the retrofit
sysprop instead.
Also, renamed IsRetrofitDevice to IsRetrofitMetadata to avoid the
confusion.
Test: OTA on retrofit DAP device
Test: OTA on launch DAP device
Test: liblp_test_static
Change-Id: I4636de854734df1bb61779d9a955217e89fdb2fd
Normally MetadataBuilder will refuse to create non-suffixed partitions
on A/B devices. There are some scenarios where this doesn't make sense,
like when gsid needs to build metadata files for
system_gsi/userdata_gsi. It also doesn't make sense for the "scratch"
partition, so we added exceptions.
It turns out that metadata created by gsid cannot be re-imported by
MetadataBuilder, because there's no opportunity to set the "ignore" flag
in MetadataBuilder's constructor. Rather than plumbing a flag through, I
think we should just remove this error. It has too many exceptions
already and it doesn't really protect against anything. The motivation was
to avoid confusion in fastbootd on retrofit devices (where there are two
super partitions), but it's a pretty minor concern.
Bug: 134536978
Test: liblp_test gtest
Change-Id: I4629a3c46070c35bcce1017096338e72aa234371
When allocating a partition with a size that is unaligned (to the
optimal alignment), the remaining sectors are wasted since they are
never reallocated. This is because the free list is guaranteed to only
contain optimally-aligned regions. Unfortunately this means when a
partition is resized, we are wasting a small amount of space each time.
On a non-A/B device, this could wind up being significant.
For example, with an alignment of 512KiB, a 4KiB partition at offset 0
will waste 508KiB of space. The next extent to be allocated by any
partition will start at the next 512KiB.
To address this, we check if the last extent for a partition can be
extended to cover the difference between its last sector and the next
optimally aligned sector. We also verify that this region was not
allocated to any other partition, and does not appear in the free list,
to make sure we're not stealing space that will be used somewhere else.
Bug: 120434950
Test: liblp_test gtest
Change-Id: I88689889d44a4d2c51e659241918aaf2c064e049
When this patch landed, it was thought that over-allocating partitions
had no undesired side effects. However there are cases where it is now
causing problems. When flashing a GSI for VTS, the vbmeta is appended to
the end of the partition. If libfs_avb cannot find this vbmeta by
looking at the end of the partition, verification will fail. Similar use
cases with verifying other dynamic partitions are expected to be
problematic, so for now we revert to block-size alignment.
This reverts commit dccfdca1e1.
Bug: 125113249
Test: liblp_test gtest
Change-Id: Ibfd66734b63265e9fbb2ccf6b670c168c36190bc
When flashing in fastbootd, we create a new MetadataBuilder using the
given super_empty.img and attempt to import the existing partition
table. This will fail if there is some incompatibility in the partition
layout or partition quotas.
This import code was accidentally double-accounting partitions when
determining if they could fit within the group quota, preventing
"fastboot flashall" once partitions reached a certain size.
Bug: 126930319
Test: liblp_test gtest
Change-Id: I89a69cba110b62719197c9a4885cfc5bcf8f009f
liblp treats the term "block size" ambiguously when it compares the logical
hardware block size with the file system block size (which for all
intents and purposes must be 4K). This warning is thus spurious on
devices with say a 512 logical block size. However, liblp's block size
should at least be a multiple of this, so change the check accordingly.
Bug: 123317012
Test: liblp_test gtest
Change-Id: I0f41f6bae60a512ab8d313e487c28606daa661a6
Bug: 122616553
Test: built and ran liblp_test on Pixel 3 with Q weekly build
Added missing __attribute__((packed)) in two metadata structures.
Fixed error logging message when repairing primary metadata.
Few very minor additions related to metadata validation.
Fixed an off by one error in the validation of partition name length.
Change-Id: Ic777baf97871c786a209da7c32bc13c1360a8482
Signed-off-by: Ramon Pantin <pantin@google.com>
When allocating a partition with a size that is unaligned (to the
optimal alignment), the remaining sectors are wasted since they are
never reallocated. This is because the free list is guaranteed to only
contain optimally-aligned regions. Unfortunately this means when a
partition is resized, we are wasting a small amount of space each time.
On a non-A/B device, this could wind up being significant.
For example, with an alignment of 512KiB, a 4KiB partition at offset 0
will waste 508KiB of space. The next extent to be allocated by any
partition will start at the next 512KiB.
To address this, we round up extents to the optimal alignment. This
means partitions may wind up slightly over-allocated, versus before,
where they would waste space by making it unavailable.
Bug: 120434950
Test: liblp_test gtest
Change-Id: I555209b301058555526cc4309f7049ae81cf877d
When allocating "b" partitions on a non-retrofit A/B device, prioritize
regions occuring in the second half of the super partition. To make this
effective, the region covering the midpoint sector is split into two
additional regions.
This will allow OTAs to avoid unecessary fragmentation, since each
slot's partitions will be grouped together, leaving a large chunk of
contiguous space available when the OTA deletes the target slot. Since
updates are not allowed to consume more than half of the super
partition, this should guarantee one extent per partition. Note that, if
this restriction is not in place (for example, a developer flashes a
massive "system_b"), then an additional extent will be allocated due to
the region that was split.
Bug: 120433288
Test: liblp_test gtest
Change-Id: I1797e59e14c8b0d4d0e6855a1d984e8159b21df2
This method was designed for a single-super model, and now needs to
change to accomodate two super partitions (system_a and system_b, for
retrofitting).
NewForUpdate is supposed to transition metadata from one block device
to the next for updates. For normal devices this is a no-op, since
metadata only exists on one partition (super). For retrofit devices,
metadata exists on system_a and system_b. This has two implications.
First, any references to the source slot must be rewritten. For example
"vendor_b" must become "vendor_a". However this is not true of partition
names. Partitions/extents are cleared in the updated metadata since they
no longer have any meaning (the block device list has been
rewritten). We also clear groups since they are re-added during OTA.
The reason we have to do this rewriting is that slot suffixes are
automatically applied in ReadMetadata. We do not have access to the
original unsuffixed metadata that was written by the initial OTA.
This was a conscious design decision, since it localizes retrofitting
idiosyncracies to just a few places (ReadMetadata, NewForUpdate, and
fastbootd), minimizing the number of external callers that have to
understand auto-slot-suffixing.
It would be arguably cleaner if retrofit metadata was always serialized
*without* slot suffixes, thereby making NewForUpdate a no-op. However
this would necessitate changes to the API elsewhere. The functions that
read partition names would have to take a slot suffix, and this would
further complicate MetadataBuilder and fastbootd. Another solution would
be to augment LpMetadata to retain unsuffixed information, but this is
probably not worthwhile given that retrofitting is intended to be
surgical, and will have a shorter lifespan than the non-retrofit case.
Bug: 116802789
Test: liblp_test gtest
Change-Id: I33596d92b38c47bc70bc0aa37ed04f6f0b9d4b6f
Retrofit devices will have two super partitions, spanning the A and B
slots separately. By design an OTA will never cause "A" or "B"
partitions to be assigned to the wrong super. However, the same is not
true of fastbootd, where it is possible to flash the inactive slot. We
do not want, for example, logical "system_a" flashing to super_b.
When interacting with partitions, fastbootd now extracts the slot suffix
from a GetSuperSlotSuffix() helper. On retrofit devices, if the partition
name has a slot, that slot will override FastbootDevice::GetCurrentSlot.
This forces partitions in the inactive slot to be assigned to the correct
super.
There are two consequences of this. First, partitions with no slot
suffix will default to the current slot. That means it is possible to
wind up with two "scratch" partitions, if "adb remount" is used on both
the "A" and "B" slots. However, only the active slot's "scratch" will be
visible to the user (either through adb or fastboot).
Second, if one slot does not have dynamic partitions, flashing will
default to fixed partitions. For example, if the A slot is logical and B
is not, flashing "system_a" will be logical and "system_b" will be
fixed. This works no matter which slot is active. We do not try to
upgrade the inactive slot to dynamic partitions.
Bug: 116802789
Test: fastboot set_active a
fastboot flashall # dynamic partitions
fastboot getvar is-logical:system_a # true
fastboot getvar is-logical:system_b # false
fastboot set_active b
fastboot flashall --skip-secondary
fastboot getvar is-logical:system_a # true
fastboot getvar is-logical:system_b # true
Booting both slots works.
Change-Id: Ib3c91944aaee1a96b2f5ad69c90e215bd6c5a2e8
This is needed for update_engine to properly clean old partitions on
retrofit devices.
Bug: 119687874
Test: liblp_test gtest
Change-Id: Ida9483ad3c127e357f45789540ebbedc9d3d3883
This adds a new MetadataBuilder constructor, NewForUpdate, that can be
used by update_engine to simplify upgrading metadata. It is safe to call
whether or not the device is a retrofit. If the metadata has block
devices assigned to a specific slot, and that slot matches the slot
suffix, it will ensure that an equivalent entry exists for the alternate
slot.
Thus, if the source slot is _a and the target slot is _b, and the
metadata has "system_a" as a block device but not "system_b", this will
automatically add "system_b" as a block device.
Bug: 116802789
Test: liblp_test gtest
Change-Id: Ie89d4dbf4c708b5705e658220227ebf33fcb1930
On retrofit devices, an OTA package or super_empty.img won't know which
slot it applies to. This is not an issue on devices shipping with
dynamic partitions, since they ship on the "a" slot.
To work around this, partitions and block devices can be flagged as
"auto-slot-suffixed". This indicates that ReadMetadata should
automatically append a slot suffix before returning the metadata. This
flag is added by MetadataBuilder when requested, and will be enabled via
lpmake separately.
After ReadMetadata has applied slot suffixes, it takes care to remove
the slot-suffix flag. This prevents the suffix from being applied twice,
if for example the metadata is then imported into a MetadataBuilder.
Bug: 116802789
Test: liblp_test gtest
retrofit device boots
Change-Id: Ic7de06d31253a8d5b8d15c0d936175ca2939f857
When updating the super partition, attempt to preserve partitions from
the other slot. If any partition can't be preserved, fail and require a
wipe (-w) to proceed. This allows two bootable builds to be flashed to
both slots.
The preserve operation can fail if the metadata is not compatible with
the old partition layout. For example, if the partition references a
group that no longer exists, or a group changed its capacity, or the
metadata's block device list or list contents changed.
Bug: N/A
Test: liblp_test gtest
fastboot flashall --skip-secondary
Change-Id: I53fdd29bc1f0ef132005a93d3cf1cdcd7f2fc05f
This patch allows the block device table in LpMetadataHeader to contain
additional partitions. MetadataBuilder can now resize partitions such
that are allocated across block devices as needed, however, it attempts
to minimize this by grouping free regions by device.
Bug: 116802789
Test: liblp_test gtests
device with super partition flashes and boots
Change-Id: I9cf74c8925faf154703eeba2a26546a152efcaa2
This change introduces an IPartitionOpener abstraction. Methods that
interact with live metadata, such as ReadMetadata, UpdatePartitionTable,
and FlashPartitionTable, now require an IPartitionOpener object. Its
purpose is dependency injection: it will make these methods much easier
to test when the super partition spans multiple block devices.
All non-test consumers should be using PartitionOpener, and as such,
some helper methods have been added that automatically create one.
Bug: 116802789
Test: liblp_test gtest
device with super partition boots
Change-Id: I76725a5830ef643c5007c152c00ccaad8085151f
This patch removes the alignment, block device size, and starting sector
fields from LpGeometry into a new LpMetadataBlockDevice struct. The
metadata now contains a table of these structs, and the table will have
exactly one entry representing the super partition.
This refactoring will make it easier to have logical partitions span
multiple physical partitions. When that happens, the table will be
allowed to have more than one entry, and the first entry of the table
will be considered the "root" of the super partition.
Bug: 116802789
Test: liblp_test gtest
device with logical partitions flashes and boots
Change-Id: I97f23beac0363182cb6ae78ba2595860950afcf0
These will help update_engine clear the target slot before applying an OTA.
Bug: 117182932
Test: liblp_test gtest
Change-Id: I6ad370e617f22f2098245a0028a93488f9ac8674
In preparation for supporting multiple block devices, this factors out
the free-list calculation for resizing partitions.
Additionally, it fixes a bug where space in between the first usable
sector and the first extent wasn't added to the free list.
Bug: 116802789
Test: liblp_test gtest
Change-Id: I965760eef0176020e9a5691ce1be2c8b5e0c8bc8
Align the first usable sector to the logical block size, if no other
alignment was specified. This fixes a bunch of warnings during certain
gtests (ones with unaligned metadata sizes). The warnings were coming
from MetadataBuilder::GrowPartition() which expects the first sector
to always be block-aligned.
Bug: 116802789
Test: liblp_test gtest
Change-Id: I8dcf502aa4c2ba0674c5b4dcb77a274f300ff0a3
Traditionally the first 512 bytes of a partition can be interpreted as
an MBR. To prevent any compatibility issues, we explicitly zero the
first 4096 bytes of the super partition (one logical block, on most
systems).
Bug: 116802789
Test: liblp_test gtest
device with super partition flashes and boots
Change-Id: I29688ca75dbb52442f1464e8ab35893678a4f79e