aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRam Pai <linuxram@us.ibm.com>2005-11-07 17:20:48 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 21:18:11 -0500
commita58b0eb8e64b78d9315a5491955e78b1391d42e5 (patch)
tree546f77cb0338c817ef1e34d8ebbc6eaf0e5d6be9 /fs
parenta05964f3917c7c55368c229d7985f8e7c9977e97 (diff)
[PATCH] introduce slave mounts
A slave mount always has a master mount from which it receives mount/umount events. Unlike shared mount the event propagation does not flow from the slave mount to the master. Signed-off-by: Ram Pai <linuxram@us.ibm.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/namespace.c4
-rw-r--r--fs/pnode.c54
-rw-r--r--fs/pnode.h2
3 files changed, 56 insertions, 4 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 4b1af01c2fb4..46f99bc585bd 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -67,6 +67,8 @@ struct vfsmount *alloc_vfsmnt(const char *name)
67 INIT_LIST_HEAD(&mnt->mnt_list); 67 INIT_LIST_HEAD(&mnt->mnt_list);
68 INIT_LIST_HEAD(&mnt->mnt_expire); 68 INIT_LIST_HEAD(&mnt->mnt_expire);
69 INIT_LIST_HEAD(&mnt->mnt_share); 69 INIT_LIST_HEAD(&mnt->mnt_share);
70 INIT_LIST_HEAD(&mnt->mnt_slave_list);
71 INIT_LIST_HEAD(&mnt->mnt_slave);
70 if (name) { 72 if (name) {
71 int size = strlen(name) + 1; 73 int size = strlen(name) + 1;
72 char *newname = kmalloc(size, GFP_KERNEL); 74 char *newname = kmalloc(size, GFP_KERNEL);
@@ -1243,7 +1245,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
1243 data_page); 1245 data_page);
1244 else if (flags & MS_BIND) 1246 else if (flags & MS_BIND)
1245 retval = do_loopback(&nd, dev_name, flags & MS_REC); 1247 retval = do_loopback(&nd, dev_name, flags & MS_REC);
1246 else if (flags & (MS_SHARED | MS_PRIVATE)) 1248 else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
1247 retval = do_change_type(&nd, flags); 1249 retval = do_change_type(&nd, flags);
1248 else if (flags & MS_MOVE) 1250 else if (flags & MS_MOVE)
1249 retval = do_move_mount(&nd, dev_name); 1251 retval = do_move_mount(&nd, dev_name);
diff --git a/fs/pnode.c b/fs/pnode.c
index 7bc942d047cd..f73eba24f1d1 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -17,13 +17,61 @@ static inline struct vfsmount *next_peer(struct vfsmount *p)
17 return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); 17 return list_entry(p->mnt_share.next, struct vfsmount, mnt_share);
18} 18}
19 19
20static int do_make_slave(struct vfsmount *mnt)
21{
22 struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master;
23 struct vfsmount *slave_mnt;
24
25 /*
26 * slave 'mnt' to a peer mount that has the
27 * same root dentry. If none is available than
28 * slave it to anything that is available.
29 */
30 while ((peer_mnt = next_peer(peer_mnt)) != mnt &&
31 peer_mnt->mnt_root != mnt->mnt_root) ;
32
33 if (peer_mnt == mnt) {
34 peer_mnt = next_peer(mnt);
35 if (peer_mnt == mnt)
36 peer_mnt = NULL;
37 }
38 list_del_init(&mnt->mnt_share);
39
40 if (peer_mnt)
41 master = peer_mnt;
42
43 if (master) {
44 list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave)
45 slave_mnt->mnt_master = master;
46 list_del(&mnt->mnt_slave);
47 list_add(&mnt->mnt_slave, &master->mnt_slave_list);
48 list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev);
49 INIT_LIST_HEAD(&mnt->mnt_slave_list);
50 } else {
51 struct list_head *p = &mnt->mnt_slave_list;
52 while (!list_empty(p)) {
53 slave_mnt = list_entry(p->next,
54 struct vfsmount, mnt_slave);
55 list_del_init(&slave_mnt->mnt_slave);
56 slave_mnt->mnt_master = NULL;
57 }
58 }
59 mnt->mnt_master = master;
60 CLEAR_MNT_SHARED(mnt);
61 INIT_LIST_HEAD(&mnt->mnt_slave_list);
62 return 0;
63}
64
20void change_mnt_propagation(struct vfsmount *mnt, int type) 65void change_mnt_propagation(struct vfsmount *mnt, int type)
21{ 66{
22 if (type == MS_SHARED) { 67 if (type == MS_SHARED) {
23 set_mnt_shared(mnt); 68 set_mnt_shared(mnt);
24 } else { 69 return;
25 list_del_init(&mnt->mnt_share); 70 }
26 mnt->mnt_flags &= ~MNT_PNODE_MASK; 71 do_make_slave(mnt);
72 if (type != MS_SLAVE) {
73 list_del_init(&mnt->mnt_slave);
74 mnt->mnt_master = NULL;
27 } 75 }
28} 76}
29 77
diff --git a/fs/pnode.h b/fs/pnode.h
index 9b88ba06794a..b59f0e9fe6b1 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -12,10 +12,12 @@
12#include <linux/mount.h> 12#include <linux/mount.h>
13 13
14#define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) 14#define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED)
15#define IS_MNT_SLAVE(mnt) (mnt->mnt_master)
15#define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) 16#define IS_MNT_NEW(mnt) (!mnt->mnt_namespace)
16#define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) 17#define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED)
17 18
18#define CL_EXPIRE 0x01 19#define CL_EXPIRE 0x01
20#define CL_SLAVE 0x02
19#define CL_COPY_ALL 0x04 21#define CL_COPY_ALL 0x04
20#define CL_MAKE_SHARED 0x08 22#define CL_MAKE_SHARED 0x08
21#define CL_PROPAGATION 0x10 23#define CL_PROPAGATION 0x10