Blob Blame History Raw
From 06456e9d3235921c13e0e2f86a68e41a930aae0c Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Mon, 26 Oct 2015 15:13:28 +0100
Subject: [PATCH] unmount: Pass in mount options when remounting read-only

man 2 mount says that the mountflags and data parameteres should
match the original values except for the desired changes. We only
bother with the mount options since the only flags we can change
are MS_RDONLY, MS_SYNCHRONOUS and MS_MANDLOCK; which shouldn't
matter too much.

Fixes: #351

(cherry picked from commit 471b48ed2ff6539e7071ff4694c03483c5835639)

Related: #1312002
---
 src/core/umount.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/src/core/umount.c b/src/core/umount.c
index dd7df194de..bfd8aa5f88 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -28,6 +28,7 @@
 #include <linux/loop.h>
 #include <linux/dm-ioctl.h>
 
+#include "fstab-util.h"
 #include "list.h"
 #include "mount-setup.h"
 #include "umount.h"
@@ -39,6 +40,7 @@
 
 typedef struct MountPoint {
         char *path;
+        char *options;
         dev_t devnum;
         LIST_FIELDS(struct MountPoint, mount_point);
 } MountPoint;
@@ -71,7 +73,7 @@ static int mount_points_list_get(MountPoint **head) {
                 return -errno;
 
         for (i = 1;; i++) {
-                _cleanup_free_ char *path = NULL;
+                _cleanup_free_ char *path = NULL, *options = NULL;
                 char *p = NULL;
                 MountPoint *m;
                 int k;
@@ -82,15 +84,15 @@ static int mount_points_list_get(MountPoint **head) {
                            "%*s "       /* (3) major:minor */
                            "%*s "       /* (4) root */
                            "%ms "       /* (5) mount point */
-                           "%*s"        /* (6) mount options */
+                           "%*s"        /* (6) mount flags */
                            "%*[^-]"     /* (7) optional fields */
                            "- "         /* (8) separator */
                            "%*s "       /* (9) file system type */
                            "%*s"        /* (10) mount source */
-                           "%*s"        /* (11) mount options 2 */
+                           "%ms"        /* (11) mount options */
                            "%*[^\n]",   /* some rubbish at the end */
-                           &path);
-                if (k != 1) {
+                           &path, &options);
+                if (k != 2) {
                         if (k == EOF)
                                 break;
 
@@ -125,6 +127,9 @@ static int mount_points_list_get(MountPoint **head) {
                 }
 
                 m->path = p;
+                m->options = options;
+                options = NULL;
+
                 LIST_PREPEND(mount_point, *head, m);
         }
 
@@ -368,6 +373,14 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
                    benefits, but might confuse the host, as we remount
                    the superblock here, not the bind mound. */
                 if (detect_container(NULL) <= 0)  {
+                        _cleanup_free_ char *options = NULL;
+                        /* MS_REMOUNT requires that the data parameter
+                         * should be the same from the original mount
+                         * except for the desired changes. Since we want
+                         * to remount read-only, we should filter out
+                         * rw (and ro too, because it confuses the kernel) */
+                        (void) fstab_filter_options(m->options, "rw\0ro\0", NULL, NULL, &options);
+
                         /* We always try to remount directories
                          * read-only first, before we go on and umount
                          * them.
@@ -384,7 +397,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
                          * alias read-only we hence should be
                          * relatively safe regarding keeping the fs we
                          * can otherwise not see dirty. */
-                        mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
+                        log_info("Remounting '%s' read-only with options '%s'.", m->path, options);
+                        (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options);
                 }
 
                 /* Skip / and /usr since we cannot unmount that