[RFC PATCH 5/5] Directory cache invalidation

2007-12-05 Thread Bharata B Rao
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

2007-12-05 Thread Bharata B Rao
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);