Re: supposed to be shared subtree patches.

2005-07-25 Thread Ram Pai
On Mon, 2005-07-25 at 15:44, Ram Pai wrote:
> , [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
> linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
> Subject: [PATCH 0/7] shared subtree
> 
> Hi Andrew/Al Viro,
> 
>   Enclosing a final set of well tested patches that implement

my apologies. I screwed up sending the patches through quilt.

anyway I have received the following comments from Andrew Morton, which
I will incorporate before sending out saner looking patches.
sorry again,
RP

Andrew's comments follows:


Frankly, I don't even know what these patches _do_, and haven't spent
the time to try to find out.

If these patches are merged, how do we expect end-users to find out how
to use the new capabilities?

A few paragraphs in the patch #1 changelog would help.  A high-level
description of the new capability which explains what it does and why it
would be a useful thing for Linux.

And maybe some deeper information in a Documentation/ file.

Right now, there might well be a lot of people who could use these new
features, but they don't even know that these patches provide them! 
It's all a bit of a mystery, really.
-


-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[no subject]

2005-07-25 Thread Ram Pai
, [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 1/7] shared subtree
Content-Type: text/x-patch; name=shared_private_slave.patch
Content-Disposition: inline; filename=shared_private_slave.patch

This patch adds the shared/private/slave support for VFS trees.

Signed by Ram Pai ([EMAIL PROTECTED])

 fs/Makefile   |2 
 fs/dcache.c   |2 
 fs/namespace.c|   93 ++
 fs/pnode.c|  441 ++
 include/linux/fs.h|5 
 include/linux/mount.h |   44 
 include/linux/pnode.h |   90 ++
 7 files changed, 673 insertions(+), 4 deletions(-)

Index: 2.6.12.work2/fs/namespace.c
===
--- 2.6.12.work2.orig/fs/namespace.c
+++ 2.6.12.work2/fs/namespace.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -62,6 +63,7 @@ struct vfsmount *alloc_vfsmnt(const char
INIT_LIST_HEAD(&mnt->mnt_mounts);
INIT_LIST_HEAD(&mnt->mnt_list);
INIT_LIST_HEAD(&mnt->mnt_fslink);
+   INIT_LIST_HEAD(&mnt->mnt_pnode_mntlist);
if (name) {
int size = strlen(name)+1;
char *newname = kmalloc(size, GFP_KERNEL);
@@ -615,6 +617,95 @@ out_unlock:
return err;
 }
 
+static int do_make_shared(struct vfsmount *mnt)
+{
+   int err=0;
+   struct vfspnode *old_pnode = NULL;
+   /*
+* if the mount is already a slave mount,
+* allocate a new pnode and make it
+* a slave pnode of the original pnode.
+*/
+   if (IS_MNT_SLAVE(mnt)) {
+   old_pnode = mnt->mnt_pnode;
+   pnode_del_slave_mnt(mnt);
+   }
+   if(!IS_MNT_SHARED(mnt)) {
+   mnt->mnt_pnode = pnode_alloc();
+   if(!mnt->mnt_pnode) {
+   pnode_add_slave_mnt(old_pnode, mnt);
+   err = -ENOMEM;
+   goto out;
+   }
+   pnode_add_member_mnt(mnt->mnt_pnode, mnt);
+   }
+   if(old_pnode)
+   pnode_add_slave_pnode(old_pnode, mnt->mnt_pnode);
+   set_mnt_shared(mnt);
+out:
+   return err;
+}
+
+static int do_make_slave(struct vfsmount *mnt)
+{
+   int err=0;
+
+   if (IS_MNT_SLAVE(mnt))
+   goto out;
+   /*
+* only shared mounts can
+* be made slave
+*/
+   if (!IS_MNT_SHARED(mnt)) {
+   err = -EINVAL;
+   goto out;
+   }
+   pnode_member_to_slave(mnt);
+out:
+   return err;
+}
+
+static int do_make_private(struct vfsmount *mnt)
+{
+   if(mnt->mnt_pnode)
+   pnode_disassociate_mnt(mnt);
+   set_mnt_private(mnt);
+   return 0;
+}
+
+/*
+ * recursively change the type of the mountpoint.
+ */
+static int do_change_type(struct nameidata *nd, int flag)
+{
+   struct vfsmount *m, *mnt = nd->mnt;
+   int err=0;
+
+   if (!(flag & MS_SHARED) && !(flag & MS_PRIVATE)
+   && !(flag & MS_SLAVE))
+   return -EINVAL;
+
+   if (nd->dentry != nd->mnt->mnt_root)
+   return -EINVAL;
+
+   spin_lock(&vfsmount_lock);
+   for (m = mnt; m; m = next_mnt(m, mnt)) {
+   switch (flag) {
+   case MS_SHARED:
+   err = do_make_shared(m);
+   break;
+   case MS_SLAVE:
+   err = do_make_slave(m);
+   break;
+   case MS_PRIVATE:
+   err = do_make_private(m);
+   break;
+   }
+   }
+   spin_unlock(&vfsmount_lock);
+   return err;
+}
+
 /*
  * do loopback mount.
  */
@@ -1049,6 +1140,8 @@ long do_mount(char * dev_name, char * di
data_page);
else if (flags & MS_BIND)
retval = do_loopback(&nd, dev_name, flags & MS_REC);
+   else if (flags & MS_SHARED || flags & MS_PRIVATE || flags & MS_SLAVE)
+   retval = do_change_type(&nd, flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&nd, dev_name);
else
Index: 2.6.12.work2/fs/pnode.c
===
--- /dev/null
+++ 2.6.12.work2/fs/pnode.c
@@ -0,0 +1,441 @@
+/*
+ *  linux/fs/pnode.c
+ *
+ * (C) Copyright IBM Corporation 2005.
+ * Released under GPL v2.
+ * Author : Ram Pai ([EMAIL PROTECTED])
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static kmem_cache_t * pnode_cachep;
+
+/* spinlock for pnode related operations */
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfspnode_lock);
+
+enu

[no subject]

2005-07-25 Thread Ram Pai
, [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 6/7] shared subtree
Content-Type: text/x-patch; name=namespace.patch
Content-Disposition: inline; filename=namespace.patch

Adds ability to clone a namespace that has shared/private/slave/unclone
subtrees in it.

RP


Signed by Ram Pai ([EMAIL PROTECTED])

 fs/namespace.c |9 +
 1 files changed, 9 insertions(+)

Index: 2.6.12-rc6.work1/fs/namespace.c
===
--- 2.6.12-rc6.work1.orig/fs/namespace.c
+++ 2.6.12-rc6.work1/fs/namespace.c
@@ -1894,6 +1894,13 @@ int copy_namespace(int flags, struct tas
q = new_ns->root;
while (p) {
q->mnt_namespace = new_ns;
+
+   if (IS_MNT_SHARED(q))
+   pnode_add_member_mnt(q->mnt_pnode, q);
+   else if (IS_MNT_SLAVE(q))
+   pnode_add_slave_mnt(q->mnt_pnode, q);
+   put_pnode(q->mnt_pnode);
+
if (fs) {
if (p == fs->rootmnt) {
rootmnt = p;
@@ -2271,6 +2278,8 @@ void __put_namespace(struct namespace *n
spin_lock(&vfsmount_lock);
 
list_for_each_entry(mnt, &namespace->list, mnt_list) {
+   if (mnt->mnt_pnode)
+   pnode_disassociate_mnt(mnt);
mnt->mnt_namespace = NULL;
}
 
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[no subject]

2005-07-25 Thread Ram Pai
, [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 3/7] shared subtree
Content-Type: text/x-patch; name=rbind.patch
Content-Disposition: inline; filename=rbind.patch

Adds the ability to bind/rbind a shared/private/slave subtree and set up
propogation wherever needed.

RP

Signed by Ram Pai ([EMAIL PROTECTED])

 fs/namespace.c|  660 --
 fs/pnode.c|  235 
 include/linux/dcache.h|2 
 include/linux/fs.h|5 
 include/linux/namespace.h |1 
 5 files changed, 826 insertions(+), 77 deletions(-)

Index: 2.6.12.work2/fs/namespace.c
===
--- 2.6.12.work2.orig/fs/namespace.c
+++ 2.6.12.work2/fs/namespace.c
@@ -42,7 +42,8 @@ static inline int sysfs_init(void)
 
 static struct list_head *mount_hashtable;
 static int hash_mask, hash_bits;
-static kmem_cache_t *mnt_cache; 
+static kmem_cache_t *mnt_cache;
+static struct rw_semaphore namespace_sem;
 
 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
 {
@@ -54,7 +55,7 @@ static inline unsigned long hash(struct 
 
 struct vfsmount *alloc_vfsmnt(const char *name)
 {
-   struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); 
+   struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL);
if (mnt) {
memset(mnt, 0, sizeof(struct vfsmount));
atomic_set(&mnt->mnt_count,1);
@@ -86,7 +87,8 @@ void free_vfsmnt(struct vfsmount *mnt)
  * Now, lookup_mnt increments the ref count before returning
  * the vfsmount struct.
  */
-struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
+struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
+   struct dentry *root)
 {
struct list_head * head = mount_hashtable + hash(mnt, dentry);
struct list_head * tmp = head;
@@ -99,7 +101,8 @@ struct vfsmount *lookup_mnt(struct vfsmo
if (tmp == head)
break;
p = list_entry(tmp, struct vfsmount, mnt_hash);
-   if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
+   if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry &&
+   (root == NULL || p->mnt_root == root)) {
found = mntget(p);
break;
}
@@ -108,6 +111,37 @@ struct vfsmount *lookup_mnt(struct vfsmo
return found;
 }
 
+struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
+{
+   return __lookup_mnt(mnt, dentry, NULL);
+}
+
+static struct vfsmount *
+clone_mnt(struct vfsmount *old, struct dentry *root)
+{
+   struct super_block *sb = old->mnt_sb;
+   struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname);
+
+   if (mnt) {
+   mnt->mnt_flags = old->mnt_flags;
+   atomic_inc(&sb->s_active);
+   mnt->mnt_sb = sb;
+   mnt->mnt_root = dget(root);
+   mnt->mnt_mountpoint = mnt->mnt_root;
+   mnt->mnt_parent = mnt;
+   mnt->mnt_namespace = old->mnt_namespace;
+   mnt->mnt_pnode = get_pnode(old->mnt_pnode);
+
+   /* stick the duplicate mount on the same expiry list
+* as the original if that was on one */
+   spin_lock(&vfsmount_lock);
+   if (!list_empty(&old->mnt_fslink))
+   list_add(&mnt->mnt_fslink, &old->mnt_fslink);
+   spin_unlock(&vfsmount_lock);
+   }
+   return mnt;
+}
+
 static inline int check_mnt(struct vfsmount *mnt)
 {
return mnt->mnt_namespace == current->namespace;
@@ -128,11 +162,71 @@ static void attach_mnt(struct vfsmount *
 {
mnt->mnt_parent = mntget(nd->mnt);
mnt->mnt_mountpoint = dget(nd->dentry);
-   list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
+   mnt->mnt_namespace = nd->mnt->mnt_namespace;
+   list_add_tail(&mnt->mnt_hash,
+   mount_hashtable+hash(nd->mnt, nd->dentry));
list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts);
nd->dentry->d_mounted++;
 }
 
+static void attach_prepare_mnt(struct vfsmount *mnt, struct nameidata *nd)
+{
+   mnt->mnt_parent = mntget(nd->mnt);
+   mnt->mnt_mountpoint = dget(nd->dentry);
+   nd->dentry->d_mounted++;
+}
+
+
+void do_attach_commit_mnt(struct vfsmount *mnt)
+{
+   struct vfsmount *parent = mnt->mnt_parent;
+   BUG_ON(parent==mnt);
+   if(list_empty(&mnt->mnt_hash))
+   list_add_tail(&mnt->mnt_hash,
+   mount_hashtable+hash(parent, mnt->mnt_mountpoint));
+   if(list_empty(&mnt->mnt_child))
+   list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
+   mnt->mnt_namespace = parent->mnt_namespace;
+   list_add_tail(&mnt->mnt_l

[no subject]

2005-07-25 Thread Ram Pai
, [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 4/7] shared subtree
Content-Type: text/x-patch; name=move.patch
Content-Disposition: inline; filename=move.patch

Adds ability to move a shared/private/slave/unclone tree to any other
shared/private/slave/unclone tree. Also incorporates the same behavior
for pivot_root()

RP


Signed by Ram Pai ([EMAIL PROTECTED])

 fs/namespace.c|  196 +++---
 include/linux/mount.h |2 
 2 files changed, 173 insertions(+), 25 deletions(-)

Index: 2.6.12.work2/fs/namespace.c
===
--- 2.6.12.work2.orig/fs/namespace.c
+++ 2.6.12.work2/fs/namespace.c
@@ -772,9 +772,12 @@ static void abort_attach_recursive_mnt(s
list_del_init(head);
 }
 
+
  /*
  *  @source_mnt : mount tree to be attached
  *  @nd: place the mount tree @source_mnt is attached
+ *  @move  : use the move semantics if set, else use normal attach 
semantics
+ *as explained below
  *
  *  NOTE: in the table below explains the semantics when a source vfsmount
  *  of a given type is attached to a destination vfsmount of a give type.
@@ -801,12 +804,41 @@ static void abort_attach_recursive_mnt(s
  *  |  |   ||  |   |
  *   
  *
- * (++)  the mount will be propogated to all the vfsmounts in the pnode tree
+ * (++)  the mount is propogated to all the vfsmounts in the pnode tree
  *   of the destination vfsmount, and all the non-slave new mounts in
  *   destination vfsmount will be added the source vfsmount's pnode.
- * (+)  the mount will be propogated to the destination vfsmount
+ * (+)  the mount is propogated to the destination vfsmount
  *   and the new mount will be added to the source vfsmount's pnode.
  *
+ *  -
+ *  |  MOVE MOUNT OPERATION|
+ *  |***|
+ *  |  dest --> | shared   |   private  |  slave   |unclonable |
+ *  | source   |   ||  |   |
+ *  |   |  |   ||  |   |
+ *  |   v  |   ||  |   |
+ *  |***|
+ *  |  |   ||  |   |
+ *  |  shared  | shared (++)   |  shared (+)|shared (+)| shared (+)|
+ *  |  |   ||  |   |
+ *  |  |   ||  |   |
+ *  | private  | shared (+)|  private   | private  | private   |
+ *  |  |   ||  |   |
+ *  |  |   ||  |   |
+ *  | slave| shared (+++)  |  slave | slave| slave |
+ *  |  |   ||  |   |
+ *  |  |   ||  |   |
+ *  | unclonable|  invalid | unclonable |unclonable| unclonable|
+ *  |  |   ||  |   |
+ *  |  |   ||  |   |
+ *   
+ *
+ * (+++)  the mount is propogated to all the vfsmounts in the pnode tree
+ *   of the destination vfsmount, and all the new mounts is
+ *   added to a new pnode , which is a slave pnode of the
+ *   source vfsmount's pnode.
+ *
+ *
  * if the source mount is a tree, the operations explained above is
  * applied to each vfsmount in the tree.
  *
@@ -815,7 +847,7 @@ static void abort_attach_recursive_mnt(s
  *
   */
 static int attach_recursive_mnt(struct vfsmount *source_mnt,
-   struct nameidata *nd)
+   struct nameidata *nd, int move)
 {
struct vfsmount *mntpt_mnt, *last, *m, *p;
struct vfspnode *src_pnode, *dest_pnode, *tmp_pnode;
@@ -849,8 +881,8 @@ static int attach_recursive_mnt(struct v
list_add_tail(&mnt_list_head, &source_mnt->mnt_list);
 
for (m = source_mnt; m; m = next_mnt(m, source_mnt)) {
-
-   BUG_ON(IS_MNT_UNCLONE(m));
+   int unclone = IS_MNT_UNCLONE(m);
+   int slave = IS_MNT_SLAVE(m);
 
while (p && p != m->mnt_parent)
p = p->mnt_parent;
@@ -866,7 +898,7 @@ static int attach_recursive_mnt(struct v
 
dest_pnode = IS_MNT_SHARED(mntpt_mnt) ?
mntpt_mnt->mnt_pnode : NULL;
-   src_pnode = (IS_MNT_SHARED(m))?
+   src_pnode =

[no subject]

2005-07-25 Thread Ram Pai
, [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 5/7] shared subtree
Content-Type: text/x-patch; name=umount.patch
Content-Disposition: inline; filename=umount.patch

Adds ability to unmount a shared/slave/unclone/private tree

RP

Signed by Ram Pai ([EMAIL PROTECTED])

 fs/namespace.c|   76 --
 fs/pnode.c|   66 +++
 include/linux/fs.h|3 +
 include/linux/pnode.h |9 -
 4 files changed, 138 insertions(+), 16 deletions(-)

Index: 2.6.12.work2/fs/pnode.c
===
--- 2.6.12.work2.orig/fs/pnode.c
+++ 2.6.12.work2/fs/pnode.c
@@ -666,3 +666,69 @@ int pnode_abort_mount(struct vfspnode *p
NULL, (void *)NULL, NULL, NULL,
vfs_abort_mount_func, exception_mnt);
 }
+
+static int vfs_busy(struct vfsmount *mnt, enum pnode_vfs_type flag,
+   void *indata, va_list args)
+{
+   struct dentry *dentry = va_arg(args, struct dentry *);
+   struct dentry *rootdentry = va_arg(args, struct dentry *);
+   struct vfsmount *origmnt = va_arg(args, struct vfsmount *);
+   struct vfsmount *child_mnt;
+   int ret=0;
+
+   spin_unlock(&vfsmount_lock);
+   child_mnt = __lookup_mnt(mnt, dentry, rootdentry);
+   spin_lock(&vfsmount_lock);
+
+   if (!child_mnt)
+   return 0;
+
+   if (list_empty(&child_mnt->mnt_mounts)) {
+   if (origmnt == child_mnt)
+   ret = do_refcount_check(child_mnt, 3);
+   else
+   ret = do_refcount_check(child_mnt, 2);
+   }
+   mntput(child_mnt);
+   return ret;
+}
+
+int pnode_mount_busy(struct vfspnode *pnode, struct dentry *mntpt,
+   struct dentry *root, struct vfsmount *mnt)
+{
+   return pnode_traverse(pnode, NULL, NULL,
+   NULL, NULL, vfs_busy, mntpt, root, mnt);
+}
+
+
+int vfs_umount(struct vfsmount *mnt, enum pnode_vfs_type flag,
+   void *indata, va_list args)
+{
+   struct vfsmount *child_mnt;
+   struct dentry *dentry, *rootdentry;
+
+
+   dentry = va_arg(args, struct dentry *);
+   rootdentry = va_arg(args, struct dentry *);
+
+   spin_unlock(&vfsmount_lock);
+   child_mnt = __lookup_mnt(mnt, dentry, rootdentry);
+   spin_lock(&vfsmount_lock);
+   mntput(child_mnt);
+   if (child_mnt && list_empty(&child_mnt->mnt_mounts)) {
+   if (IS_MNT_SHARED(child_mnt) ||
+   IS_MNT_SLAVE(child_mnt)) {
+   BUG_ON(!child_mnt->mnt_pnode);
+   pnode_disassociate_mnt(child_mnt);
+   }
+   do_detach_mount(child_mnt);
+   }
+   return 0;
+}
+
+int pnode_umount(struct vfspnode *pnode, struct dentry *dentry,
+   struct dentry *rootdentry)
+{
+   return pnode_traverse(pnode, NULL, (void *)NULL,
+   NULL, NULL, vfs_umount, dentry, rootdentry);
+}
Index: 2.6.12.work2/fs/namespace.c
===
--- 2.6.12.work2.orig/fs/namespace.c
+++ 2.6.12.work2/fs/namespace.c
@@ -395,6 +395,20 @@ resume:
 
 EXPORT_SYMBOL(may_umount_tree);
 
+int mount_busy(struct vfsmount *mnt)
+{
+   struct vfspnode *parent_pnode;
+
+   if (mnt == mnt->mnt_parent || !IS_MNT_SHARED(mnt->mnt_parent))
+   return do_refcount_check(mnt, 2);
+
+   parent_pnode = mnt->mnt_parent->mnt_pnode;
+   BUG_ON(!parent_pnode);
+   return pnode_mount_busy(parent_pnode,
+   mnt->mnt_mountpoint,
+   mnt->mnt_root, mnt);
+}
+
 /**
  * may_umount - check if a mount point is busy
  * @mnt: root of mount
@@ -410,14 +424,28 @@ EXPORT_SYMBOL(may_umount_tree);
  */
 int may_umount(struct vfsmount *mnt)
 {
-   if (atomic_read(&mnt->mnt_count) > 2)
+   if (mount_busy(mnt))
return -EBUSY;
return 0;
 }
 
 EXPORT_SYMBOL(may_umount);
 
-void umount_tree(struct vfsmount *mnt)
+void do_detach_mount(struct vfsmount *mnt)
+{
+   struct nameidata old_nd;
+   if (mnt != mnt->mnt_parent) {
+   detach_mnt(mnt, &old_nd);
+   path_release(&old_nd);
+   }
+   list_del_init(&mnt->mnt_list);
+   list_del_init(&mnt->mnt_fslink);
+   spin_unlock(&vfsmount_lock);
+   mntput(mnt);
+   spin_lock(&vfsmount_lock);
+}
+
+void __umount_tree(struct vfsmount *mnt, int propogate)
 {
struct vfsmount *p;
LIST_HEAD(kill);
@@ -431,20 +459,40 @@ void umount_tree(struct vfsmount *mnt)
mnt = list_entry(kill.next, struct vfsmount, mnt_list);
list_del_init(&mnt->mnt_list);
list_del_init(&mnt->mnt_fslink);
-   if (mnt->mnt_parent == mnt) {
-

[no subject]

2005-07-25 Thread Ram Pai
, [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 7/7] shared subtree
Content-Type: text/x-patch; name=automount.patch
Content-Disposition: inline; filename=automount.patch

adds support for mount/umount propogation for autofs initiated operations,
RP

Signed by Ram Pai ([EMAIL PROTECTED])

 fs/namespace.c|  176 +++---
 fs/pnode.c|   12 +--
 include/linux/pnode.h |3 
 3 files changed, 76 insertions(+), 115 deletions(-)

Index: 2.6.12.work2/fs/namespace.c
===
--- 2.6.12.work2.orig/fs/namespace.c
+++ 2.6.12.work2/fs/namespace.c
@@ -202,6 +202,9 @@ struct vfsmount *do_attach_prepare_mnt(s
if(!(child_mnt = clone_mnt(template_mnt,
template_mnt->mnt_root)))
return NULL;
+   spin_lock(&vfsmount_lock);
+   list_del_init(&child_mnt->mnt_fslink);
+   spin_unlock(&vfsmount_lock);
} else
child_mnt = template_mnt;
 
@@ -355,35 +358,14 @@ struct seq_operations mounts_op = {
  */
 int may_umount_tree(struct vfsmount *mnt)
 {
-   struct list_head *next;
-   struct vfsmount *this_parent = mnt;
-   int actual_refs;
-   int minimum_refs;
+   int actual_refs=0;
+   int minimum_refs=0;
+   struct vfsmount *p;
 
spin_lock(&vfsmount_lock);
-   actual_refs = atomic_read(&mnt->mnt_count);
-   minimum_refs = 2;
-repeat:
-   next = this_parent->mnt_mounts.next;
-resume:
-   while (next != &this_parent->mnt_mounts) {
-   struct vfsmount *p = list_entry(next, struct vfsmount, 
mnt_child);
-
-   next = next->next;
-
+   for (p = mnt; p; p = next_mnt(p, mnt)) {
actual_refs += atomic_read(&p->mnt_count);
minimum_refs += 2;
-
-   if (!list_empty(&p->mnt_mounts)) {
-   this_parent = p;
-   goto repeat;
-   }
-   }
-
-   if (this_parent != mnt) {
-   next = this_parent->mnt_child.next;
-   this_parent = this_parent->mnt_parent;
-   goto resume;
}
spin_unlock(&vfsmount_lock);
 
@@ -395,18 +377,18 @@ resume:
 
 EXPORT_SYMBOL(may_umount_tree);
 
-int mount_busy(struct vfsmount *mnt)
+int mount_busy(struct vfsmount *mnt, int refcnt)
 {
struct vfspnode *parent_pnode;
 
if (mnt == mnt->mnt_parent || !IS_MNT_SHARED(mnt->mnt_parent))
-   return do_refcount_check(mnt, 2);
+   return do_refcount_check(mnt, refcnt);
 
parent_pnode = mnt->mnt_parent->mnt_pnode;
BUG_ON(!parent_pnode);
return pnode_mount_busy(parent_pnode,
mnt->mnt_mountpoint,
-   mnt->mnt_root, mnt);
+   mnt->mnt_root, mnt, refcnt);
 }
 
 /**
@@ -424,9 +406,12 @@ int mount_busy(struct vfsmount *mnt)
  */
 int may_umount(struct vfsmount *mnt)
 {
-   if (mount_busy(mnt))
-   return -EBUSY;
-   return 0;
+   int ret=0;
+   spin_lock(&vfsmount_lock);
+   if (mount_busy(mnt, 2))
+   ret = -EBUSY;
+   spin_unlock(&vfsmount_lock);
+   return ret;
 }
 
 EXPORT_SYMBOL(may_umount);
@@ -445,7 +430,26 @@ void do_detach_mount(struct vfsmount *mn
spin_lock(&vfsmount_lock);
 }
 
-void __umount_tree(struct vfsmount *mnt, int propogate)
+void umount_mnt(struct vfsmount *mnt, int propogate)
+{
+   if (propogate && mnt->mnt_parent != mnt &&
+   IS_MNT_SHARED(mnt->mnt_parent)) {
+   struct vfspnode *parent_pnode
+   = mnt->mnt_parent->mnt_pnode;
+   BUG_ON(!parent_pnode);
+   pnode_umount(parent_pnode,
+   mnt->mnt_mountpoint,
+   mnt->mnt_root);
+   } else {
+   if (IS_MNT_SHARED(mnt) || IS_MNT_SLAVE(mnt)) {
+   BUG_ON(!mnt->mnt_pnode);
+   pnode_disassociate_mnt(mnt);
+   }
+   do_detach_mount(mnt);
+   }
+}
+
+static void __umount_tree(struct vfsmount *mnt, int propogate)
 {
struct vfsmount *p;
LIST_HEAD(kill);
@@ -459,21 +463,7 @@ void __umount_tree(struct vfsmount *mnt,
mnt = list_entry(kill.next, struct vfsmount, mnt_list);
list_del_init(&mnt->mnt_list);
list_del_init(&mnt->mnt_fslink);
-   if (propogate && mnt->mnt_parent != mnt &&
-   IS_MNT_SHARED(mnt->mnt_parent)) {
-   struct vfspnode *parent_pnode
-   = mnt->mnt_parent->mnt_pnode;
-   BUG_ON(!parent_pnode);
-   pnode_umount(parent_pnode,
-   mnt->mnt_mountpoint,
-   

[no subject]

2005-07-25 Thread Ram Pai
, [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 2/7] shared subtree
Content-Type: text/x-patch; name=unclone.patch
Content-Disposition: inline; filename=unclone.patch

 Adds the ability to unclone a vfs tree. A uncloned vfs tree will not be
 clonnable, and hence cannot be bind/rbind to any other mountpoint.

 RP

Signed by Ram Pai ([EMAIL PROTECTED])

 fs/namespace.c|   15 ++-
 include/linux/fs.h|1 +
 include/linux/mount.h |   15 +++
 3 files changed, 30 insertions(+), 1 deletion(-)

Index: 2.6.12.work2/fs/namespace.c
===
--- 2.6.12.work2.orig/fs/namespace.c
+++ 2.6.12.work2/fs/namespace.c
@@ -673,6 +673,14 @@ static int do_make_private(struct vfsmou
return 0;
 }
 
+static int do_make_unclone(struct vfsmount *mnt)
+{
+   if(mnt->mnt_pnode)
+   pnode_disassociate_mnt(mnt);
+   set_mnt_unclone(mnt);
+   return 0;
+}
+
 /*
  * recursively change the type of the mountpoint.
  */
@@ -682,6 +690,7 @@ static int do_change_type(struct nameida
int err=0;
 
if (!(flag & MS_SHARED) && !(flag & MS_PRIVATE)
+   && !(flag & MS_UNCLONE)
&& !(flag & MS_SLAVE))
return -EINVAL;
 
@@ -700,6 +709,9 @@ static int do_change_type(struct nameida
case MS_PRIVATE:
err = do_make_private(m);
break;
+   case MS_UNCLONE:
+   err = do_make_unclone(m);
+   break;
}
}
spin_unlock(&vfsmount_lock);
@@ -1140,7 +1152,8 @@ long do_mount(char * dev_name, char * di
data_page);
else if (flags & MS_BIND)
retval = do_loopback(&nd, dev_name, flags & MS_REC);
-   else if (flags & MS_SHARED || flags & MS_PRIVATE || flags & MS_SLAVE)
+   else if (flags & MS_SHARED || flags & MS_UNCLONE ||
+   flags & MS_PRIVATE || flags & MS_SLAVE)
retval = do_change_type(&nd, flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&nd, dev_name);
Index: 2.6.12.work2/include/linux/fs.h
===
--- 2.6.12.work2.orig/include/linux/fs.h
+++ 2.6.12.work2/include/linux/fs.h
@@ -102,6 +102,7 @@ extern int dir_notify_enable;
 #define MS_MOVE8192
 #define MS_REC 16384
 #define MS_VERBOSE 32768
+#define MS_UNCLONE (1<<17) /* recursively change to unclonnable */
 #define MS_PRIVATE (1<<18) /* recursively change to private */
 #define MS_SLAVE   (1<<19) /* recursively change to slave */
 #define MS_SHARED  (1<<20) /* recursively change to shared */
Index: 2.6.12.work2/include/linux/mount.h
===
--- 2.6.12.work2.orig/include/linux/mount.h
+++ 2.6.12.work2/include/linux/mount.h
@@ -22,15 +22,18 @@
 #define MNT_PRIVATE0x10  /* if the vfsmount is private, by default it is 
private*/
 #define MNT_SLAVE  0x20  /* if the vfsmount is a slave mount of its pnode 
*/
 #define MNT_SHARED 0x40  /* if the vfsmount is a slave mount of its pnode 
*/
+#define MNT_UNCLONE0x80  /* if the vfsmount is unclonable */
 #define MNT_PNODE_MASK 0xf0  /* propogation flag mask */
 
 #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED)
 #define IS_MNT_SLAVE(mnt) (mnt->mnt_flags & MNT_SLAVE)
 #define IS_MNT_PRIVATE(mnt) (mnt->mnt_flags & MNT_PRIVATE)
+#define IS_MNT_UNCLONE(mnt) (mnt->mnt_flags & MNT_UNCLONE)
 
 #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~(MNT_PNODE_MASK & 
MNT_SHARED))
 #define CLEAR_MNT_PRIVATE(mnt) (mnt->mnt_flags &= ~(MNT_PNODE_MASK & 
MNT_PRIVATE))
 #define CLEAR_MNT_SLAVE(mnt) (mnt->mnt_flags &= ~(MNT_PNODE_MASK & MNT_SLAVE))
+#define CLEAR_MNT_UNCLONE(mnt) (mnt->mnt_flags &= ~(MNT_PNODE_MASK & 
MNT_UNCLONE))
 
 struct vfsmount
 {
@@ -59,6 +62,7 @@ static inline void set_mnt_shared(struct
mnt->mnt_flags |= MNT_PNODE_MASK & MNT_SHARED;
CLEAR_MNT_PRIVATE(mnt);
CLEAR_MNT_SLAVE(mnt);
+   CLEAR_MNT_UNCLONE(mnt);
 }
 
 static inline void set_mnt_private(struct vfsmount *mnt)
@@ -66,6 +70,16 @@ static inline void set_mnt_private(struc
mnt->mnt_flags |= MNT_PNODE_MASK & MNT_PRIVATE;
CLEAR_MNT_SLAVE(mnt);
CLEAR_MNT_SHARED(mnt);
+   CLEAR_MNT_UNCLONE(mnt);
+   mnt->mnt_pnode = NULL;
+}
+
+static inline void set_mnt_unclone(struct vfsmount *mnt)
+{
+   mnt->mnt_flags |= MNT_PNODE_MASK & MNT_UNCLONE;
+   CLEAR_MNT_SLAVE(mnt);
+   CLEAR_MNT_SHARED(mnt);
+   CLEAR_MNT_PRIVATE(mnt);
mnt->mnt_pnode = NULL;
 }
 
@@ -74,6 +88,7 @@ static inline void set_mnt_slave(struct 
mnt->mnt_flags |= MNT_PNODE_MASK & MNT_SLAVE;
CLEAR_MNT_PRIVATE(mnt);
CLEAR_MNT

[no subject]

2005-07-25 Thread Ram Pai
, [EMAIL PROTECTED], Janak Desai <[EMAIL PROTECTED]>, 
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 0/7] shared subtree

Hi Andrew/Al Viro,

Enclosing a final set of well tested patches that implement
Al Viro's shared subtree proposal.

These patches provide the ability to mark a mount tree as
shared/private/slave/unclone, along with the ability to play with these
trees with operations like bind/rbind/move/pivot_root/namespace-clone
etc.

I believe this powerful feature can help build features like
per-user namespace.  Couple of projects may benefit from
shared subtrees.
1) automounter for the ability to automount across namespaces.
2) SeLinux for implementing polyinstantiated trees.
3) MVFS for providing versioning file system.
4) FUSE for per-user namespaces?

Thanks to Avantika for developing about 100+ test cases that tests
various combintation of private/shared/slave/unclonable trees. All
these tests have passed. I feel pretty confident about the stability of
the code.

The patches have been broken into 7 units, for ease of review.  I
realize that patch-3 'rbind.patch' is a bit heavier than all the other
patches. The reason being, most of the shared-subtree functionality 
gets manifestated during bind/rbind operation.

Couple of work items to be done are:
1. modify the mount command to support this feature
eg:  mount --make-shared /tmp
2. a tool that can help visualize the propogation tree, maybe
support in /proc?
3. some documentation on how to use all this functionality.

Please consider the patches for inclusion in your tree.

The footprint of this code is pretty small in the normal code path
where shared-subtree functionality is not used.

Any suggestions/comments to improve the code is welcome.

Thanks,
RP
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html