2 fs/namei.c | 66 ++++++++++++++++++++++++++++++++++++++---------------
3 include/linux/fs.h | 11 ++++----
4 3 files changed, 54 insertions(+), 24 deletions(-)
6 Index: linux-2.6.7/fs/namei.c
7 ===================================================================
8 --- linux-2.6.7.orig/fs/namei.c 2004-09-06 22:53:19.000000000 +0400
9 +++ linux-2.6.7/fs/namei.c 2004-09-07 14:39:44.000000000 +0400
11 * any extra contention...
14 +void *lock_dir(struct inode *dir, struct qstr *name)
18 + if (!IS_PDIROPS(dir)) {
23 + /* OK. fs understands parallel directory operations.
24 + * so, we try to acquire lock for hash of requested
25 + * filename in order to prevent any operations with
26 + * same name in same time -bzzz */
28 + /* calculate name hash */
29 + hash = full_name_hash(name->name, name->len);
31 + /* lock this hash */
32 + return dynlock_lock(&dir->i_dcache_lock, hash, 1, GFP_ATOMIC);
34 +EXPORT_SYMBOL(lock_dir);
36 +void unlock_dir(struct inode *dir, void *lock)
38 + if (!IS_PDIROPS(dir)) {
42 + dynlock_unlock(&dir->i_dcache_lock, lock);
44 +EXPORT_SYMBOL(unlock_dir);
46 /* In order to reduce some races, while at the same time doing additional
47 * checking and hopefully speeding things up, we copy filenames to the
48 * kernel data space before using them..
50 struct dentry * result;
51 struct inode *dir = parent->d_inode;
58 + lock = lock_dir(dir, name);
60 * First re-do the cached lookup just in case it was created
61 * while we waited for the directory semaphore..
67 + unlock_dir(dir, lock);
72 * Uhhuh! Nasty case: the cache was re-populated while
73 * we waited on the semaphore. Need to revalidate.
76 + unlock_dir(dir, lock);
77 if (result->d_op && result->d_op->d_revalidate) {
78 if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
83 nd->flags &= ~LOOKUP_PARENT;
84 - down(&dir->d_inode->i_sem);
85 + nd->lock = lock_dir(dir->d_inode, &nd->last);
86 nd->flags |= LOOKUP_LAST;
87 dentry = __lookup_hash(&nd->last, nd->dentry, nd);
88 nd->flags &= ~LOOKUP_LAST;
91 error = PTR_ERR(dentry);
93 - up(&dir->d_inode->i_sem);
94 + unlock_dir(dir->d_inode, nd->lock);
99 if (!IS_POSIXACL(dir->d_inode))
100 mode &= ~current->fs->umask;
101 error = vfs_create(dir->d_inode, dentry, mode, nd);
102 - up(&dir->d_inode->i_sem);
103 + unlock_dir(dir->d_inode, nd->lock);
107 @@ -1398,7 +1431,7 @@
111 - up(&dir->d_inode->i_sem);
112 + unlock_dir(dir->d_inode, nd->lock);
116 @@ -1474,7 +1507,7 @@
120 - down(&dir->d_inode->i_sem);
121 + nd->lock = lock_dir(dir->d_inode, &nd->last);
122 nd->flags |= LOOKUP_LAST;
123 dentry = __lookup_hash(&nd->last, nd->dentry, nd);
124 nd->flags &= ~LOOKUP_LAST;
125 @@ -1494,7 +1527,7 @@
127 struct dentry *dentry;
129 - down(&nd->dentry->d_inode->i_sem);
130 + nd->lock = lock_dir(nd->dentry->d_inode, &nd->last);
131 dentry = ERR_PTR(-EEXIST);
132 if (nd->last_type != LAST_NORM)
134 @@ -1589,7 +1622,7 @@
138 - up(&nd.dentry->d_inode->i_sem);
139 + unlock_dir(nd.dentry->d_inode, nd.lock);
143 @@ -1652,7 +1685,7 @@
144 error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
147 - up(&nd.dentry->d_inode->i_sem);
148 + unlock_dir(nd.dentry->d_inode, nd.lock);
152 @@ -1765,14 +1798,14 @@
156 - down(&nd.dentry->d_inode->i_sem);
157 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
158 dentry = lookup_hash(&nd.last, nd.dentry);
159 error = PTR_ERR(dentry);
160 if (!IS_ERR(dentry)) {
161 error = vfs_rmdir(nd.dentry->d_inode, dentry);
164 - up(&nd.dentry->d_inode->i_sem);
165 + unlock_dir(nd.dentry->d_inode, nd.lock);
169 @@ -1842,7 +1875,7 @@
170 if (error != -EOPNOTSUPP)
173 - down(&nd.dentry->d_inode->i_sem);
174 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
175 dentry = lookup_hash(&nd.last, nd.dentry);
176 error = PTR_ERR(dentry);
177 if (!IS_ERR(dentry)) {
178 @@ -1856,7 +1889,7 @@
182 - up(&nd.dentry->d_inode->i_sem);
183 + unlock_dir(nd.dentry->d_inode, nd.lock);
187 @@ -1927,7 +1960,7 @@
188 error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
191 - up(&nd.dentry->d_inode->i_sem);
192 + unlock_dir(nd.dentry->d_inode, nd.lock);
196 @@ -2021,7 +2054,7 @@
197 error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
200 - up(&nd.dentry->d_inode->i_sem);
201 + unlock_dir(nd.dentry->d_inode, nd.lock);
205 Index: linux-2.6.7/fs/inode.c
206 ===================================================================
207 --- linux-2.6.7.orig/fs/inode.c 2004-09-06 22:53:19.000000000 +0400
208 +++ linux-2.6.7/fs/inode.c 2004-09-07 14:39:44.000000000 +0400
211 memset(&inode->u, 0, sizeof(inode->u));
212 inode->i_mapping = mapping;
213 + dynlock_init(&inode->i_dcache_lock);
217 Index: linux-2.6.7/include/linux/fs.h
218 ===================================================================
219 --- linux-2.6.7.orig/include/linux/fs.h 2004-09-07 14:12:12.000000000 +0400
220 +++ linux-2.6.7/include/linux/fs.h 2004-09-07 14:39:44.000000000 +0400
222 #include <linux/prio_tree.h>
223 #include <linux/kobject.h>
224 #include <asm/atomic.h>
225 +#include <linux/dynlocks.h>
230 #define S_NOQUOTA 64 /* Inode is not counted to quota */
231 #define S_DIRSYNC 128 /* Directory modifications are synchronous */
232 #define S_NOCMTIME 256 /* Do not update file c/mtime */
233 +#define S_PDIROPS 256 /* Parallel directory operations */
236 * Note that nosuid etc flags are inode-specific: setting some file-system
238 #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
239 #define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
240 #define IS_ONE_SECOND(inode) __IS_FLG(inode, MS_ONE_SECOND)
241 +#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
243 #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
244 #define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
246 atomic_t i_writecount;
249 + struct dynlock i_dcache_lock; /* for parallel directory ops */
253 Index: linux-2.6.7/include/linux/namei.h
254 ===================================================================
255 --- linux-2.6.7.orig/include/linux/namei.h 2004-09-06 22:53:19.000000000 +0400
256 +++ linux-2.6.7/include/linux/namei.h 2004-09-07 14:40:06.000000000 +0400
260 struct lookup_intent intent;