From d14eb57377ad5799da18c59ae4a87cc682be2534 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Wed, 5 Dec 2018 10:19:48 -0800 Subject: [PATCH 1/3] fs_mgr: overlay: split out fs_mgr_overlayfs_make_scratch() Reduce some complexity in fs_mgr_overlayfs_setup_scratch() Test: adb-remount-test.sh Bug: 119885423 Change-Id: Ia158b6ed140a017fc2f5afb838482e0f8cba1222 --- fs_mgr/fs_mgr_overlayfs.cpp | 46 +++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index f2673e720..3a90f8bf7 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -652,10 +652,31 @@ std::string fs_mgr_overlayfs_scratch_device() { return scratch_device_cache = path; } +bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std::string& mnt_type) { + // Force mkfs by design for overlay support of adb remount, simplify and + // thus do not rely on fsck to correct problems that could creep in. + auto command = ""s; + if (mnt_type == "f2fs") { + command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint); + } else if (mnt_type == "ext4") { + command = kMkExt4 + " -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint; + } else { + errno = ESRCH; + LERROR << mnt_type << " has no mkfs cookbook"; + return false; + } + command += " " + scratch_device; + auto ret = system(command.c_str()); + if (ret) { + LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret; + return false; + } + return true; +} + // Create and mount kScratchMountPoint storage if we have logical partitions bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) { if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true; - auto mnt_type = fs_mgr_overlayfs_scratch_mount_type(); auto scratch_device = fs_mgr_overlayfs_scratch_device(); auto partition_create = !fs_mgr_rw_access(scratch_device); auto slot_number = fs_mgr_overlayfs_slot_number(); @@ -730,33 +751,18 @@ bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) { if (change) *change = true; } + // If the partition exists, assume first that it can be mounted. + auto mnt_type = fs_mgr_overlayfs_scratch_mount_type(); if (partition_exists) { if (fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type)) { if (change) *change = true; return true; } - // partition existed, but was not initialized; + // partition existed, but was not initialized; fall through to make it. errno = 0; } - // Force mkfs by design for overlay support of adb remount, simplify and - // thus do not rely on fsck to correct problems that could creep in. - auto command = ""s; - if (mnt_type == "f2fs") { - command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint); - } else if (mnt_type == "ext4") { - command = kMkExt4 + " -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint; - } else { - errno = ESRCH; - LERROR << mnt_type << " has no mkfs cookbook"; - return false; - } - command += " " + scratch_device; - auto ret = system(command.c_str()); - if (ret) { - LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret; - return false; - } + if (!fs_mgr_overlayfs_make_scratch(scratch_device, mnt_type)) return false; if (change) *change = true; From 13a66050709b71da26479c9d6803298dfbc02414 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Wed, 5 Dec 2018 10:45:06 -0800 Subject: [PATCH 2/3] fs_mgr: overlay: split out fs_mgr_overlayfs_create_scratch() Reduce some complexity in fs_mgr_overlayfs_setup_scratch() Test: adb-remount-test.sh Bug: 119885423 Change-Id: Idb769991f6342739c75654b1d42ab8f8633cbadf --- fs_mgr/fs_mgr_overlayfs.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index 3a90f8bf7..25b32c873 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -674,11 +674,11 @@ bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std: return true; } -// Create and mount kScratchMountPoint storage if we have logical partitions -bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) { - if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true; - auto scratch_device = fs_mgr_overlayfs_scratch_device(); - auto partition_create = !fs_mgr_rw_access(scratch_device); +bool fs_mgr_overlayfs_create_scratch(const fstab* fstab, std::string* scratch_device, + bool* partition_exists, bool* change) { + *scratch_device = fs_mgr_overlayfs_scratch_device(); + *partition_exists = fs_mgr_rw_access(*scratch_device); + auto partition_create = !*partition_exists; auto slot_number = fs_mgr_overlayfs_slot_number(); auto super_device = fs_mgr_overlayfs_super_device(slot_number); if (!fs_mgr_rw_access(super_device)) return false; @@ -690,9 +690,9 @@ bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) { } const auto partition_name = android::base::Basename(kScratchMountPoint); auto partition = builder->FindPartition(partition_name); - auto partition_exists = partition != nullptr; + *partition_exists = partition != nullptr; auto changed = false; - if (!partition_exists) { + if (!*partition_exists) { partition = builder->AddPartition(partition_name, LP_PARTITION_ATTR_NONE); if (!partition) { LERROR << "create " << partition_name; @@ -728,7 +728,7 @@ bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) { } if (!partition_create) DestroyLogicalPartition(partition_name, 10s); changed = true; - partition_exists = false; + *partition_exists = false; } } } @@ -745,11 +745,23 @@ bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) { if (changed || partition_create) { if (!CreateLogicalPartition(super_device, slot_number, partition_name, true, 0s, - &scratch_device)) + scratch_device)) return false; if (change) *change = true; } + return true; +} + +// Create and mount kScratchMountPoint storage if we have logical partitions +bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) { + if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true; + + std::string scratch_device; + bool partition_exists; + if (!fs_mgr_overlayfs_create_scratch(fstab, &scratch_device, &partition_exists, change)) { + return false; + } // If the partition exists, assume first that it can be mounted. auto mnt_type = fs_mgr_overlayfs_scratch_mount_type(); From f269312466621dcb636225fc4c80eb636649a3ee Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Mon, 26 Nov 2018 09:57:17 -0800 Subject: [PATCH 3/3] fs_mgr: overlay: use alternate for backing storage When we have multiple physical super partitions, it is prudent to take the alternate super physical partition in its raw entirety rather than to construct a logical partition out of the current super partition's limited remaining space. SideEffect: alternate boot partitions destroyed for the sake of debug Test: adb-remount-test.sh (including manually disabled to check both code paths). Bug: 119885423 Change-Id: I368d3a5619f69de3b0d1fcad73c4b42d25d0d969 --- fs_mgr/README.overlayfs.md | 6 +++++ fs_mgr/fs_mgr_overlayfs.cpp | 23 +++++++++++++---- fs_mgr/tests/adb-remount-test.sh | 42 +++++++++++++++++++++++--------- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md index 171936b5c..fbb5f5d62 100644 --- a/fs_mgr/README.overlayfs.md +++ b/fs_mgr/README.overlayfs.md @@ -95,6 +95,12 @@ Caveats multiple reasons. NB: This is not a problem for fastbootd or recovery as overrides are disabled for those special boot scenarios. +- For implementation simplicity on retrofit dynamic partition devices, + take the whole alternate super (eg: if "*a*" slot, then the whole of + "*system_b*"). + Since landing a filesystem on the alternate super physical device + without differentiating if it is setup to support logical or physical, + the alternate slot metadata and previous content will be lost. - If dynamic partitions runs out of space, resizing a logical partition larger may fail because of the scratch partition. If this happens, either fastboot flashall or adb enable-verity can diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index 25b32c873..fdfe1c036 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -386,8 +386,10 @@ uint32_t fs_mgr_overlayfs_slot_number() { return SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix()); } +const auto kPhysicalDevice = "/dev/block/by-name/"s; + std::string fs_mgr_overlayfs_super_device(uint32_t slot_number) { - return "/dev/block/by-name/" + fs_mgr_get_super_partition_name(slot_number); + return kPhysicalDevice + fs_mgr_get_super_partition_name(slot_number); } bool fs_mgr_overlayfs_has_logical(const fstab* fstab) { @@ -645,10 +647,16 @@ std::string fs_mgr_overlayfs_scratch_mount_type() { std::string fs_mgr_overlayfs_scratch_device() { if (!scratch_device_cache.empty()) return scratch_device_cache; - auto& dm = DeviceMapper::Instance(); - const auto partition_name = android::base::Basename(kScratchMountPoint); - std::string path; - if (!dm.GetDmDevicePathByName(partition_name, &path)) return ""; + // Is this a multiple super device (retrofit)? + auto slot_number = fs_mgr_overlayfs_slot_number(); + auto super_device = fs_mgr_overlayfs_super_device(slot_number); + auto path = fs_mgr_overlayfs_super_device(slot_number == 0); + if (super_device == path) { + // Create from within single super device; + auto& dm = DeviceMapper::Instance(); + const auto partition_name = android::base::Basename(kScratchMountPoint); + if (!dm.GetDmDevicePathByName(partition_name, &path)) return ""; + } return scratch_device_cache = path; } @@ -679,6 +687,10 @@ bool fs_mgr_overlayfs_create_scratch(const fstab* fstab, std::string* scratch_de *scratch_device = fs_mgr_overlayfs_scratch_device(); *partition_exists = fs_mgr_rw_access(*scratch_device); auto partition_create = !*partition_exists; + // Do we need to create a logical "scratch" partition? + if (!partition_create && android::base::StartsWith(*scratch_device, kPhysicalDevice)) { + return true; + } auto slot_number = fs_mgr_overlayfs_slot_number(); auto super_device = fs_mgr_overlayfs_super_device(slot_number); if (!fs_mgr_rw_access(super_device)) return false; @@ -784,6 +796,7 @@ bool fs_mgr_overlayfs_setup_scratch(const fstab* fstab, bool* change) { bool fs_mgr_overlayfs_scratch_can_be_mounted(const std::string& scratch_device) { if (scratch_device.empty()) return false; if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return false; + if (android::base::StartsWith(scratch_device, kPhysicalDevice)) return true; if (fs_mgr_rw_access(scratch_device)) return true; auto slot_number = fs_mgr_overlayfs_slot_number(); auto super_device = fs_mgr_overlayfs_super_device(slot_number); diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh index c7c86eb39..561debb86 100755 --- a/fs_mgr/tests/adb-remount-test.sh +++ b/fs_mgr/tests/adb-remount-test.sh @@ -378,6 +378,11 @@ fi M=`adb_sh cat /proc/mounts | sed -n 's@\([^ ]*\) /mnt/scratch \([^ ]*\) .*@\2 on \1@p'` [ -n "${M}" ] && echo "${BLUE}[ INFO ]${NORMAL} scratch filesystem ${M}" +uses_dynamic_scratch=true +if [ "${M}" != "${M##*/dev/block/by-name/}" ]; then + uses_dynamic_scratch=false + scratch_partition="${M##*/dev/block/by-name/}" +fi scratch_size=`adb_sh df -k /mnt/scratch /dev/null | while read device kblocks used available use mounted on; do if [ "/mnt/scratch" = "\${mounted}" ]; then @@ -453,16 +458,30 @@ echo "${GREEN}[ RUN ]${NORMAL} flash vendor, confirm its content disappears fastboot flash vendor || ( fastboot reboot && false) || die "fastboot flash vendor" -# check ${scratch_partition} via fastboot -fastboot_getvar partition-type:${scratch_partition} raw && - fastboot_getvar has-slot:${scratch_partition} no && - fastboot_getvar is-logical:${scratch_partition} yes || +fastboot_getvar partition-type:${scratch_partition} raw || ( fastboot reboot && false) || die "fastboot can not see ${scratch_partition} parameters" -echo "${BLUE}[ INFO ]${NORMAL} expect fastboot erase ${scratch_partition} to fail" >&2 -fastboot erase ${scratch_partition} && - ( fastboot reboot || true) && - die "fastboot can erase ${scratch_partition}" +if ${uses_dynamic_scratch}; then + # check ${scratch_partition} via fastboot + fastboot_getvar has-slot:${scratch_partition} no && + fastboot_getvar is-logical:${scratch_partition} yes || + ( fastboot reboot && false) || + die "fastboot can not see ${scratch_partition} parameters" +else + fastboot_getvar is-logical:${scratch_partition} no || + ( fastboot reboot && false) || + die "fastboot can not see ${scratch_partition} parameters" +fi +if ! ${uses_dynamic_scratch}; then + fastboot reboot-bootloader || + die "Reboot into fastboot" +fi +if ${uses_dynamic_scratch}; then + echo "${BLUE}[ INFO ]${NORMAL} expect fastboot erase ${scratch_partition} to fail" >&2 + fastboot erase ${scratch_partition} && + ( fastboot reboot || true) && + die "fastboot can erase ${scratch_partition}" +fi echo "${BLUE}[ INFO ]${NORMAL} expect fastboot format ${scratch_partition} to fail" >&2 fastboot format ${scratch_partition} && ( fastboot reboot || true) && @@ -507,12 +526,13 @@ check_eq "cat: /vendor/hello: No such file or directory" "${B}" after flash rm echo "${GREEN}[ RUN ]${NORMAL} test fastboot flash to ${scratch_partition}" >&2 -adb reboot-fastboot && - dd if=/dev/zero of=/tmp/adb-remount-test.img bs=4096 count=16 2>/dev/null && +adb reboot-fastboot || + die "Reboot into fastbootd" +dd if=/dev/zero of=/tmp/adb-remount-test.img bs=4096 count=16 2>/dev/null && fastboot_wait 2m || ( rm /tmp/adb-remount-test.img && false) || die "reboot into fastboot" -fastboot flash ${scratch_partition} /tmp/adb-remount-test.img +fastboot flash --force ${scratch_partition} /tmp/adb-remount-test.img err=${?} rm /tmp/adb-remount-test.img fastboot reboot ||