]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: add support for "bind,ro"
authorKarel Zak <kzak@redhat.com>
Mon, 17 Aug 2015 09:54:26 +0000 (11:54 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 17 Aug 2015 09:54:26 +0000 (11:54 +0200)
Now it's necessary t use two mount(8) calls to create a read-only
mount:

  mount /foo /bar -o bind
  mount /bar -o remount,ro,bind

This patch allows to specify "bind,ro" and the remount is done
automatically by libmount by additional mount(2) syscall. It's not
atomic of course.

Signed-off-by: Karel Zak <kzak@redhat.com>
Documentation/releases/v2.27-ReleaseNotes
libmount/src/context_mount.c
sys-utils/mount.8

index 44793220c5ddc631459d328c6f24767abef0a198..d537f7ef61445372e5304387b387f865a0bf5291 100644 (file)
@@ -9,6 +9,10 @@ new default unifies unshare behavior and makes it independent of distribution
 default. The unshare supports persistent namespaces too (no process has to run
 to keep namespace in existence).
 
+The command mount(8) supports read-only binds in one step by the options
+"bind,ro" (command line or fstab). This feature is implemented by additional
+remount mount(2) syscall and it is not atomic.
+
 The commands fdisk and sfdisk can be compiled with GNU readline support to
 improve their line-editing functionality.
 
index 63cba216b3122519add648be7db491827aae4480..9dadadf8ebd8037b2826b5533836cb29c463c135 100644 (file)
@@ -63,6 +63,10 @@ static int mnt_context_append_additional_mount(struct libmnt_context *cxt,
        return 0;
 }
 
+/*
+ * add additional mount(2) syscall requests when necessary to set propagation flags
+ * after regular mount(2).
+ */
 static int init_propagation(struct libmnt_context *cxt)
 {
        char *name;
@@ -102,6 +106,41 @@ static int init_propagation(struct libmnt_context *cxt)
        return 0;
 }
 
+/*
+ * add additional mount(2) syscall request to implement "ro,bind", the first regular
+ * mount(2) is the "bind" operation, the second is "remount,ro,bind" call.
+ *
+ * Note that we don't remove "ro" from the first syscall (kernel silently
+ * ignores this flags for bind operation) -- maybe one day kernel will support
+ * read-only binds in one step and then all will be done by the firts mount(2) and the
+ * second remount will be noop...
+ */
+static int init_robind(struct libmnt_context *cxt)
+{
+       struct libmnt_addmount *ad;
+       int rc;
+
+       assert(cxt);
+       assert(cxt->mountflags & MS_BIND);
+       assert(cxt->mountflags & MS_RDONLY);
+       assert(!(cxt->mountflags & MS_REMOUNT));
+
+       DBG(CXT, ul_debugobj(cxt, "mount: initialize additional ro,bind mount"));
+
+       ad = mnt_new_addmount();
+       if (!ad)
+               return -ENOMEM;
+
+       ad->mountflags = MS_REMOUNT | MS_BIND | MS_RDONLY;
+       if (cxt->mountflags & MS_REC)
+               ad->mountflags |= MS_REC;
+       rc = mnt_context_append_additional_mount(cxt, ad);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
 #if defined(HAVE_LIBSELINUX) || defined(HAVE_SMACK)
 struct libmnt_optname {
        const char *name;
@@ -214,6 +253,13 @@ static int fix_optstr(struct libmnt_context *cxt)
                if (rc)
                        return rc;
        }
+       if ((cxt->mountflags & MS_BIND)
+           && (cxt->mountflags & MS_RDONLY)
+           && !(cxt->mountflags & MS_REMOUNT)) {
+               rc = init_robind(cxt);
+               if (rc)
+                       return rc;
+       }
 
        next = fs->fs_optstr;
 
@@ -731,7 +777,7 @@ static int do_mount(struct libmnt_context *cxt, const char *try_type)
                                                        -cxt->syscall_status));
                        return -cxt->syscall_status;
                }
-               DBG(CXT, ul_debugobj(cxt, "mount(2) success"));
+               DBG(CXT, ul_debugobj(cxt, "  success"));
                cxt->syscall_status = 0;
 
                /*
index b439586540b3868d9042afd10cd07dbcce8c9881..8c0fd83d8b18ad4daca3a62e157aeb30494b40d3 100644 (file)
@@ -362,28 +362,25 @@ a second place by using:
 .RE
 
 Note that the filesystem mount options will remain the same as those
-on the original mount point, and cannot be changed by passing the
+on the original mount point.
+
+.BR mount(8)
+since v2.27 allow to change the options by passing the
 .B \-o
 option along with
-.BR \-\-bind / \-\-rbind .
-The mount options can be
-changed by a separate remount command, for example:
+.BR \-\-bind
+for example:
 
 .RS
 .br
-.B mount \-\-bind
-.I olddir newdir
-.br
-.B mount \-o remount,ro
-.I newdir
+.B mount \-\-bind,ro foo foo
 .RE
 
-Note that the behavior of the remount operation depends on the /etc/mtab file.
-The first command stores the 'bind' flag in the /etc/mtab file and the second
-command reads the flag from the file.  If you have a system without the
-/etc/mtab file or if you explicitly define source and target for the remount
-command (then \fBmount\fR(8) does not read /etc/mtab), then you have to use
-the bind flag (or option) for the remount command too.  For example:
+This feature is not supported by Linux kernel and it is implemented in userspace
+by additional remount mount(2) syscall. This solution is not atomic.
+
+The alternative (classic) way to create a read-only bind mount is to use remount
+operation, for example:
 
 .RS
 .br
@@ -394,14 +391,14 @@ the bind flag (or option) for the remount command too.  For example:
 .I olddir newdir
 .RE
 
-Note that
-.B remount,ro,bind
-will create a read-only mountpoint (VFS entry), but the original filesystem
-superblock will still be writable, meaning that the
+Note that read-only bind will create a read-only mountpoint (VFS entry), but the
+original filesystem superblock will still be writable, meaning that the
 .I olddir
 will be writable, but the
 .I newdir
 will be read-only.
+
+It's impossible to change mount options recursively (for example b \fB -o rbind,ro\fR).
 .RE
 
 .B The move operation.