[RFC PATCH 5/5] Directory cache invalidation
Changes to keep dirent cache uptodate. Dirent cache stored as part of topmost directory's struct file needs to be marked stale whenever there is a modification in any of the directories that is part of the union. Modifications(like addition/deletion of new entries) to a directory can occur from places like mkdir, rmdir, mknod etc. Signed-off-by: Bharata B Rao <[EMAIL PROTECTED]> --- fs/dcache.c|1 fs/namei.c | 13 +++ fs/union.c | 178 - include/linux/dcache.h |4 - include/linux/fs.h |4 + include/linux/union.h |3 6 files changed, 201 insertions(+), 2 deletions(-) --- a/fs/dcache.c +++ b/fs/dcache.c @@ -974,6 +974,7 @@ struct dentry *d_alloc(struct dentry * p #endif #ifdef CONFIG_UNION_MOUNT INIT_LIST_HEAD(>d_unions); + INIT_LIST_HEAD(>d_overlaid); dentry->d_unionized = 0; #endif INIT_HLIST_NODE(>d_hash); --- a/fs/namei.c +++ b/fs/namei.c @@ -2237,6 +2237,7 @@ static int __open_namei_create(struct na nd->path.dentry = path->dentry; if (error) return error; + rdcache_invalidate(>path); /* Don't check for write permission, don't truncate */ return may_open(nd, 0, flag & ~O_TRUNC); } @@ -2682,6 +2683,8 @@ asmlinkage long sys_mknodat(int dfd, con mode, 0); break; } + if (!error) + rdcache_invalidate(); mnt_drop_write(nd.path.mnt); out_dput: path_put_conditional(, ); @@ -2757,6 +2760,8 @@ asmlinkage long sys_mkdirat(int dfd, con if (error) goto out_dput; error = vfs_mkdir(nd.path.dentry->d_inode, path.dentry, mode); + if (!error) + rdcache_invalidate(); mnt_drop_write(nd.path.mnt); out_dput: path_put_conditional(, ); @@ -3287,6 +3292,8 @@ static long do_rmdir(int dfd, const char if (error) goto exit3; error = vfs_rmdir(nd.path.dentry->d_inode, path.dentry); + if (!error) + rdcache_invalidate(); mnt_drop_write(nd.path.mnt); exit3: path_put_conditional(, ); @@ -3375,6 +3382,8 @@ static long do_unlinkat(int dfd, const c if (error) goto exit2; error = vfs_unlink(nd.path.dentry->d_inode, path.dentry); + if (!error) + rdcache_invalidate(); mnt_drop_write(nd.path.mnt); exit2: path_put_conditional(, ); @@ -3466,6 +3475,8 @@ asmlinkage long sys_symlinkat(const char goto out_dput; error = vfs_symlink(nd.path.dentry->d_inode, path.dentry, from, S_IALLUGO); + if (!error) + rdcache_invalidate(); mnt_drop_write(nd.path.mnt); out_dput: path_put_conditional(, ); @@ -3566,6 +3577,8 @@ asmlinkage long sys_linkat(int olddfd, c goto out_dput; error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, path.dentry); + if (!error) + rdcache_invalidate(); mnt_drop_write(nd.path.mnt); out_dput: path_put_conditional(, ); --- a/fs/union.c +++ b/fs/union.c @@ -39,6 +39,7 @@ static struct hlist_head *union_hashtabl static unsigned int union_rhash_mask __read_mostly; static unsigned int union_rhash_shift __read_mostly; static struct hlist_head *union_rhashtable __read_mostly; +static struct hlist_head *readdir_hashtable __read_mostly; /* * Locking Rules: @@ -103,6 +104,18 @@ static int __init init_union(void) for (loop = 0; loop < (1 << union_rhash_shift); loop++) INIT_HLIST_HEAD(_rhashtable[loop]); + readdir_hashtable = alloc_large_system_hash("readdir-cache", + sizeof(struct hlist_head), + union_hash_entries, + 14, + 0, + _rhash_shift, + _rhash_mask, + 0); + + for (loop = 0; loop < (1 << union_rhash_shift); loop++) + INIT_HLIST_HEAD(_hashtable[loop]); + readdir_cache = kmem_cache_create("readdir-cache", sizeof(struct rdcache_entry), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); @@ -126,6 +139,7 @@ struct union_mount *union_alloc(struct d atomic_set(>u_count, 1); INIT_LIST_HEAD(>u_unions); INIT_LIST_HEAD(>u_list); + INIT_LIST_HEAD(>u_overlaid); INIT_HLIST_NODE(>u_hash); INIT_HLIST_NODE(>u_rhash); @@ -290,6 +304,7 @@ int append_to_union(struct vfsmount *mnt }
[RFC PATCH 5/5] Directory cache invalidation
Changes to keep dirent cache uptodate. Dirent cache stored as part of topmost directory's struct file needs to be marked stale whenever there is a modification in any of the directories that is part of the union. Modifications(like addition/deletion of new entries) to a directory can occur from places like mkdir, rmdir, mknod etc. Signed-off-by: Bharata B Rao [EMAIL PROTECTED] --- fs/dcache.c|1 fs/namei.c | 13 +++ fs/union.c | 178 - include/linux/dcache.h |4 - include/linux/fs.h |4 + include/linux/union.h |3 6 files changed, 201 insertions(+), 2 deletions(-) --- a/fs/dcache.c +++ b/fs/dcache.c @@ -974,6 +974,7 @@ struct dentry *d_alloc(struct dentry * p #endif #ifdef CONFIG_UNION_MOUNT INIT_LIST_HEAD(dentry-d_unions); + INIT_LIST_HEAD(dentry-d_overlaid); dentry-d_unionized = 0; #endif INIT_HLIST_NODE(dentry-d_hash); --- a/fs/namei.c +++ b/fs/namei.c @@ -2237,6 +2237,7 @@ static int __open_namei_create(struct na nd-path.dentry = path-dentry; if (error) return error; + rdcache_invalidate(nd-path); /* Don't check for write permission, don't truncate */ return may_open(nd, 0, flag ~O_TRUNC); } @@ -2682,6 +2683,8 @@ asmlinkage long sys_mknodat(int dfd, con mode, 0); break; } + if (!error) + rdcache_invalidate(nd.path); mnt_drop_write(nd.path.mnt); out_dput: path_put_conditional(path, nd); @@ -2757,6 +2760,8 @@ asmlinkage long sys_mkdirat(int dfd, con if (error) goto out_dput; error = vfs_mkdir(nd.path.dentry-d_inode, path.dentry, mode); + if (!error) + rdcache_invalidate(nd.path); mnt_drop_write(nd.path.mnt); out_dput: path_put_conditional(path, nd); @@ -3287,6 +3292,8 @@ static long do_rmdir(int dfd, const char if (error) goto exit3; error = vfs_rmdir(nd.path.dentry-d_inode, path.dentry); + if (!error) + rdcache_invalidate(nd.path); mnt_drop_write(nd.path.mnt); exit3: path_put_conditional(path, nd); @@ -3375,6 +3382,8 @@ static long do_unlinkat(int dfd, const c if (error) goto exit2; error = vfs_unlink(nd.path.dentry-d_inode, path.dentry); + if (!error) + rdcache_invalidate(nd.path); mnt_drop_write(nd.path.mnt); exit2: path_put_conditional(path, nd); @@ -3466,6 +3475,8 @@ asmlinkage long sys_symlinkat(const char goto out_dput; error = vfs_symlink(nd.path.dentry-d_inode, path.dentry, from, S_IALLUGO); + if (!error) + rdcache_invalidate(nd.path); mnt_drop_write(nd.path.mnt); out_dput: path_put_conditional(path, nd); @@ -3566,6 +3577,8 @@ asmlinkage long sys_linkat(int olddfd, c goto out_dput; error = vfs_link(old_nd.path.dentry, nd.path.dentry-d_inode, path.dentry); + if (!error) + rdcache_invalidate(nd.path); mnt_drop_write(nd.path.mnt); out_dput: path_put_conditional(path, nd); --- a/fs/union.c +++ b/fs/union.c @@ -39,6 +39,7 @@ static struct hlist_head *union_hashtabl static unsigned int union_rhash_mask __read_mostly; static unsigned int union_rhash_shift __read_mostly; static struct hlist_head *union_rhashtable __read_mostly; +static struct hlist_head *readdir_hashtable __read_mostly; /* * Locking Rules: @@ -103,6 +104,18 @@ static int __init init_union(void) for (loop = 0; loop (1 union_rhash_shift); loop++) INIT_HLIST_HEAD(union_rhashtable[loop]); + readdir_hashtable = alloc_large_system_hash(readdir-cache, + sizeof(struct hlist_head), + union_hash_entries, + 14, + 0, + union_rhash_shift, + union_rhash_mask, + 0); + + for (loop = 0; loop (1 union_rhash_shift); loop++) + INIT_HLIST_HEAD(readdir_hashtable[loop]); + readdir_cache = kmem_cache_create(readdir-cache, sizeof(struct rdcache_entry), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); @@ -126,6 +139,7 @@ struct union_mount *union_alloc(struct d atomic_set(um-u_count, 1); INIT_LIST_HEAD(um-u_unions); INIT_LIST_HEAD(um-u_list); + INIT_LIST_HEAD(um-u_overlaid); INIT_HLIST_NODE(um-u_hash);