Bug 1010669

Summary: bind-mount marked as MS_SLAVE cannot be converted to MS_SHARED.
Product: [Fedora] Fedora Reporter: Etsuji Nakai <enakai>
Component: kernelAssignee: Kernel Maintainer List <kernel-maint>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 19CC: gansalmon, itamar, jonathan, kernel-maint, madhu.chinakonda, marcelo.barbosa, skottler
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2013-09-26 00:16:38 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Attachments:
Description Flags
makeshift test code. none

Description Etsuji Nakai 2013-09-22 11:29:26 UTC
Created attachment 801183 [details]
makeshift test code.

Description of problem:

Once bind-mount point is marked as MS_SLAVE, it cannot be converted to MS_SHARED again.

For example,

  mount("/root/orig", "/root/bind", NULL, MS_BIND|MS_REC, NULL);
  mount(NULL, "/root/bind", NULL, MS_SLAVE|MS_REC, NULL);

This makes "/root/bind" a salve mount point, that is, additional bind-mount under /root/bind is not seen from /root/orig. After this operation,

  mount(NULL, "/root/bind", NULL, MS_SHARED, NULL)

I expect this will make "/root/bind" a shared mount point. But "/root/bind" still behaves as MS_SLAVE.

I checked this with the attached makeshift test code. The resulst is as below.

==============
# ./bindtest 
mount --bind /root/orig /root/bind
----
mark /root/bind as shared
mount --bind /tmp /root/bind/tmp
ls /root/orig/tmp   ### /root/bind/tmp can be seen from /root/orig/tmp as expected.
yum_save_tx.2013-09-22.04-53.Cu432Q.yumtx
----
mark /root/bind as slave
mount --bind /tmp /root/bind/tmp
ls /root/orig/tmp   ### /root/bind/tmp can't be seen from /root/orig/tmp as expected.
----
mark /root/bind as shared, again
mount --bind /tmp /root/bind/tmp
ls /root/orig/tmp   ### /root/bind/tmp can't be seen from /root/orig/tmp though it's marked as MS_SHARE
----
==============

Is this an intentional behavior of the kernel???

Version-Release number of selected component (if applicable):

# rpm -q kernel
kernel-3.9.5-301.fc19.x86_64
# rpm -q glibc
glibc-2.17-14.fc19.x86_64
# cat /etc/redhat-release 
Fedora release 19 (Schrödinger’s Cat)

Comment 1 Josh Boyer 2013-09-26 00:16:38 UTC
OK, so I spent some time looking at this today.  Essentially, your second call to make /root/bind shared is making it shared, but it doesn't clear the slave state.  What you wind up with is a mount that is in 'shared and slave' state.

Basically, that mount point will receive propagation events from it's master (in this case /root/orig), and it will forward propagation events to it's peer group and it's slaves.  It's peer group isn't the same group as it's master, so the master (/root/orig) doesn't receive mount events.

You can see the shared slave state and group info in /proc/self/mountinfo.  I've illustrated it below:

[root@hansolo ~]# mount --bind /root/orig /root/bind
[root@hansolo ~]# mount --make-shared /root/bind
[root@hansolo ~]# mount --bind /tmp /root/bind/tmp
[root@hansolo ~]# ls -l /root/orig/tmp
total 24
-rw------- 1 jwboyer jwboyer  939 Sep 23 08:24 krb5cc_500
drwx------ 2 gdm     gdm     4096 Sep 23 08:23 pulse-sXQxnhVNJ4r5
drwx------ 2 jwboyer jwboyer 4096 Sep 23 08:24 ssh-BnhXwo2226
drwx------ 2 jwboyer jwboyer 4096 Sep 25 14:31 ssh-DzXbh11272
drwx------ 2 jwboyer jwboyer 4096 Sep 17 08:47 ssh-feBoQ23013
drwx------ 2 jwboyer jwboyer 4096 Sep 23 08:22 ssh-mFlElp2103
[root@hansolo ~]# umount /root/bind/tmp
[root@hansolo ~]# mount --make-slave /root/bind
[root@hansolo ~]# mount --bind /tmp /root/bind/tmp
[root@hansolo ~]# ls /root/orig/tmp
[root@hansolo ~]# umount /root/bind/tmp
[root@hansolo ~]# mount --make-shared /root/bind
[root@hansolo ~]# mount --bind /tmp /root/bind/tmp
[root@hansolo ~]# ls /root/orig/tmp
[root@hansolo ~]# ls /root/bind/tmp
krb5cc_500          ssh-BnhXwo2226  ssh-feBoQ23013
pulse-sXQxnhVNJ4r5  ssh-DzXbh11272  ssh-mFlElp2103
[root@hansolo ~]# umount /root/bind/tmp

Everything up to this point is identical to your example.  Now we bind mount /tmp to /root/orig/tmp and we can see it in both /root/orig/tmp and /root/bind/tmp:

[root@hansolo ~]# mount --bind /tmp /root/orig/tmp
[root@hansolo ~]# ls /root/orig/tmp
krb5cc_500          ssh-BnhXwo2226  ssh-feBoQ23013
pulse-sXQxnhVNJ4r5  ssh-DzXbh11272  ssh-mFlElp2103
[root@hansolo ~]# ls /root/bind/tmp
krb5cc_500          ssh-BnhXwo2226  ssh-feBoQ23013
pulse-sXQxnhVNJ4r5  ssh-DzXbh11272  ssh-mFlElp2103
[root@hansolo ~]# umount /root/orig/tmp

Then if we look at mountinfo for the /root/* mounts:

[root@hansolo ~]# cat /proc/self/mountinfo | grep "/root"
48 21 8:3 /root/orig /root/bind rw,relatime shared:2 master:1 - ext3 /dev/sda3 rw,data=ordered
[root@hansolo ~]# 

We see that /root/bind is in shared slave mode, with the master being group 1 (or / in our example) and the shared peer group being 2.

If you want to make a slave mount go back to shared mode, and not shared slave, you can make it private and then make it shared again.  As far as I can tell, that is the only way to clear slave mode.

I think this is working as intended, and as documented for shared slave in Documentation/filesystems/sharedsubtrees.txt in the kernel source tree.  If you have further questions, I would recommend emailing the VFS maintainers and LKML with your example and I'm sure they'll be able to answer them more quickly than I can.