Loading fs_mgr/fs_mgr_overlayfs_mount.cpp +65 −41 Original line number Diff line number Diff line Loading @@ -381,54 +381,86 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { auto retval = true; struct move_entry { struct MoveEntry { std::string mount_point; std::string dir; bool shared_flag; }; std::vector<move_entry> move; std::vector<MoveEntry> moved_mounts; auto parent_private = false; auto parent_made_private = false; auto dev_private = false; auto dev_made_private = false; for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) { // There could be multiple mount entries with the same mountpoint. // Group these entries together with stable_sort, and keep only the last entry of a group. // Only move mount the last entry in an over mount group, because the other entries are // overshadowed and only the filesystem mounted with the last entry participates in file // pathname resolution. auto mountinfo = ReadMountinfoFromFile("/proc/self/mountinfo"); std::stable_sort(mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) { return lhs.mount_point < rhs.mount_point; }); std::reverse(mountinfo.begin(), mountinfo.end()); auto erase_from = std::unique( mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) { return lhs.mount_point == rhs.mount_point; }); mountinfo.erase(erase_from, mountinfo.end()); std::reverse(mountinfo.begin(), mountinfo.end()); // mountinfo is reversed twice, so still is in lexical sorted order. for (const auto& entry : mountinfo) { if ((entry.mount_point == mount_point) && !entry.shared_flag) { parent_private = true; } if ((entry.mount_point == "/dev") && !entry.shared_flag) { dev_private = true; } } // Need to make the original mountpoint MS_PRIVATE, so that the overlayfs can be MS_MOVE. // This could happen if its parent mount is remounted later. if (!parent_private) { parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false); } for (const auto& entry : mountinfo) { // Find all immediate submounts. if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) { continue; } if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) { return android::base::StartsWith(entry.mount_point, it.mount_point + "/"); }) != move.end()) { // Exclude duplicated or more specific entries. if (std::find_if(moved_mounts.begin(), moved_mounts.end(), [&entry](const auto& it) { return it.mount_point == entry.mount_point || android::base::StartsWith(entry.mount_point, it.mount_point + "/"); }) != moved_mounts.end()) { continue; } // mountinfo is in lexical order, so no need to worry about |entry| being a parent mount of // entries of |moved_mounts|. // use as the bound directory in /dev. MoveEntry new_entry{entry.mount_point, "/dev/TemporaryDir-XXXXXX", entry.shared_flag}; { AutoSetFsCreateCon createcon; auto new_context = fs_mgr_get_context(entry.mount_point); if (new_context.empty() || !createcon.Set(new_context)) { continue; } move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX", entry.shared_flag}; const auto target = mkdtemp(new_entry.dir.data()); if (!createcon.Restore()) { return false; } if (!target) { retval = false; PERROR << "temporary directory for MS_BIND"; PERROR << "temporary directory for MS_MOVE"; continue; } if (!parent_private && !parent_made_private) { parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false); if (!createcon.Restore()) { retval = false; rmdir(new_entry.dir.c_str()); continue; } } if (new_entry.shared_flag) { new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false); } Loading @@ -437,9 +469,10 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { if (new_entry.shared_flag) { fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true); } rmdir(new_entry.dir.c_str()); continue; } move.emplace_back(std::move(new_entry)); moved_mounts.push_back(std::move(new_entry)); } // hijack __mount() report format to help triage Loading @@ -463,7 +496,7 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { } // Move submounts back. for (const auto& entry : move) { for (const auto& entry : moved_mounts) { if (!dev_private && !dev_made_private) { dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false); } Loading Loading @@ -658,22 +691,13 @@ Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) { !fs_mgr_wants_overlayfs(&new_entry)) { continue; } auto new_mount_point = fs_mgr_mount_point(entry.mount_point); auto duplicate_or_more_specific = false; for (auto it = candidates.begin(); it != candidates.end();) { auto it_mount_point = fs_mgr_mount_point(it->mount_point); if ((it_mount_point == new_mount_point) || (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) { duplicate_or_more_specific = true; break; } if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) { it = candidates.erase(it); } else { ++it; } const auto new_mount_point = fs_mgr_mount_point(new_entry.mount_point); if (std::find_if(candidates.begin(), candidates.end(), [&](const auto& it) { return fs_mgr_mount_point(it.mount_point) == new_mount_point; }) != candidates.end()) { continue; } if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry)); candidates.push_back(std::move(new_entry)); } return candidates; } Loading fs_mgr/fs_mgr_remount.cpp +0 −19 Original line number Diff line number Diff line Loading @@ -88,17 +88,6 @@ const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) { return entry.mount_point; } const FstabEntry* GetWrappedEntry(const Fstab& overlayfs_candidates, const FstabEntry& entry) { auto mount_point = system_mount_point(entry); auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(), [&mount_point](const auto& entry) { return android::base::StartsWith(mount_point, system_mount_point(entry) + "/"); }); if (it == overlayfs_candidates.end()) return nullptr; return &(*it); } class MyLogger { public: explicit MyLogger(bool verbose) : verbose_(verbose) {} Loading Loading @@ -196,9 +185,6 @@ static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) { if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) { return candidate_entry->fs_type == entry.fs_type; } if (GetWrappedEntry(candidates, entry)) { return false; } return true; } Loading Loading @@ -252,11 +238,6 @@ bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fs } const FstabEntry* entry = &*it; if (auto wrap = GetWrappedEntry(candidates, *entry); wrap != nullptr) { LOG(INFO) << "partition " << arg << " covered by overlayfs for " << wrap->mount_point << ", switching"; entry = wrap; } // If it's already remounted, include it so it gets gracefully skipped // later on. Loading Loading
fs_mgr/fs_mgr_overlayfs_mount.cpp +65 −41 Original line number Diff line number Diff line Loading @@ -381,54 +381,86 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { auto retval = true; struct move_entry { struct MoveEntry { std::string mount_point; std::string dir; bool shared_flag; }; std::vector<move_entry> move; std::vector<MoveEntry> moved_mounts; auto parent_private = false; auto parent_made_private = false; auto dev_private = false; auto dev_made_private = false; for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) { // There could be multiple mount entries with the same mountpoint. // Group these entries together with stable_sort, and keep only the last entry of a group. // Only move mount the last entry in an over mount group, because the other entries are // overshadowed and only the filesystem mounted with the last entry participates in file // pathname resolution. auto mountinfo = ReadMountinfoFromFile("/proc/self/mountinfo"); std::stable_sort(mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) { return lhs.mount_point < rhs.mount_point; }); std::reverse(mountinfo.begin(), mountinfo.end()); auto erase_from = std::unique( mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) { return lhs.mount_point == rhs.mount_point; }); mountinfo.erase(erase_from, mountinfo.end()); std::reverse(mountinfo.begin(), mountinfo.end()); // mountinfo is reversed twice, so still is in lexical sorted order. for (const auto& entry : mountinfo) { if ((entry.mount_point == mount_point) && !entry.shared_flag) { parent_private = true; } if ((entry.mount_point == "/dev") && !entry.shared_flag) { dev_private = true; } } // Need to make the original mountpoint MS_PRIVATE, so that the overlayfs can be MS_MOVE. // This could happen if its parent mount is remounted later. if (!parent_private) { parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false); } for (const auto& entry : mountinfo) { // Find all immediate submounts. if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) { continue; } if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) { return android::base::StartsWith(entry.mount_point, it.mount_point + "/"); }) != move.end()) { // Exclude duplicated or more specific entries. if (std::find_if(moved_mounts.begin(), moved_mounts.end(), [&entry](const auto& it) { return it.mount_point == entry.mount_point || android::base::StartsWith(entry.mount_point, it.mount_point + "/"); }) != moved_mounts.end()) { continue; } // mountinfo is in lexical order, so no need to worry about |entry| being a parent mount of // entries of |moved_mounts|. // use as the bound directory in /dev. MoveEntry new_entry{entry.mount_point, "/dev/TemporaryDir-XXXXXX", entry.shared_flag}; { AutoSetFsCreateCon createcon; auto new_context = fs_mgr_get_context(entry.mount_point); if (new_context.empty() || !createcon.Set(new_context)) { continue; } move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX", entry.shared_flag}; const auto target = mkdtemp(new_entry.dir.data()); if (!createcon.Restore()) { return false; } if (!target) { retval = false; PERROR << "temporary directory for MS_BIND"; PERROR << "temporary directory for MS_MOVE"; continue; } if (!parent_private && !parent_made_private) { parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false); if (!createcon.Restore()) { retval = false; rmdir(new_entry.dir.c_str()); continue; } } if (new_entry.shared_flag) { new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false); } Loading @@ -437,9 +469,10 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { if (new_entry.shared_flag) { fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true); } rmdir(new_entry.dir.c_str()); continue; } move.emplace_back(std::move(new_entry)); moved_mounts.push_back(std::move(new_entry)); } // hijack __mount() report format to help triage Loading @@ -463,7 +496,7 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { } // Move submounts back. for (const auto& entry : move) { for (const auto& entry : moved_mounts) { if (!dev_private && !dev_made_private) { dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false); } Loading Loading @@ -658,22 +691,13 @@ Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) { !fs_mgr_wants_overlayfs(&new_entry)) { continue; } auto new_mount_point = fs_mgr_mount_point(entry.mount_point); auto duplicate_or_more_specific = false; for (auto it = candidates.begin(); it != candidates.end();) { auto it_mount_point = fs_mgr_mount_point(it->mount_point); if ((it_mount_point == new_mount_point) || (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) { duplicate_or_more_specific = true; break; } if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) { it = candidates.erase(it); } else { ++it; } const auto new_mount_point = fs_mgr_mount_point(new_entry.mount_point); if (std::find_if(candidates.begin(), candidates.end(), [&](const auto& it) { return fs_mgr_mount_point(it.mount_point) == new_mount_point; }) != candidates.end()) { continue; } if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry)); candidates.push_back(std::move(new_entry)); } return candidates; } Loading
fs_mgr/fs_mgr_remount.cpp +0 −19 Original line number Diff line number Diff line Loading @@ -88,17 +88,6 @@ const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) { return entry.mount_point; } const FstabEntry* GetWrappedEntry(const Fstab& overlayfs_candidates, const FstabEntry& entry) { auto mount_point = system_mount_point(entry); auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(), [&mount_point](const auto& entry) { return android::base::StartsWith(mount_point, system_mount_point(entry) + "/"); }); if (it == overlayfs_candidates.end()) return nullptr; return &(*it); } class MyLogger { public: explicit MyLogger(bool verbose) : verbose_(verbose) {} Loading Loading @@ -196,9 +185,6 @@ static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) { if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) { return candidate_entry->fs_type == entry.fs_type; } if (GetWrappedEntry(candidates, entry)) { return false; } return true; } Loading Loading @@ -252,11 +238,6 @@ bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fs } const FstabEntry* entry = &*it; if (auto wrap = GetWrappedEntry(candidates, *entry); wrap != nullptr) { LOG(INFO) << "partition " << arg << " covered by overlayfs for " << wrap->mount_point << ", switching"; entry = wrap; } // If it's already remounted, include it so it gets gracefully skipped // later on. Loading