From f495fe798b180345371beec82e4aa74c5feb0dea Mon Sep 17 00:00:00 2001 From: Nikita Ioffe Date: Fri, 6 Mar 2020 17:36:05 +0000 Subject: [PATCH] fs_mgr_get_mounted_entry_for_userdata: handle logical partitions In case of GSI on DSU, /data is mounted on the following stack: userdata -> userdata_gsi -> actual block device, and fstab returned from ReadDefaultFstab() function will say that /data should be mounted onto userdata_gsi. This configuration wasn't supported. To support it, fs_mgr_get_mounted_entry_for_userdata now unwinds the dm-device stack /data is mounted onto, and for each entry in fstab resolves corresponding block device (in case of logical partitions by asking DeviceMapper to resolve name -> path, and for other cases by reading a symlink), and then checking whenever resolved block device belongs to the unwinded stack. Test: on both normal boot & DSU Test: atest CtsUserspaceRebootHostSideTestCases Test: atest CtsFsMgrTestCases Bug: 148612148 Change-Id: I1bb3e64ae92d56de905b4f7f1997b7499b101b0f --- fs_mgr/fs_mgr.cpp | 78 ++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 2e46b4f87..d509e7153 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -1589,76 +1589,58 @@ static bool fs_mgr_unmount_all_data_mounts(const std::string& block_device) { } } -static std::string ResolveBlockDevice(const std::string& block_device) { +static bool UnwindDmDeviceStack(const std::string& block_device, + std::vector* dm_stack) { if (!StartsWith(block_device, "/dev/block/")) { LWARNING << block_device << " is not a block device"; - return block_device; + return false; } - std::string name = block_device.substr(5); - if (!StartsWith(name, "block/dm-")) { - // Not a dm-device, but might be a symlink. Optimistically try to readlink. - std::string result; - if (Readlink(block_device, &result)) { - return result; - } else if (errno == EINVAL) { - // After all, it wasn't a symlink. - return block_device; - } else { - LERROR << "Failed to readlink " << block_device; - return ""; - } - } - // It's a dm-device, let's find what's inside! - std::string sys_dir = "/sys/" + name; + std::string current = block_device; + DeviceMapper& dm = DeviceMapper::Instance(); while (true) { - std::string slaves_dir = sys_dir + "/slaves"; - std::unique_ptr dir(opendir(slaves_dir.c_str()), closedir); - if (!dir) { - LERROR << "Failed to open " << slaves_dir; - return ""; + dm_stack->push_back(current); + if (!dm.IsDmBlockDevice(current)) { + break; } - std::string sub_device_name = ""; - for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) { - if (entry->d_type != DT_LNK) continue; - if (!sub_device_name.empty()) { - LERROR << "Too many slaves in " << slaves_dir; - return ""; - } - sub_device_name = entry->d_name; + auto parent = dm.GetParentBlockDeviceByPath(current); + if (!parent) { + return false; } - if (sub_device_name.empty()) { - LERROR << "No slaves in " << slaves_dir; - return ""; - } - if (!StartsWith(sub_device_name, "dm-")) { - // Not a dm-device! We can stop now. - return "/dev/block/" + sub_device_name; - } - // Still a dm-device, keep digging. - sys_dir = "/sys/block/" + sub_device_name; + current = *parent; } + return true; } FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab, const FstabEntry& mounted_entry) { - std::string resolved_block_device = ResolveBlockDevice(mounted_entry.blk_device); - if (resolved_block_device.empty()) { + if (mounted_entry.mount_point != "/data") { + LERROR << mounted_entry.mount_point << " is not /data"; + return nullptr; + } + std::vector dm_stack; + if (!UnwindDmDeviceStack(mounted_entry.blk_device, &dm_stack)) { + LERROR << "Failed to unwind dm-device stack for " << mounted_entry.blk_device; return nullptr; } - LINFO << "/data is mounted on " << resolved_block_device; for (auto& entry : *fstab) { if (entry.mount_point != "/data") { continue; } std::string block_device; - if (!Readlink(entry.blk_device, &block_device)) { - LWARNING << "Failed to readlink " << entry.blk_device; + if (entry.fs_mgr_flags.logical) { + if (!fs_mgr_update_logical_partition(&entry)) { + LERROR << "Failed to update logic partition " << entry.blk_device; + continue; + } + block_device = entry.blk_device; + } else if (!Readlink(entry.blk_device, &block_device)) { + PWARNING << "Failed to read link " << entry.blk_device; block_device = entry.blk_device; } - if (block_device == resolved_block_device) { + if (std::find(dm_stack.begin(), dm_stack.end(), block_device) != dm_stack.end()) { return &entry; } } - LERROR << "Didn't find entry that was used to mount /data"; + LERROR << "Didn't find entry that was used to mount /data onto " << mounted_entry.blk_device; return nullptr; }