summaryrefslogtreecommitdiffstats
path: root/libmount/src/context_mount.c
diff options
context:
space:
mode:
authorKarel Zak2018-06-01 12:16:19 +0200
committerKarel Zak2018-06-01 12:16:19 +0200
commit816773b475900909d42c2c8282a6ac50252cac22 (patch)
tree94a7673aae55f11bc0c28aa16dd393b2e4e1162a /libmount/src/context_mount.c
parentmount: use internally string to set move/bind operations (diff)
downloadkernel-qcow2-util-linux-816773b475900909d42c2c8282a6ac50252cac22.tar.gz
kernel-qcow2-util-linux-816773b475900909d42c2c8282a6ac50252cac22.tar.xz
kernel-qcow2-util-linux-816773b475900909d42c2c8282a6ac50252cac22.zip
libmount: improve MS_REC usage
libmount allows to split one library (mount(8)) call to multiple mount(2) syscalls, for example --rbind --make-rslave in this case we have to be careful with MS_REC because the flag is applied to multiple operations. # strace -e mount mount --rbind --make-rslave /mnt/A /mnt/B Old version: mount("/mnt/A", "/mnt/B", 0x13ecac0, MS_MGC_VAL|MS_BIND, NULL) = 0 mount("none", "/mnt/B", NULL, MS_REC|MS_SLAVE, NULL) = 0 Fixed version: mount("/mnt/A", "/mnt/B", 0x1f22ac0, MS_MGC_VAL|MS_BIND|MS_REC, NULL) = 0 mount("none", "/mnt/B", NULL, MS_REC|MS_SLAVE, NULL) = 0 Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1584443 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libmount/src/context_mount.c')
-rw-r--r--libmount/src/context_mount.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c
index b88e60507..a8e84127c 100644
--- a/libmount/src/context_mount.c
+++ b/libmount/src/context_mount.c
@@ -73,6 +73,7 @@ static int init_propagation(struct libmnt_context *cxt)
char *opts = (char *) mnt_fs_get_vfs_options(cxt->fs);
size_t namesz;
struct libmnt_optmap const *maps[1];
+ int rec_count = 0;
if (!opts)
return 0;
@@ -86,9 +87,19 @@ static int init_propagation(struct libmnt_context *cxt)
struct libmnt_addmount *ad;
int rc;
- if (!mnt_optmap_get_entry(maps, 1, name, namesz, &ent)
- || !ent
- || !(ent->id & MS_PROPAGATION))
+ if (!mnt_optmap_get_entry(maps, 1, name, namesz, &ent) || !ent)
+ continue;
+
+ DBG(CXT, ul_debugobj(cxt, " checking %s", ent->name));
+
+ /* Note that MS_REC may be used for more flags, so we have to keep
+ * track about number of recursive options to keep the MS_REC in the
+ * mountflags if necessary.
+ */
+ if (ent->id & MS_REC)
+ rec_count++;
+
+ if (!(ent->id & MS_PROPAGATION))
continue;
ad = mnt_new_addmount();
@@ -96,13 +107,21 @@ static int init_propagation(struct libmnt_context *cxt)
return -ENOMEM;
ad->mountflags = ent->id;
+ DBG(CXT, ul_debugobj(cxt, " adding extra mount(2) call for %s", ent->name));
rc = mnt_context_append_additional_mount(cxt, ad);
if (rc)
return rc;
+ DBG(CXT, ul_debugobj(cxt, " removing %s from primary mount(2) call", ent->name));
cxt->mountflags &= ~ent->id;
+
+ if (ent->id & MS_REC)
+ rec_count--;
}
+ if (rec_count)
+ cxt->mountflags |= MS_REC;
+
return 0;
}