mount: support multiple MS_PROPAGATION flags in one mount(8) exec

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2013-01-15 14:23:54 +01:00
parent 6498ece0e7
commit be6904b92f
2 changed files with 75 additions and 33 deletions

View 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

View 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);