dd65c9
From 06456e9d3235921c13e0e2f86a68e41a930aae0c Mon Sep 17 00:00:00 2001
181b3f
From: Jan Janssen <medhefgo@web.de>
181b3f
Date: Mon, 26 Oct 2015 15:13:28 +0100
181b3f
Subject: [PATCH] unmount: Pass in mount options when remounting read-only
181b3f
181b3f
man 2 mount says that the mountflags and data parameteres should
181b3f
match the original values except for the desired changes. We only
181b3f
bother with the mount options since the only flags we can change
181b3f
are MS_RDONLY, MS_SYNCHRONOUS and MS_MANDLOCK; which shouldn't
181b3f
matter too much.
181b3f
181b3f
Fixes: #351
181b3f
181b3f
(cherry picked from commit 471b48ed2ff6539e7071ff4694c03483c5835639)
181b3f
181b3f
Related: #1312002
181b3f
---
181b3f
 src/core/umount.c | 26 ++++++++++++++++++++------
181b3f
 1 file changed, 20 insertions(+), 6 deletions(-)
181b3f
181b3f
diff --git a/src/core/umount.c b/src/core/umount.c
c62b8e
index dd7df194de..bfd8aa5f88 100644
181b3f
--- a/src/core/umount.c
181b3f
+++ b/src/core/umount.c
181b3f
@@ -28,6 +28,7 @@
181b3f
 #include <linux/loop.h>
181b3f
 #include <linux/dm-ioctl.h>
181b3f
 
181b3f
+#include "fstab-util.h"
181b3f
 #include "list.h"
181b3f
 #include "mount-setup.h"
181b3f
 #include "umount.h"
181b3f
@@ -39,6 +40,7 @@
181b3f
 
181b3f
 typedef struct MountPoint {
181b3f
         char *path;
181b3f
+        char *options;
181b3f
         dev_t devnum;
181b3f
         LIST_FIELDS(struct MountPoint, mount_point);
181b3f
 } MountPoint;
181b3f
@@ -71,7 +73,7 @@ static int mount_points_list_get(MountPoint **head) {
181b3f
                 return -errno;
181b3f
 
181b3f
         for (i = 1;; i++) {
181b3f
-                _cleanup_free_ char *path = NULL;
181b3f
+                _cleanup_free_ char *path = NULL, *options = NULL;
181b3f
                 char *p = NULL;
181b3f
                 MountPoint *m;
181b3f
                 int k;
181b3f
@@ -82,15 +84,15 @@ static int mount_points_list_get(MountPoint **head) {
181b3f
                            "%*s "       /* (3) major:minor */
181b3f
                            "%*s "       /* (4) root */
181b3f
                            "%ms "       /* (5) mount point */
181b3f
-                           "%*s"        /* (6) mount options */
181b3f
+                           "%*s"        /* (6) mount flags */
181b3f
                            "%*[^-]"     /* (7) optional fields */
181b3f
                            "- "         /* (8) separator */
181b3f
                            "%*s "       /* (9) file system type */
181b3f
                            "%*s"        /* (10) mount source */
181b3f
-                           "%*s"        /* (11) mount options 2 */
181b3f
+                           "%ms"        /* (11) mount options */
181b3f
                            "%*[^\n]",   /* some rubbish at the end */
181b3f
-                           &path);
181b3f
-                if (k != 1) {
181b3f
+                           &path, &options);
181b3f
+                if (k != 2) {
181b3f
                         if (k == EOF)
181b3f
                                 break;
181b3f
 
181b3f
@@ -125,6 +127,9 @@ static int mount_points_list_get(MountPoint **head) {
181b3f
                 }
181b3f
 
181b3f
                 m->path = p;
181b3f
+                m->options = options;
181b3f
+                options = NULL;
181b3f
+
181b3f
                 LIST_PREPEND(mount_point, *head, m);
181b3f
         }
181b3f
 
181b3f
@@ -368,6 +373,14 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
181b3f
                    benefits, but might confuse the host, as we remount
181b3f
                    the superblock here, not the bind mound. */
181b3f
                 if (detect_container(NULL) <= 0)  {
181b3f
+                        _cleanup_free_ char *options = NULL;
181b3f
+                        /* MS_REMOUNT requires that the data parameter
181b3f
+                         * should be the same from the original mount
181b3f
+                         * except for the desired changes. Since we want
181b3f
+                         * to remount read-only, we should filter out
181b3f
+                         * rw (and ro too, because it confuses the kernel) */
181b3f
+                        (void) fstab_filter_options(m->options, "rw\0ro\0", NULL, NULL, &options);
181b3f
+
181b3f
                         /* We always try to remount directories
181b3f
                          * read-only first, before we go on and umount
181b3f
                          * them.
181b3f
@@ -384,7 +397,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
181b3f
                          * alias read-only we hence should be
181b3f
                          * relatively safe regarding keeping the fs we
181b3f
                          * can otherwise not see dirty. */
181b3f
-                        mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
181b3f
+                        log_info("Remounting '%s' read-only with options '%s'.", m->path, options);
181b3f
+                        (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options);
181b3f
                 }
181b3f
 
181b3f
                 /* Skip / and /usr since we cannot unmount that