diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index 05f3311cf..233706583 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -815,26 +815,72 @@ std::string fs_mgr_overlayfs_scratch_mount_type() { return "auto"; } -std::string fs_mgr_overlayfs_scratch_device() { - if (!scratch_device_cache.empty()) return scratch_device_cache; +enum class ScratchStrategy { + kNone, + // DAP device, use logical partitions. + kDynamicPartition, + // Retrofit DAP device, use super_. + kSuperOther, + // Pre-DAP device, uses the other slot. + kSystemOther +}; - // Is this a multiple super device (retrofit)? +static ScratchStrategy GetScratchStrategy(std::string* backing_device) { 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)) { - // non-DAP A/B device? - if (fs_mgr_access(super_device)) return ""; - auto other_slot = fs_mgr_get_other_slot_suffix(); - if (other_slot.empty()) return ""; - path = kPhysicalDevice + "system" + other_slot; + if (super_device != path) { + // Note: we do not check access() here, since in first-stage init we + // 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; + return ScratchStrategy::kSuperOther; + } + if (fs_mgr_access(super_device)) { + *backing_device = super_device; + return ScratchStrategy::kDynamicPartition; + } + + auto other_slot = fs_mgr_get_other_slot_suffix(); + if (!other_slot.empty()) { + path = kPhysicalDevice + "system" + other_slot; + if (fs_mgr_access(path)) { + *backing_device = path; + return ScratchStrategy::kSystemOther; } } - return scratch_device_cache = path; + return ScratchStrategy::kNone; +} + +// Return the scratch device if it exists. +static std::string GetScratchDevice() { + std::string device; + ScratchStrategy strategy = GetScratchStrategy(&device); + + switch (strategy) { + case ScratchStrategy::kSuperOther: + case ScratchStrategy::kSystemOther: + return device; + case ScratchStrategy::kDynamicPartition: { + auto& dm = DeviceMapper::Instance(); + auto partition_name = android::base::Basename(kScratchMountPoint); + if (dm.GetState(partition_name) != DmDeviceState::INVALID && + dm.GetDmDevicePathByName(partition_name, &device)) { + return device; + } + return ""; + } + default: + return ""; + } +} + +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) {