]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
mount: support multiple MS_PROPAGATION flags in one mount(8) exec
authorKarel Zak <kzak@redhat.com>
Tue, 15 Jan 2013 13:23:54 +0000 (14:23 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 15 Jan 2013 13:23:54 +0000 (14:23 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/mount.8
sys-utils/mount.c

index add9818fab52994f64c2191d09fdc8530ad2dfcc..7fd38df44861994c2977779397c0a29cb423d994 100644 (file)
@@ -458,14 +458,11 @@ of that mount such that mounts and umounts within any of the mirrors propagate
 to the other mirror. A slave mount receives propagation from its master, but
 any not vice-versa.  A private mount carries no propagation abilities.  A
 unbindable mount is a private mount which cannot be cloned through a bind
-operation. Detailed semantics is documented in Documentation/filesystems/sharedsubtree.txt
+operation. Detailed semantics is documented in
+.B Documentation/filesystems/sharedsubtree.txt
 file in the kernel source tree.
 
-Note that Linux kernel does not allow to change more propagation flags by one
-.BR mount (2)
-syscall and the flags cannot be mixed with another mount options. It means that
-more --make-* options cannot be used together or with another mount options.
-
+Supported operations:
 .RS
 .nf
 .BI "mount --make-shared " mountpoint
@@ -486,6 +483,41 @@ mounts under a given mountpoint.
 .BI "mount --make-runbindable " mountpoint
 .fi
 .RE
+
+.BR mount (8)
+.B does not read
+.BR fstab (5)
+when --make-* operation is requested. All necessary information has to be
+specified on command line.
+
+Note that Linux kernel does not allow to change more propagation flags by one
+.BR mount (2)
+syscall and the flags cannot be mixed with another mount options.
+
+Since util-linux 2.23 mount command allows to use more propagation flags
+together and with another mount operations. This feature is EXPERIMENTAL. In
+this case the propagation flags are applied by additional mount(2) syscalls
+after previous successful mount operation. Note that this use case is not
+atomic. The propagation flags is possible to specified in
+.BR fstab (5)
+as mount options
+(private,slave,shared,unbindable,rprivate,rslave,rshared,runbindable).
+
+For example
+.RS
+.nf
+.BI "mount --make-private --make-unbindable /dev/sda1 /A"
+.fi
+.RE
+
+is the same as
+.RS
+.nf
+.BI "mount /dev/sda1 /A"
+.BI "mount --make-private /A"
+.BI "mount --make-unbindable /A"
+.fi
+.RE
 .RE
 
 .SH COMMAND LINE OPTIONS
index fed96eb7bef9a492d9302892bd7af679f19ea417..0b57c92a04b48d330f4e1f59cf8d8296a665dfc9 100644 (file)
@@ -335,11 +335,14 @@ static int mk_exit_code(struct libmnt_context *cxt, int rc)
        const char *src = mnt_context_get_source(cxt);
 
 try_readonly:
-       if (mnt_context_helper_executed(cxt))
+       if (mnt_context_helper_executed(cxt)) {
                /*
                 * /sbin/mount.<type> called, return status
                 */
+               if (rc == -MNT_ERR_APPLYFLAGS)
+                       warnx(_("WARNING: failed to apply propagation flags"));
                return mnt_context_get_helper_status(cxt);
+       }
 
        if (rc == 0 && mnt_context_get_status(cxt) == 1) {
                /*
@@ -497,7 +500,7 @@ try_readonly:
        case EINVAL:
                if (mflags & MS_REMOUNT)
                        warnx(_("%s not mounted or bad option"), tgt);
-               else if (mflags & MS_PROPAGATION)
+               else if (rc == -MNT_ERR_APPLYFLAGS)
                        warnx(_("%s is not mountpoint or bad option"), tgt);
                else
                        warnx(_("wrong fs type, bad option, bad superblock on %s,\n"
@@ -635,6 +638,12 @@ static void sanitize_paths(struct libmnt_context *cxt)
        }
 }
 
+static void append_option(struct libmnt_context *cxt, const char *opt)
+{
+       if (mnt_context_append_options(cxt, opt))
+               err(MOUNT_EX_SYSERR, _("failed to append option '%s'"), opt);
+}
+
 static void __attribute__((__noreturn__)) usage(FILE *out)
 {
        fputs(USAGE_HEADER, out);
@@ -718,6 +727,7 @@ int main(int argc, char **argv)
        char *srcbuf = NULL;
        char *types = NULL;
        unsigned long oper = 0;
+       int propa = 0;
 
        enum {
                MOUNT_OPT_SHARED = CHAR_MAX + 1,
@@ -771,12 +781,7 @@ int main(int argc, char **argv)
        };
 
        static const ul_excl_t excl[] = {       /* rows and cols in in ASCII order */
-               { 'B','M','R',                  /* bind,move,rbind */
-                  MOUNT_OPT_SHARED,   MOUNT_OPT_SLAVE,
-                  MOUNT_OPT_PRIVATE,  MOUNT_OPT_UNBINDABLE,
-                  MOUNT_OPT_RSHARED,  MOUNT_OPT_RSLAVE,
-                  MOUNT_OPT_RPRIVATE, MOUNT_OPT_RUNBINDABLE },
-
+               { 'B','M','R' },                        /* bind,move,rbind */
                { 'L','U', MOUNT_OPT_SOURCE },  /* label,uuid,source */
                { 0 }
        };
@@ -830,8 +835,7 @@ int main(int argc, char **argv)
                        mnt_context_disable_mtab(cxt, TRUE);
                        break;
                case 'r':
-                       if (mnt_context_append_options(cxt, "ro"))
-                               err(MOUNT_EX_SYSERR, _("failed to append options"));
+                       append_option(cxt, "ro");
                        readwrite = 0;
                        break;
                case 'v':
@@ -841,13 +845,11 @@ int main(int argc, char **argv)
                        print_version();
                        break;
                case 'w':
-                       if (mnt_context_append_options(cxt, "rw"))
-                               err(MOUNT_EX_SYSERR, _("failed to append options"));
+                       append_option(cxt, "rw");
                        readwrite = 1;
                        break;
                case 'o':
-                       if (mnt_context_append_options(cxt, optarg))
-                               err(MOUNT_EX_SYSERR, _("failed to append options"));
+                       append_option(cxt, optarg);
                        break;
                case 'O':
                        if (mnt_context_set_options_pattern(cxt, optarg))
@@ -890,28 +892,36 @@ int main(int argc, char **argv)
                        oper |= (MS_BIND | MS_REC);
                        break;
                case MOUNT_OPT_SHARED:
-                       oper |= MS_SHARED;
+                       append_option(cxt, "shared");
+                       propa = 1;
                        break;
                case MOUNT_OPT_SLAVE:
-                       oper |= MS_SLAVE;
+                       append_option(cxt, "slave");
+                       propa = 1;
                        break;
                case MOUNT_OPT_PRIVATE:
-                       oper |= MS_PRIVATE;
+                       append_option(cxt, "private");
+                       propa = 1;
                        break;
                case MOUNT_OPT_UNBINDABLE:
-                       oper |= MS_UNBINDABLE;
+                       append_option(cxt, "unbindable");
+                       propa = 1;
                        break;
                case MOUNT_OPT_RSHARED:
-                       oper |= (MS_SHARED | MS_REC);
+                       append_option(cxt, "rshared");
+                       propa = 1;
                        break;
                case MOUNT_OPT_RSLAVE:
-                       oper |= (MS_SLAVE | MS_REC);
+                       append_option(cxt, "rslave");
+                       propa = 1;
                        break;
                case MOUNT_OPT_RPRIVATE:
-                       oper |= (MS_PRIVATE | MS_REC);
+                       append_option(cxt, "rprivate");
+                       propa = 1;
                        break;
                case MOUNT_OPT_RUNBINDABLE:
-                       oper |= (MS_UNBINDABLE | MS_REC);
+                       append_option(cxt, "runbindable");
+                       propa = 1;
                        break;
                case MOUNT_OPT_TARGET:
                        mnt_context_disable_swapmatch(cxt, 1);
@@ -944,7 +954,7 @@ int main(int argc, char **argv)
            !mnt_context_get_target(cxt) &&
            !argc &&
            !all) {
-               if (oper)
+               if (oper || mnt_context_get_options(cxt))
                        usage(stderr);
                print_all(cxt, types, show_labels);
                goto done;
@@ -1010,13 +1020,13 @@ int main(int argc, char **argv)
        if (mnt_context_is_restricted(cxt))
                sanitize_paths(cxt);
 
-       if (oper) {
-               /* MS_PROPAGATION operations, let's set the mount flags */
+       if (oper)
+               /* BIND/MOVE operations, let's set the mount flags */
                mnt_context_set_mflags(cxt, oper);
 
-               /* For -make* or --bind is fstab unnecessary */
+       if (oper || propa)
+               /* For --make-* or --bind is fstab unnecessary */
                mnt_context_set_optsmode(cxt, MNT_OMODE_NOTAB);
-       }
 
        rc = mnt_context_mount(cxt);
        rc = mk_exit_code(cxt, rc);