2 fs/namei.c | 66 ++++++++++++++++++++++++++++++++++++++---------------
3 include/linux/fs.h | 11 ++++----
4 3 files changed, 54 insertions(+), 24 deletions(-)
6 Index: linux-2.6.10/fs/inode.c
7 ===================================================================
8 --- linux-2.6.10.orig/fs/inode.c 2004-12-25 05:35:40.000000000 +0800
9 +++ linux-2.6.10/fs/inode.c 2005-03-31 18:03:53.551688872 +0800
12 memset(&inode->u, 0, sizeof(inode->u));
13 inode->i_mapping = mapping;
14 + dynlock_init(&inode->i_dcache_lock);
18 Index: linux-2.6.10/fs/namei.c
19 ===================================================================
20 --- linux-2.6.10.orig/fs/namei.c 2005-03-31 17:57:10.767921312 +0800
21 +++ linux-2.6.10/fs/namei.c 2005-03-31 18:05:52.839554360 +0800
23 * any extra contention...
26 +void *lock_dir(struct inode *dir, struct qstr *name)
30 + if (!IS_PDIROPS(dir)) {
35 + /* OK. fs understands parallel directory operations.
36 + * so, we try to acquire lock for hash of requested
37 + * filename in order to prevent any operations with
38 + * same name in same time -bzzz */
40 + /* calculate name hash */
41 + hash = full_name_hash(name->name, name->len);
43 + /* lock this hash */
44 + return dynlock_lock(&dir->i_dcache_lock, hash, 1, GFP_ATOMIC);
46 +EXPORT_SYMBOL(lock_dir);
48 +void unlock_dir(struct inode *dir, void *lock)
50 + if (!IS_PDIROPS(dir)) {
54 + dynlock_unlock(&dir->i_dcache_lock, lock);
56 +EXPORT_SYMBOL(unlock_dir);
58 /* In order to reduce some races, while at the same time doing additional
59 * checking and hopefully speeding things up, we copy filenames to the
60 * kernel data space before using them..
63 struct dentry * result;
64 struct inode *dir = parent->d_inode;
68 + lock = lock_dir(dir, name);
70 * First re-do the cached lookup just in case it was created
71 * while we waited for the directory semaphore..
77 + unlock_dir(dir, lock);
82 * Uhhuh! Nasty case: the cache was re-populated while
83 * we waited on the semaphore. Need to revalidate.
86 + unlock_dir(dir, lock);
87 if (result->d_op && result->d_op->d_revalidate) {
88 if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
93 nd->flags &= ~LOOKUP_PARENT;
94 - down(&dir->d_inode->i_sem);
95 + nd->lock = lock_dir(dir->d_inode, &nd->last);
96 nd->flags |= LOOKUP_LAST;
97 dentry = __lookup_hash(&nd->last, nd->dentry, nd);
98 nd->flags &= ~LOOKUP_LAST;
101 error = PTR_ERR(dentry);
102 if (IS_ERR(dentry)) {
103 - up(&dir->d_inode->i_sem);
104 + unlock_dir(dir->d_inode, nd->lock);
108 @@ -1478,7 +1511,7 @@
109 if (!IS_POSIXACL(dir->d_inode))
110 mode &= ~current->fs->umask;
111 error = vfs_create(dir->d_inode, dentry, mode, nd);
112 - up(&dir->d_inode->i_sem);
113 + unlock_dir(dir->d_inode, nd->lock);
117 @@ -1492,7 +1525,7 @@
121 - up(&dir->d_inode->i_sem);
122 + unlock_dir(dir->d_inode, nd->lock);
126 @@ -1576,7 +1609,7 @@
130 - down(&dir->d_inode->i_sem);
131 + nd->lock = lock_dir(dir->d_inode, &nd->last);
132 nd->flags |= LOOKUP_LAST;
133 dentry = __lookup_hash(&nd->last, nd->dentry, nd);
134 nd->flags &= ~LOOKUP_LAST;
135 @@ -1596,7 +1629,7 @@
137 struct dentry *dentry;
139 - down(&nd->dentry->d_inode->i_sem);
140 + nd->lock = lock_dir(nd->dentry->d_inode, &nd->last);
141 dentry = ERR_PTR(-EEXIST);
142 if (nd->last_type != LAST_NORM)
144 @@ -1688,7 +1721,7 @@
148 - up(&nd.dentry->d_inode->i_sem);
149 + unlock_dir(nd.dentry->d_inode, nd.lock);
153 @@ -1747,7 +1780,7 @@
154 error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
157 - up(&nd.dentry->d_inode->i_sem);
158 + unlock_dir(nd.dentry->d_inode, nd.lock);
162 @@ -1852,14 +1885,14 @@
166 - down(&nd.dentry->d_inode->i_sem);
167 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
168 dentry = lookup_hash(&nd.last, nd.dentry);
169 error = PTR_ERR(dentry);
170 if (!IS_ERR(dentry)) {
171 error = vfs_rmdir(nd.dentry->d_inode, dentry);
174 - up(&nd.dentry->d_inode->i_sem);
175 + unlock_dir(nd.dentry->d_inode, nd.lock);
179 @@ -1925,7 +1958,7 @@
181 if (nd.last_type != LAST_NORM)
183 - down(&nd.dentry->d_inode->i_sem);
184 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
185 dentry = lookup_hash(&nd.last, nd.dentry);
186 error = PTR_ERR(dentry);
187 if (!IS_ERR(dentry)) {
188 @@ -1939,7 +1972,7 @@
192 - up(&nd.dentry->d_inode->i_sem);
193 + unlock_dir(nd.dentry->d_inode, nd.lock);
195 iput(inode); /* truncate the inode here */
197 @@ -2005,7 +2038,7 @@
198 error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
201 - up(&nd.dentry->d_inode->i_sem);
202 + unlock_dir(nd.dentry->d_inode, nd.lock);
206 @@ -2094,7 +2127,7 @@
207 error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
210 - up(&nd.dentry->d_inode->i_sem);
211 + unlock_dir(nd.dentry->d_inode, nd.lock);
215 Index: linux-2.6.10/include/linux/fs.h
216 ===================================================================
217 --- linux-2.6.10.orig/include/linux/fs.h 2005-03-31 17:57:13.330531736 +0800
218 +++ linux-2.6.10/include/linux/fs.h 2005-03-31 18:08:59.645155592 +0800
220 #include <linux/prio_tree.h>
221 #include <linux/kobject.h>
222 #include <asm/atomic.h>
223 +#include <linux/dynlocks.h>
228 #define S_DIRSYNC 64 /* Directory modifications are synchronous */
229 #define S_NOCMTIME 128 /* Do not update file c/mtime */
230 #define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */
232 +#define S_PDIROPS 512 /* Parallel directory operations */
234 * Note that nosuid etc flags are inode-specific: setting some file-system
235 * flags just means all the inodes inherit those flags by default. It might be
237 #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
238 #define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
239 #define IS_ONE_SECOND(inode) __IS_FLG(inode, MS_ONE_SECOND)
240 +#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
242 #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
243 #define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
246 atomic_t i_writecount;
248 + struct dynlock i_dcache_lock; /* for parallel directory ops */
252 Index: linux-2.6.10/include/linux/namei.h
253 ===================================================================
254 --- linux-2.6.10.orig/include/linux/namei.h 2005-03-31 17:50:12.533502608 +0800
255 +++ linux-2.6.10/include/linux/namei.h 2005-03-31 18:10:30.237383480 +0800
259 char *saved_names[MAX_NESTED_LINKS + 1];
265 struct open_intent open;
267 #define LOOKUP_ATOMIC 64
268 #define LOOKUP_LAST 128
269 #define LOOKUP_LINK_NOTLAST 256