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..
51 struct dentry * result;
52 struct inode *dir = parent->d_inode;
56 + lock = lock_dir(dir, name);
58 * First re-do the cached lookup just in case it was created
59 * while we waited for the directory semaphore..
65 + unlock_dir(dir, lock);
70 * Uhhuh! Nasty case: the cache was re-populated while
71 * we waited on the semaphore. Need to revalidate.
74 + unlock_dir(dir, lock);
75 if (result->d_op && result->d_op->d_revalidate) {
76 if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
81 nd->flags &= ~LOOKUP_PARENT;
82 - down(&dir->d_inode->i_sem);
83 + nd->lock = lock_dir(dir->d_inode, &nd->last);
84 nd->flags |= LOOKUP_LAST;
85 dentry = __lookup_hash(&nd->last, nd->dentry, nd);
86 nd->flags &= ~LOOKUP_LAST;
89 error = PTR_ERR(dentry);
91 - up(&dir->d_inode->i_sem);
92 + unlock_dir(dir->d_inode, nd->lock);
97 if (!IS_POSIXACL(dir->d_inode))
98 mode &= ~current->fs->umask;
99 error = vfs_create(dir->d_inode, dentry, mode, nd);
100 - up(&dir->d_inode->i_sem);
101 + unlock_dir(dir->d_inode, nd->lock);
105 @@ -1398,7 +1431,7 @@
109 - up(&dir->d_inode->i_sem);
110 + unlock_dir(dir->d_inode, nd->lock);
114 @@ -1474,7 +1507,7 @@
118 - down(&dir->d_inode->i_sem);
119 + nd->lock = lock_dir(dir->d_inode, &nd->last);
120 nd->flags |= LOOKUP_LAST;
121 dentry = __lookup_hash(&nd->last, nd->dentry, nd);
122 nd->flags &= ~LOOKUP_LAST;
123 @@ -1494,7 +1527,7 @@
125 struct dentry *dentry;
127 - down(&nd->dentry->d_inode->i_sem);
128 + nd->lock = lock_dir(nd->dentry->d_inode, &nd->last);
129 dentry = ERR_PTR(-EEXIST);
130 if (nd->last_type != LAST_NORM)
132 @@ -1589,7 +1622,7 @@
136 - up(&nd.dentry->d_inode->i_sem);
137 + unlock_dir(nd.dentry->d_inode, nd.lock);
141 @@ -1652,7 +1685,7 @@
142 error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
145 - up(&nd.dentry->d_inode->i_sem);
146 + unlock_dir(nd.dentry->d_inode, nd.lock);
150 @@ -1735,14 +1735,14 @@
154 - down(&nd.dentry->d_inode->i_sem);
155 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
156 dentry = lookup_hash(&nd.last, nd.dentry);
157 error = PTR_ERR(dentry);
158 if (!IS_ERR(dentry)) {
159 error = vfs_rmdir(nd.dentry->d_inode, dentry);
162 - up(&nd.dentry->d_inode->i_sem);
163 + unlock_dir(nd.dentry->d_inode, nd.lock);
167 @@ -1808,7 +1808,7 @@
169 if (nd.last_type != LAST_NORM)
171 - down(&nd.dentry->d_inode->i_sem);
172 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
173 dentry = lookup_hash(&nd.last, nd.dentry);
174 error = PTR_ERR(dentry);
175 if (!IS_ERR(dentry)) {
176 @@ -1856,7 +1889,7 @@
180 - up(&nd.dentry->d_inode->i_sem);
181 + unlock_dir(nd.dentry->d_inode, nd.lock);
185 @@ -1927,7 +1960,7 @@
186 error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
189 - up(&nd.dentry->d_inode->i_sem);
190 + unlock_dir(nd.dentry->d_inode, nd.lock);
194 @@ -2021,7 +2054,7 @@
195 error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
198 - up(&nd.dentry->d_inode->i_sem);
199 + unlock_dir(nd.dentry->d_inode, nd.lock);
203 Index: linux-2.6.7/fs/inode.c
204 ===================================================================
205 --- linux-2.6.7.orig/fs/inode.c 2004-09-06 22:53:19.000000000 +0400
206 +++ linux-2.6.7/fs/inode.c 2004-09-07 14:39:44.000000000 +0400
209 memset(&inode->u, 0, sizeof(inode->u));
210 inode->i_mapping = mapping;
211 + dynlock_init(&inode->i_dcache_lock);
215 Index: linux-2.6.7/include/linux/fs.h
216 ===================================================================
217 --- linux-2.6.7.orig/include/linux/fs.h 2004-09-07 14:12:12.000000000 +0400
218 +++ linux-2.6.7/include/linux/fs.h 2004-09-07 14:39:44.000000000 +0400
220 #include <linux/prio_tree.h>
221 #include <linux/kobject.h>
222 #include <asm/atomic.h>
223 +#include <linux/dynlocks.h>
228 #define S_NOQUOTA 64 /* Inode is not counted to quota */
229 #define S_DIRSYNC 128 /* Directory modifications are synchronous */
230 #define S_NOCMTIME 256 /* Do not update file c/mtime */
231 +#define S_PDIROPS 512 /* Parallel directory operations */
234 * Note that nosuid etc flags are inode-specific: setting some file-system
236 #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
237 #define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
238 #define IS_ONE_SECOND(inode) __IS_FLG(inode, MS_ONE_SECOND)
239 +#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
241 #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
242 #define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
244 atomic_t i_writecount;
247 + struct dynlock i_dcache_lock; /* for parallel directory ops */
251 Index: linux-2.6.7/include/linux/namei.h
252 ===================================================================
253 --- linux-2.6.7.orig/include/linux/namei.h 2004-09-06 22:53:19.000000000 +0400
254 +++ linux-2.6.7/include/linux/namei.h 2004-09-07 14:40:06.000000000 +0400
262 struct open_intent open;