fs_mgr_overlayfs: Don't preemptively change mount propagation type
If the overlaid mount have no submount and is not submount of other
mount, then we don't need to change its propagation type.
This makes the remount process less disruptive as we create less
fragmented mount namespaces.
The general rule is still to always reboot after initial remount setup
to get the most predictable result.
Bug: 342967841
Test: adb_remount test
Change-Id: I19ca62018149f1fa81186824a9d7f1c32d9d6008
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
index a1ec63b..bd0fcfd 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -412,6 +412,8 @@
bool retval = true;
bool move_dir_shared = true;
bool parent_shared = true;
+ bool parent_have_parent = false;
+ bool parent_made_private = false;
bool root_shared = true;
bool root_made_private = false;
@@ -443,6 +445,10 @@
if (entry.mount_point == "/") {
root_shared = entry.shared_flag;
}
+ // Ignore "/" as we don't overlay "/" directly.
+ if (entry.mount_point != "/") {
+ parent_have_parent |= android::base::StartsWith(mount_point, entry.mount_point + "/");
+ }
}
// Precondition is that kMoveMountTempDir is MS_PRIVATE, otherwise don't try to move any
@@ -453,11 +459,13 @@
// 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 (!fs_mgr_overlayfs_set_shared_mount(mount_point, false)) {
- // If failed to set "/system" mount type, it might be due to "/system" not being a valid
- // mountpoint after switch root. Retry with "/" in this case.
- if (errno == EINVAL && mount_point == "/system") {
- root_made_private = fs_mgr_overlayfs_set_shared_mount("/", false);
+ if (parent_have_parent) {
+ parent_made_private |= fs_mgr_overlayfs_set_shared_mount(mount_point, false);
+ if (!parent_made_private && errno == EINVAL && mount_point == "/system") {
+ // If failed to set "/system" mount type, it might be due to "/system" not being a valid
+ // mountpoint after switch root. Retry with "/" in this case.
+ parent_made_private |= fs_mgr_overlayfs_set_shared_mount("/", false);
+ root_made_private |= parent_made_private;
}
}
@@ -496,6 +504,15 @@
continue;
}
}
+ if (!parent_made_private) {
+ parent_made_private |= fs_mgr_overlayfs_set_shared_mount(mount_point, false);
+ if (!parent_made_private && errno == EINVAL && mount_point == "/system") {
+ // If failed to set "/system" mount type, it might be due to "/system" not being a
+ // valid mountpoint after switch root. Retry with "/" in this case.
+ parent_made_private |= fs_mgr_overlayfs_set_shared_mount("/", false);
+ root_made_private |= parent_made_private;
+ }
+ }
if (new_entry.shared_flag) {
new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
@@ -524,7 +541,7 @@
rmdir(entry.dir.c_str());
}
// If the original (overridden) mount was MS_SHARED, then set the overlayfs mount to MS_SHARED.
- if (parent_shared) {
+ if (parent_shared && parent_made_private) {
fs_mgr_overlayfs_set_shared_mount(mount_point, true);
}
if (root_shared && root_made_private) {