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
This commit is contained in:
parent
bbbd1a8e41
commit
f495fe798b
1 changed files with 30 additions and 48 deletions
|
|
@ -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<std::string>* dm_stack) {
|
||||||
if (!StartsWith(block_device, "/dev/block/")) {
|
if (!StartsWith(block_device, "/dev/block/")) {
|
||||||
LWARNING << block_device << " is not a block device";
|
LWARNING << block_device << " is not a block device";
|
||||||
return block_device;
|
return false;
|
||||||
}
|
}
|
||||||
std::string name = block_device.substr(5);
|
std::string current = block_device;
|
||||||
if (!StartsWith(name, "block/dm-")) {
|
DeviceMapper& dm = DeviceMapper::Instance();
|
||||||
// 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;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
std::string slaves_dir = sys_dir + "/slaves";
|
dm_stack->push_back(current);
|
||||||
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
|
if (!dm.IsDmBlockDevice(current)) {
|
||||||
if (!dir) {
|
break;
|
||||||
LERROR << "Failed to open " << slaves_dir;
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
std::string sub_device_name = "";
|
auto parent = dm.GetParentBlockDeviceByPath(current);
|
||||||
for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
|
if (!parent) {
|
||||||
if (entry->d_type != DT_LNK) continue;
|
return false;
|
||||||
if (!sub_device_name.empty()) {
|
|
||||||
LERROR << "Too many slaves in " << slaves_dir;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
sub_device_name = entry->d_name;
|
|
||||||
}
|
}
|
||||||
if (sub_device_name.empty()) {
|
current = *parent;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab, const FstabEntry& mounted_entry) {
|
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 (mounted_entry.mount_point != "/data") {
|
||||||
if (resolved_block_device.empty()) {
|
LERROR << mounted_entry.mount_point << " is not /data";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
std::vector<std::string> dm_stack;
|
||||||
|
if (!UnwindDmDeviceStack(mounted_entry.blk_device, &dm_stack)) {
|
||||||
|
LERROR << "Failed to unwind dm-device stack for " << mounted_entry.blk_device;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
LINFO << "/data is mounted on " << resolved_block_device;
|
|
||||||
for (auto& entry : *fstab) {
|
for (auto& entry : *fstab) {
|
||||||
if (entry.mount_point != "/data") {
|
if (entry.mount_point != "/data") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::string block_device;
|
std::string block_device;
|
||||||
if (!Readlink(entry.blk_device, &block_device)) {
|
if (entry.fs_mgr_flags.logical) {
|
||||||
LWARNING << "Failed to readlink " << entry.blk_device;
|
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;
|
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;
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue