Re: [RFC PATCH 2/4] Mount changes to support union mount.

2007-06-21 Thread Josef Sipek
On Wed, Jun 20, 2007 at 02:23:30PM +0530, Bharata B Rao wrote:
> (replying from a different ID as you didn't copy me on reply)
> 
> On 6/20/07, Jan Blunck <[EMAIL PROTECTED]> wrote:
> >On Wed, 20 Jun 2007 11:22:41 +0530, Bharata B Rao wrote:
> >
> >> +/*
> >> + * When propagating mount events to peer group, this is called under
> >> + * vfsmount_lock. Hence using GFP_ATOMIC for kmalloc here.
> >> + * TODO: Can we use a separate kmem cache for union_mount ?
> >> + */
> >> +struct union_mount *alloc_union_mount(struct vfsmount *src_mnt,
> >> + struct dentry *src_dentry, struct vfsmount *dst_mnt,
> >> + struct dentry *dst_dentry)
> >> +{
> >> + struct union_mount *u;
> >> + u = kmalloc(sizeof(struct union_mount), GFP_ATOMIC);
> >> + if (!u)
> >> + return u;
> >> + u->dst_mnt = mntget(dst_mnt);
> >> + u->dst_dentry = dget(dst_dentry);
> >> + u->src_mnt = src_mnt;
> >> + u->src_dentry = dget(src_dentry);
> >> + INIT_LIST_HEAD(&u->hash);
> >> + INIT_LIST_HEAD(&u->list);
> >> + return u;
> >> +}
> >
> >Hmm, you pin the dentries in memory until umount. This isn't good. Besides
> >that this doesn't work with file systems that do invalidate their
> >dentries. The file system must have a chance to replace the dentry in the
> >union structure.
> 
> Yes, both top level and next level dentries are pinned until umount of
> the upper layer. I was thinking if we could prune these from
> prune_dcache(). What do you think ?
> 
> Ok, I haven't thought about filesystem invalidating the dentries. Yet
> to understand the dentry invalidation, but would filesystem invalidate
> an inuse dentry ?
 
NFS, and quite possibly other network/cluster filesystems can encounter all
sort of odd conditions where the dentry might change, no?

Josef "Jeff" Sipek.

-- 
Hegh QaQ law'
quvHa'ghach QaQ puS
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 2/4] Mount changes to support union mount.

2007-06-20 Thread Bharata B Rao

(replying from a different ID as you didn't copy me on reply)

On 6/20/07, Jan Blunck <[EMAIL PROTECTED]> wrote:

On Wed, 20 Jun 2007 11:22:41 +0530, Bharata B Rao wrote:

> +/*
> + * When propagating mount events to peer group, this is called under
> + * vfsmount_lock. Hence using GFP_ATOMIC for kmalloc here.
> + * TODO: Can we use a separate kmem cache for union_mount ?
> + */
> +struct union_mount *alloc_union_mount(struct vfsmount *src_mnt,
> + struct dentry *src_dentry, struct vfsmount *dst_mnt,
> + struct dentry *dst_dentry)
> +{
> + struct union_mount *u;
> + u = kmalloc(sizeof(struct union_mount), GFP_ATOMIC);
> + if (!u)
> + return u;
> + u->dst_mnt = mntget(dst_mnt);
> + u->dst_dentry = dget(dst_dentry);
> + u->src_mnt = src_mnt;
> + u->src_dentry = dget(src_dentry);
> + INIT_LIST_HEAD(&u->hash);
> + INIT_LIST_HEAD(&u->list);
> + return u;
> +}

Hmm, you pin the dentries in memory until umount. This isn't good. Besides
that this doesn't work with file systems that do invalidate their
dentries. The file system must have a chance to replace the dentry in the
union structure.


Yes, both top level and next level dentries are pinned until umount of
the upper layer. I was thinking if we could prune these from
prune_dcache(). What do you think ?

Ok, I haven't thought about filesystem invalidating the dentries. Yet
to understand the dentry invalidation, but would filesystem invalidate
an inuse dentry ?

Regards,
Bharata.
--
"Men come and go but mountains remain" -- Ruskin Bond.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 2/4] Mount changes to support union mount.

2007-06-20 Thread Jan Blunck
On Wed, 20 Jun 2007 11:22:41 +0530, Bharata B Rao wrote:

> +/*
> + * When propagating mount events to peer group, this is called under
> + * vfsmount_lock. Hence using GFP_ATOMIC for kmalloc here.
> + * TODO: Can we use a separate kmem cache for union_mount ?
> + */
> +struct union_mount *alloc_union_mount(struct vfsmount *src_mnt,
> + struct dentry *src_dentry, struct vfsmount *dst_mnt,
> + struct dentry *dst_dentry)
> +{
> + struct union_mount *u;
> + u = kmalloc(sizeof(struct union_mount), GFP_ATOMIC);
> + if (!u)
> + return u;
> + u->dst_mnt = mntget(dst_mnt);
> + u->dst_dentry = dget(dst_dentry);
> + u->src_mnt = src_mnt;
> + u->src_dentry = dget(src_dentry);
> + INIT_LIST_HEAD(&u->hash);
> + INIT_LIST_HEAD(&u->list);
> + return u;
> +}

Hmm, you pin the dentries in memory until umount. This isn't good. Besides
that this doesn't work with file systems that do invalidate their
dentries. The file system must have a chance to replace the dentry in the
union structure.

Jan

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


[RFC PATCH 2/4] Mount changes to support union mount.

2007-06-19 Thread Bharata B Rao
From: Bharata B Rao <[EMAIL PROTECTED]>
Subject: Mount changes to support union mount.

Adds union mount support.

This patch adds a new mount type for union mount (MNT_UNION) and changes
the mount path to build a union stack during mount. The routines for
supporting the creation, traversal and destruction of union stacks are
also included here.

Signed-off-by: Bharata B Rao <[EMAIL PROTECTED]>
---
 fs/namespace.c|  164 ++
 include/linux/fs.h|1 
 include/linux/mount.h |   17 +
 3 files changed, 172 insertions(+), 10 deletions(-)

--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -35,6 +35,7 @@ __cacheline_aligned_in_smp DEFINE_SPINLO
 static int event;
 
 static struct list_head *mount_hashtable __read_mostly;
+static struct list_head *union_mount_hashtable;
 static int hash_mask __read_mostly, hash_bits __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
 static struct rw_semaphore namespace_sem;
@@ -54,6 +55,89 @@ static inline unsigned long hash(struct 
return tmp & hash_mask;
 }
 
+/* Must be called with vfsmount_lock held */
+static struct union_mount *find_union_mount(struct vfsmount *mnt,
+   struct dentry *dentry)
+{
+   struct list_head *head;
+   struct union_mount *u;
+
+   if (!IS_MNT_UNION(mnt))
+   return NULL;
+
+   head = union_mount_hashtable + hash(mnt, dentry);
+   list_for_each_entry(u, head, hash)
+   if (u->src_mnt == mnt && u->src_dentry == dentry)
+   return u;
+   return NULL;
+}
+
+/*
+ * When propagating mount events to peer group, this is called under
+ * vfsmount_lock. Hence using GFP_ATOMIC for kmalloc here.
+ * TODO: Can we use a separate kmem cache for union_mount ?
+ */
+struct union_mount *alloc_union_mount(struct vfsmount *src_mnt,
+   struct dentry *src_dentry, struct vfsmount *dst_mnt,
+   struct dentry *dst_dentry)
+{
+   struct union_mount *u;
+   u = kmalloc(sizeof(struct union_mount), GFP_ATOMIC);
+   if (!u)
+   return u;
+   u->dst_mnt = mntget(dst_mnt);
+   u->dst_dentry = dget(dst_dentry);
+   u->src_mnt = src_mnt;
+   u->src_dentry = dget(src_dentry);
+   INIT_LIST_HEAD(&u->hash);
+   INIT_LIST_HEAD(&u->list);
+   return u;
+}
+
+/* Must be called with vfsmount_lock held */
+void attach_mnt_union(struct union_mount *u)
+{
+   if (!u)
+   return;
+
+   list_add_tail(&u->hash, union_mount_hashtable +
+   hash(u->src_mnt, u->src_dentry));
+   list_add_tail(&u->list, &u->src_mnt->mnt_union);
+}
+
+/*
+ * Finds the next (vfsmount, dentry) in the union stack. If found, returns
+ * it via @nd and returns true. Else doesn't modify @nd, but returns false.
+ */
+int next_union_mount(struct nameidata *nd)
+{
+   struct union_mount *u;
+
+   spin_lock(&vfsmount_lock);
+   u = find_union_mount(nd->mnt, nd->dentry);
+   spin_unlock(&vfsmount_lock);
+   if (u) {
+   nd->mnt = u->dst_mnt;
+   nd->dentry = u->dst_dentry;
+   return 1;
+   }
+   return 0;
+}
+
+/* Check if next element of the union stack exists. @nd isn't modified. */
+int next_union_mount_exists(struct vfsmount *mnt, struct dentry *dentry)
+{
+   struct union_mount *u;
+
+   spin_lock(&vfsmount_lock);
+   u = find_union_mount(mnt, dentry);
+   spin_unlock(&vfsmount_lock);
+   if (u)
+   return 1;
+   else
+   return 0;
+}
+
 struct vfsmount *alloc_vfsmnt(const char *name)
 {
struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
@@ -67,6 +151,7 @@ struct vfsmount *alloc_vfsmnt(const char
INIT_LIST_HEAD(&mnt->mnt_share);
INIT_LIST_HEAD(&mnt->mnt_slave_list);
INIT_LIST_HEAD(&mnt->mnt_slave);
+   INIT_LIST_HEAD(&mnt->mnt_union);
if (name) {
int size = strlen(name) + 1;
char *newname = kmalloc(size, GFP_KERNEL);
@@ -173,18 +258,20 @@ void mnt_set_mountpoint(struct vfsmount 
dentry->d_mounted++;
 }
 
-static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd)
+static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd,
+   struct union_mount *u)
 {
mnt_set_mountpoint(nd->mnt, nd->dentry, mnt);
list_add_tail(&mnt->mnt_hash, mount_hashtable +
hash(nd->mnt, nd->dentry));
list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts);
+   attach_mnt_union(u);
 }
 
 /*
  * the caller must hold vfsmount_lock
  */
-static void commit_tree(struct vfsmount *mnt)
+static void commit_tree(struct vfsmount *mnt, struct union_mount *u)
 {
struct vfsmount *parent = mnt->mnt_parent;
struct vfsmount *m;
@@ -201,6 +288,7 @@ static void commit_tree(struct vfsmount 
list_add_tail(&mnt->mnt_hash, mount_hashtable +