From a3bf8478a3b40a7a205c829162102bc3dffd4428 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 10 Dec 2019 20:43:40 -0800 Subject: [PATCH 1/3] remount: Do not run the create-scratch logic on older devices. The prologue of fs_mgr_overlayfs_create_scratch() will implicitly succeed on physical block devices, and implicitly fail if for some reason they can't be accessed. This patch makes the success and failure cases explicit. The logic specific to DAP has been moved to CreateDynamicScratch. fs_mgr_overlayfs_create_scratch now calls GetScratchStrategy, and only calls CreateDynamicScratch for DAP-launch devices. In the case a physical block device can be used, no action is taken. Bug: 134949511 Test: adb remount and adb_remount_test.sh Change-Id: I0af7cda9bc551416c9e2ffca5a36305f89d3bf46 --- fs_mgr/fs_mgr_overlayfs.cpp | 46 ++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index 233706583..a2fe22e5c 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -825,7 +825,8 @@ enum class ScratchStrategy { kSystemOther }; -static ScratchStrategy GetScratchStrategy(std::string* backing_device) { +// Return the strategy this device must use for creating a scratch partition. +static ScratchStrategy GetScratchStrategy(std::string* backing_device = nullptr) { 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); @@ -834,11 +835,11 @@ static ScratchStrategy GetScratchStrategy(std::string* backing_device) { // wouldn't have registed by-name symlinks for the device as it's // normally not needed. The access checks elsewhere in this function // are safe because system/super are always required. - *backing_device = path; + if (backing_device) *backing_device = path; return ScratchStrategy::kSuperOther; } if (fs_mgr_access(super_device)) { - *backing_device = super_device; + if (backing_device) *backing_device = super_device; return ScratchStrategy::kDynamicPartition; } @@ -846,7 +847,7 @@ static ScratchStrategy GetScratchStrategy(std::string* backing_device) { if (!other_slot.empty()) { path = kPhysicalDevice + "system" + other_slot; if (fs_mgr_access(path)) { - *backing_device = path; + if (backing_device) *backing_device = path; return ScratchStrategy::kSystemOther; } } @@ -924,16 +925,15 @@ static void TruncatePartitionsWithSuffix(MetadataBuilder* builder, const std::st } } -// This is where we find and steal backing storage from the system. -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); +// Create or update a scratch partition within super. +static bool CreateDynamicScratch(const Fstab& fstab, std::string* scratch_device, + bool* partition_exists, bool* change) { + const auto partition_name = android::base::Basename(kScratchMountPoint); + + auto& dm = DeviceMapper::Instance(); + *partition_exists = dm.GetState(partition_name) != DmDeviceState::INVALID; + 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; @@ -943,7 +943,6 @@ bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_de LERROR << "open " << super_device << " metadata"; return false; } - const auto partition_name = android::base::Basename(kScratchMountPoint); auto partition = builder->FindPartition(partition_name); *partition_exists = partition != nullptr; auto changed = false; @@ -1024,6 +1023,25 @@ bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_de return true; } +bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_device, + bool* partition_exists, bool* change) { + auto strategy = GetScratchStrategy(); + if (strategy == ScratchStrategy::kDynamicPartition) { + return CreateDynamicScratch(fstab, scratch_device, partition_exists, change); + } + + // The scratch partition can only be landed on a physical partition if we + // get here. If there are no viable candidates that are R/W, just return + // that there is no device. + *scratch_device = GetScratchDevice(); + if (scratch_device->empty()) { + errno = ENXIO; + return false; + } + *partition_exists = 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; From 43d9f1833fd79d9fef8b7847f9aeb27b4d51fa6f Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 10 Dec 2019 21:18:28 -0800 Subject: [PATCH 2/3] remount: Refactor fs_mgr_overlayfs_teardown This pulls code for mapping the scratch device into a separate function. It also avoids implicitly failing by passing an empty device string. Finally, it calls GetScratchDevice, to remove a caller of the deprecated method fs_mgr_overlayfs_scratch_device(). Bug: 134949511 Test: adb remount and adb_remount_test.sh Change-Id: If4a543d3fa26af3f8578ec8b236859c8e4d9bfd8 --- fs_mgr/fs_mgr_overlayfs.cpp | 38 ++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index a2fe22e5c..e236d79e1 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -1252,6 +1252,27 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* return ret; } +static bool GetAndMapScratchDeviceIfNeeded(std::string* device) { + *device = GetScratchDevice(); + if (!device->empty()) { + return true; + } + + auto strategy = GetScratchStrategy(); + if (strategy == ScratchStrategy::kDynamicPartition) { + auto metadata_slot = fs_mgr_overlayfs_slot_number(); + CreateLogicalPartitionParams params = { + .block_device = fs_mgr_overlayfs_super_device(metadata_slot), + .metadata_slot = metadata_slot, + .partition_name = android::base::Basename(kScratchMountPoint), + .force_writable = true, + .timeout_ms = 10s, + }; + return CreateLogicalPartition(params, device); + } + return false; +} + // Returns false if teardown not permitted, errno set to last error. // If something is altered, set *change. bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { @@ -1261,20 +1282,11 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { // specific override entries. auto mount_scratch = false; if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) { - auto scratch_device = fs_mgr_overlayfs_scratch_device(); - if (scratch_device.empty()) { - auto metadata_slot = fs_mgr_overlayfs_slot_number(); - CreateLogicalPartitionParams params = { - .block_device = fs_mgr_overlayfs_super_device(metadata_slot), - .metadata_slot = metadata_slot, - .partition_name = android::base::Basename(kScratchMountPoint), - .force_writable = true, - .timeout_ms = 10s, - }; - CreateLogicalPartition(params, &scratch_device); + std::string scratch_device; + if (GetAndMapScratchDeviceIfNeeded(&scratch_device)) { + mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device, + fs_mgr_overlayfs_scratch_mount_type()); } - mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device, - fs_mgr_overlayfs_scratch_mount_type()); } for (const auto& overlay_mount_point : kOverlayMountPoints) { ret &= fs_mgr_overlayfs_teardown_one( From 2d79a4365ee9aa80eac032e7f4228bbc5a908b33 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 10 Dec 2019 21:09:39 -0800 Subject: [PATCH 3/3] remount: Remove fs_mgr_overlayfs_scratch_device() This is no longer needed now that GetScratchDevice exists. The cache can go away too, since it only existed to avoid libdm spam. The spam is avoided by checking GetState before calling GetDmDevicePathByName. Bug: 134949511 Test: adb remount and adb_remount_test.sh Change-Id: I9d94e2523af9de394a811d0b398fe20415708a6b --- fs_mgr/fs_mgr_overlayfs.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index e236d79e1..27971da7d 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -440,13 +440,9 @@ void fs_mgr_overlayfs_umount_scratch() { rmdir(kScratchMountPoint.c_str()); } -// reduce 'DM_DEV_STATUS failed for scratch: No such device or address' noise -std::string scratch_device_cache; - bool fs_mgr_overlayfs_teardown_scratch(const std::string& overlay, bool* change) { // umount and delete kScratchMountPoint storage if we have logical partitions if (overlay != kScratchMountPoint) return true; - scratch_device_cache.erase(); 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 true; @@ -877,13 +873,6 @@ static std::string GetScratchDevice() { } } -std::string fs_mgr_overlayfs_scratch_device() { - if (!scratch_device_cache.empty()) return scratch_device_cache; - - scratch_device_cache = GetScratchDevice(); - return scratch_device_cache; -} - 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. @@ -1131,7 +1120,7 @@ Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) { } static void TryMountScratch() { - auto scratch_device = fs_mgr_overlayfs_scratch_device(); + auto scratch_device = GetScratchDevice(); if (!fs_mgr_overlayfs_scratch_can_be_mounted(scratch_device)) { return; } @@ -1180,7 +1169,7 @@ std::vector fs_mgr_overlayfs_required_devices(Fstab* fstab) { for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) { if (fs_mgr_is_verity_enabled(entry)) continue; if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) continue; - auto device = fs_mgr_overlayfs_scratch_device(); + auto device = GetScratchDevice(); if (!fs_mgr_overlayfs_scratch_can_be_mounted(device)) break; return {device}; }