Skip to content

Commit

Permalink
liblp: Force 10.0 metadata on downgrade to Q.
Browse files Browse the repository at this point in the history
Q liblp only supports 10.0 super partition metadata, so
forcefully downgrade the current metadata version too.

On retrofit Virtual A/B devices, the metadata version is
at most 10.1, because the new VIRTUAL_AB flag is not set
on retrofit devices.

In version 10.1, two per-partition flags: UPDATED and DISABLED
are introduced.
- The updated flag is set when the device undergoes a Virtual A/B
update before. Clear it.
- The disabled flag should only be set on metadata files used by
libfiemap ImageManager. It shouldn't be used on super partition metadata.

Hence, this CL should only clear UPDATED flag.

Test: R->R->Q OTA
Bug: 159590481
Change-Id: I8b548c8ce36a75197e7172a77f9207fd44fe4670

Former-commit-id: ba5dfd76ded0502660e4cf695a4c249516adecdf
  • Loading branch information
Yifan Hong committed Jul 6, 2020
1 parent e09f8ea commit 99995cd
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 7 deletions.
17 changes: 12 additions & 5 deletions fs_mgr/liblp/builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,18 @@ std::unique_ptr<MetadataBuilder> MetadataBuilder::NewForUpdate(const IPartitionO
}
}

if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false) &&
!always_keep_source_slot) {
if (!UpdateMetadataForInPlaceSnapshot(metadata.get(), source_slot_number,
target_slot_number)) {
return nullptr;
if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false)) {
if (always_keep_source_slot) {
// always_keep_source_slot implies the target build does not support snapshots.
// Clear unsupported attributes.
SetMetadataHeaderV0(metadata.get());
} else {
// !always_keep_source_slot implies the target build supports snapshots. Do snapshot
// updates.
if (!UpdateMetadataForInPlaceSnapshot(metadata.get(), source_slot_number,
target_slot_number)) {
return nullptr;
}
}
}

Expand Down
6 changes: 4 additions & 2 deletions fs_mgr/liblp/include/liblp/builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,10 @@ class MetadataBuilder {
// metadata may not have the target slot's devices listed yet, in which
// case, it is automatically upgraded to include all available block
// devices.
// If |always_keep_source_slot| is set, on a Virtual A/B device, source slot
// partitions are kept. This is useful when applying a downgrade package.
// If |always_keep_source_slot| is set, on a Virtual A/B device
// - source slot partitions are kept.
// - UPDATED flag is cleared.
// This is useful when applying a downgrade package.
static std::unique_ptr<MetadataBuilder> NewForUpdate(const IPartitionOpener& opener,
const std::string& source_partition,
uint32_t source_slot_number,
Expand Down
39 changes: 39 additions & 0 deletions fs_mgr/liblp/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include <fcntl.h>
#include <inttypes.h>
#include <stdint.h>
#include <sys/stat.h>
#include <unistd.h>
Expand All @@ -29,6 +30,7 @@
#include <vector>

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <ext4_utils/ext4_utils.h>
#include <openssl/sha.h>

Expand Down Expand Up @@ -285,5 +287,42 @@ bool UpdateMetadataForInPlaceSnapshot(LpMetadata* metadata, uint32_t source_slot
return true;
}

inline std::string ToHexString(uint64_t value) {
return android::base::StringPrintf("0x%" PRIx64, value);
}

void SetMetadataHeaderV0(LpMetadata* metadata) {
if (metadata->header.minor_version <= LP_METADATA_MINOR_VERSION_MIN) {
return;
}
LINFO << "Forcefully setting metadata header version " << LP_METADATA_MAJOR_VERSION << "."
<< metadata->header.minor_version << " to " << LP_METADATA_MAJOR_VERSION << "."
<< LP_METADATA_MINOR_VERSION_MIN;
metadata->header.minor_version = LP_METADATA_MINOR_VERSION_MIN;
metadata->header.header_size = sizeof(LpMetadataHeaderV1_0);

// Retrofit Virtual A/B devices should have version 10.1, so flags shouldn't be set.
// Warn if this is the case, but zero it out anyways.
if (metadata->header.flags) {
LWARN << "Zeroing unexpected flags: " << ToHexString(metadata->header.flags);
}

// Zero out all fields beyond LpMetadataHeaderV0.
static_assert(sizeof(metadata->header) > sizeof(LpMetadataHeaderV1_0));
memset(reinterpret_cast<uint8_t*>(&metadata->header) + sizeof(LpMetadataHeaderV1_0), 0,
sizeof(metadata->header) - sizeof(LpMetadataHeaderV1_0));

// Clear partition attributes unknown to V0.
// On retrofit Virtual A/B devices, UPDATED flag may be set, so only log info here.
for (auto& partition : metadata->partitions) {
if (partition.attributes & ~LP_PARTITION_ATTRIBUTE_MASK_V0) {
LINFO << "Clearing " << GetPartitionName(partition)
<< " partition attribute: " << ToHexString(partition.attributes);
}

partition.attributes &= LP_PARTITION_ATTRIBUTE_MASK_V0;
}
}

} // namespace fs_mgr
} // namespace android
4 changes: 4 additions & 0 deletions fs_mgr/liblp/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ ::android::base::unique_fd GetControlFileOrOpen(std::string_view path, int flags
bool UpdateMetadataForInPlaceSnapshot(LpMetadata* metadata, uint32_t source_slot_number,
uint32_t target_slot_number);

// Forcefully set metadata header version to 1.0, clearing any incompatible flags and attributes
// so that when downgrading to a build with liblp V0, the device still boots.
void SetMetadataHeaderV0(LpMetadata* metadata);

} // namespace fs_mgr
} // namespace android

Expand Down

0 comments on commit 99995cd

Please sign in to comment.