chiark / gitweb /
switch-root: remount to MS_PRIVATE
authorLennart Poettering <lennart@poettering.net>
Sat, 11 Aug 2012 23:29:41 +0000 (01:29 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 11 Aug 2012 23:31:03 +0000 (01:31 +0200)
The kernel does not allow switching roots if things are mounted
MS_SHARED. As a work-around, remount things MS_PRIVATE before switching
roots.

This should be fixed in the kernel for good.

https://bugzilla.redhat.com/show_bug.cgi?id=847418

src/core/shutdown.c
src/core/switch-root.c

index 0b7cbd8d3410e52ee13e7dca9877610a477b00a4..c3a4c390be2e20bf4f89ec291439cd212ed5bdac 100644 (file)
@@ -104,15 +104,14 @@ static int pivot_to_new_root(void) {
                 return -errno;
         }
 
-        /*
-          In case some evil process made "/" MS_SHARED
-          It works for pivot_root, but the ref count for the root device
-          is not decreasing :-/
-        */
-        if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0) {
-                log_error("Failed to make \"/\" private mount %m");
-                return -errno;
-        }
+        /* Work-around for a kernel bug: for some reason the kernel
+         * refuses switching root if any file systems are mounted
+         * MS_SHARED. Hence remount them MS_PRIVATE here as a
+         * work-around.
+         *
+         * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
+        if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
+                log_warning("Failed to make \"/\" private mount: %m");
 
         if (pivot_root(".", "oldroot") < 0) {
                 log_error("pivot failed: %m");
index 9832a520e4ac3f29d6ecfce0e85d181d826fcb3a..efc7d345e1a83ca28a861b69eda9b0ee92cac281 100644 (file)
@@ -56,6 +56,15 @@ int switch_root(const char *new_root) {
                 goto fail;
         }
 
+        /* Work-around for a kernel bug: for some reason the kernel
+         * refuses switching root if any file systems are mounted
+         * MS_SHARED. Hence remount them MS_PRIVATE here as a
+         * work-around.
+         *
+         * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
+        if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
+                log_warning("Failed to make \"/\" private mount: %m");
+
         NULSTR_FOREACH(i, move_mounts) {
                 char new_mount[PATH_MAX];
                 struct stat sb;