fs_mgr: overlayfs skip mount points that are more specific
This is an optimization to limit us to an optimal set of overlay
mounts. If an entry is identical or more specific (eg: /vendor is
less specific than /vendor/firmware_file), then no need to craft an
override for it.
We do the check in the setup and mount_all paths.
Test: confirm on devices with more specific mounts they do not get override
Bug: 109821005
Change-Id: If34775455fc7989903f70bc4f075c948db91ce37
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 531610e..d6204e4 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -360,6 +360,34 @@
return false;
}
+std::vector<std::string> fs_mgr_candidate_list(const fstab* fstab,
+ const char* mount_point = nullptr) {
+ std::vector<std::string> mounts;
+ if (!fstab) return mounts;
+
+ for (auto i = 0; i < fstab->num_entries; i++) {
+ const auto fsrec = &fstab->recs[i];
+ if (!fs_mgr_wants_overlayfs(fsrec)) continue;
+ std::string new_mount_point(fs_mgr_mount_point(fstab, fsrec->mount_point));
+ if (mount_point && (new_mount_point != mount_point)) continue;
+ auto duplicate_or_more_specific = false;
+ for (auto it = mounts.begin(); it != mounts.end();) {
+ if ((*it == new_mount_point) ||
+ (android::base::StartsWith(new_mount_point, *it + "/"))) {
+ duplicate_or_more_specific = true;
+ break;
+ }
+ if (android::base::StartsWith(*it, new_mount_point + "/")) {
+ it = mounts.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point);
+ }
+ return mounts;
+}
+
} // namespace
bool fs_mgr_overlayfs_mount_all() {
@@ -371,10 +399,7 @@
fs_mgr_free_fstab);
if (!fstab) return ret;
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- if (!fs_mgr_wants_overlayfs(fsrec)) continue;
- std::string mount_point(fs_mgr_mount_point(fstab.get(), fsrec->mount_point));
+ for (const auto& mount_point : fs_mgr_candidate_list(fstab.get())) {
if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
}
@@ -399,20 +424,9 @@
std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
fs_mgr_free_fstab);
- std::vector<std::string> mounts;
- mount_point = fs_mgr_mount_point(fstab.get(), mount_point);
- if (fstab) {
- if (!fs_mgr_get_entry_for_mount_point(fstab.get(), kOverlayMountPoint)) return ret;
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- auto fsrec_mount_point = fs_mgr_mount_point(fstab.get(), fsrec->mount_point);
- if (!fsrec_mount_point) continue;
- if (mount_point && strcmp(fsrec_mount_point, mount_point)) continue;
- if (!fs_mgr_wants_overlayfs(fsrec)) continue;
- mounts.emplace_back(fsrec_mount_point);
- }
- if (mounts.empty()) return ret;
- }
+ if (fstab && !fs_mgr_get_entry_for_mount_point(fstab.get(), kOverlayMountPoint)) return ret;
+ auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(fstab.get(), mount_point));
+ if (fstab && mounts.empty()) return ret;
auto overlay = kOverlayMountPoint + "/overlay/";
auto save_errno = errno;