Merge "Fix logic to figure out what /data fstab entry was mounted"
am: 23a1dd630b
Change-Id: I13c1544963db2161f24d5f3d0f9c644838951ad1
This commit is contained in:
commit
89bc166320
4 changed files with 98 additions and 31 deletions
|
|
@ -1351,38 +1351,9 @@ int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetUserdataBlockDevice() {
|
|
||||||
Fstab fstab;
|
|
||||||
if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
|
|
||||||
LERROR << "Failed to read /proc/mounts";
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
auto entry = GetEntryForMountPoint(&fstab, "/data");
|
|
||||||
if (entry == nullptr) {
|
|
||||||
LERROR << "Didn't find /data mount point in /proc/mounts";
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return entry->blk_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
|
int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
|
||||||
const std::string& block_device = GetUserdataBlockDevice();
|
auto entry = GetMountedEntryForUserdata(fstab);
|
||||||
LINFO << "Userdata is mounted on " << block_device;
|
if (entry == nullptr) {
|
||||||
auto entry = std::find_if(fstab->begin(), fstab->end(), [&block_device](const FstabEntry& e) {
|
|
||||||
if (e.mount_point != "/data") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (e.blk_device == block_device) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
DeviceMapper& dm = DeviceMapper::Instance();
|
|
||||||
std::string path;
|
|
||||||
if (!dm.GetDmDevicePathByName("userdata", &path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return path == block_device;
|
|
||||||
});
|
|
||||||
if (entry == fstab->end()) {
|
|
||||||
LERROR << "Can't find /data in fstab";
|
LERROR << "Can't find /data in fstab";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ using android::base::EndsWith;
|
||||||
using android::base::ParseByteCount;
|
using android::base::ParseByteCount;
|
||||||
using android::base::ParseInt;
|
using android::base::ParseInt;
|
||||||
using android::base::ReadFileToString;
|
using android::base::ReadFileToString;
|
||||||
|
using android::base::Readlink;
|
||||||
using android::base::Split;
|
using android::base::Split;
|
||||||
using android::base::StartsWith;
|
using android::base::StartsWith;
|
||||||
|
|
||||||
|
|
@ -809,6 +810,89 @@ std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string ResolveBlockDevice(const std::string& block_device) {
|
||||||
|
if (!StartsWith(block_device, "/dev/block/")) {
|
||||||
|
LWARNING << block_device << " is not a block device";
|
||||||
|
return block_device;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
while (true) {
|
||||||
|
std::string slaves_dir = sys_dir + "/slaves";
|
||||||
|
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
|
||||||
|
if (!dir) {
|
||||||
|
LERROR << "Failed to open " << slaves_dir;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FstabEntry* GetMountedEntryForUserdata(Fstab* fstab) {
|
||||||
|
Fstab mounts;
|
||||||
|
if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
|
||||||
|
LERROR << "Failed to read /proc/mounts";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto mounted_entry = GetEntryForMountPoint(&mounts, "/data");
|
||||||
|
if (mounted_entry == nullptr) {
|
||||||
|
LWARNING << "/data is not mounted";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
std::string resolved_block_device = ResolveBlockDevice(mounted_entry->blk_device);
|
||||||
|
if (resolved_block_device.empty()) {
|
||||||
|
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;
|
||||||
|
block_device = entry.blk_device;
|
||||||
|
}
|
||||||
|
if (block_device == resolved_block_device) {
|
||||||
|
return &entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LERROR << "Didn't find entry that was used to mount /data";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::set<std::string> GetBootDevices() {
|
std::set<std::string> GetBootDevices() {
|
||||||
// First check the kernel commandline, then try the device tree otherwise
|
// First check the kernel commandline, then try the device tree otherwise
|
||||||
std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
|
std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ bool SkipMountingPartitions(Fstab* fstab);
|
||||||
FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
|
FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
|
||||||
// The Fstab can contain multiple entries for the same mount point with different configurations.
|
// The Fstab can contain multiple entries for the same mount point with different configurations.
|
||||||
std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path);
|
std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path);
|
||||||
|
FstabEntry* GetMountedEntryForUserdata(Fstab* fstab);
|
||||||
|
|
||||||
// This method builds DSU fstab entries and transfer the fstab.
|
// This method builds DSU fstab entries and transfer the fstab.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -969,3 +969,14 @@ TEST(fs_mgr, DefaultFstabContainsUserdata) {
|
||||||
ASSERT_NE(nullptr, GetEntryForMountPoint(&fstab, "/data"))
|
ASSERT_NE(nullptr, GetEntryForMountPoint(&fstab, "/data"))
|
||||||
<< "Default fstab doesn't contain /data entry";
|
<< "Default fstab doesn't contain /data entry";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(fs_mgr, UserdataMountedFromDefaultFstab) {
|
||||||
|
if (getuid() != 0) {
|
||||||
|
GTEST_SKIP() << "Must be run as root.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Fstab fstab;
|
||||||
|
ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab";
|
||||||
|
ASSERT_NE(nullptr, GetMountedEntryForUserdata(&fstab))
|
||||||
|
<< "/data wasn't mounted from default fstab";
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue