Re: [RFC PATCH 2/4] Mount changes to support union mount.
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.
(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.
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.
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 +