2 fs/namei.c | 66 ++++++++++++++++++++++++++++++++++++++---------------
3 include/linux/fs.h | 11 ++++----
4 3 files changed, 54 insertions(+), 24 deletions(-)
6 Index: linux-2.4.24/fs/namei.c
7 ===================================================================
8 --- linux-2.4.24.orig/fs/namei.c 2004-06-24 09:08:27.000000000 +0400
9 +++ linux-2.4.24/fs/namei.c 2004-06-27 21:32:00.000000000 +0400
12 EXPORT_SYMBOL(intent_release);
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, flags) && !d_invalidate(result)) {
80 @@ -1174,13 +1207,13 @@
84 - down(&dir->d_inode->i_sem);
85 + nd->lock = lock_dir(dir->d_inode, &nd->last);
86 dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
89 error = PTR_ERR(dentry);
91 - up(&dir->d_inode->i_sem);
92 + unlock_dir(dir->d_inode, nd->lock);
97 if (!dentry->d_inode) {
98 error = vfs_create_it(dir->d_inode, dentry,
99 mode & ~current->fs->umask, it);
100 - up(&dir->d_inode->i_sem);
101 + unlock_dir(dir->d_inode, nd->lock);
105 @@ -1203,7 +1236,7 @@
109 - up(&dir->d_inode->i_sem);
110 + unlock_dir(dir->d_inode, nd->lock);
114 @@ -1350,7 +1383,7 @@
118 - down(&dir->d_inode->i_sem);
119 + nd->lock = lock_dir(dir->d_inode, &nd->last);
120 dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
121 putname(nd->last.name);
123 @@ -1368,7 +1401,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 @@ -1461,7 +1494,7 @@
136 - up(&nd.dentry->d_inode->i_sem);
137 + unlock_dir(nd.dentry->d_inode, nd.lock);
141 @@ -1528,7 +1561,7 @@
142 mode & ~current->fs->umask);
145 - up(&nd.dentry->d_inode->i_sem);
146 + unlock_dir(nd.dentry->d_inode, nd.lock);
150 @@ -1638,14 +1671,14 @@
151 if (error != -EOPNOTSUPP)
154 - down(&nd.dentry->d_inode->i_sem);
155 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
156 dentry = lookup_hash_it(&nd.last, nd.dentry, &nd, NULL);
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 @@ -1704,7 +1737,7 @@
168 if (error != -EOPNOTSUPP)
171 - down(&nd.dentry->d_inode->i_sem);
172 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
173 dentry = lookup_hash_it(&nd.last, nd.dentry, &nd, NULL);
174 error = PTR_ERR(dentry);
175 if (!IS_ERR(dentry)) {
176 @@ -1715,7 +1748,7 @@
180 - up(&nd.dentry->d_inode->i_sem);
181 + unlock_dir(nd.dentry->d_inode, nd.lock);
185 @@ -1789,7 +1822,7 @@
186 error = vfs_symlink(nd.dentry->d_inode, dentry, from);
189 - up(&nd.dentry->d_inode->i_sem);
190 + unlock_dir(nd.dentry->d_inode, nd.lock);
194 @@ -1885,7 +1918,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.4.24/fs/inode.c
204 ===================================================================
205 --- linux-2.4.24.orig/fs/inode.c 2004-06-24 09:08:27.000000000 +0400
206 +++ linux-2.4.24/fs/inode.c 2004-06-24 09:08:29.000000000 +0400
208 mapping->host = inode;
209 mapping->gfp_mask = GFP_HIGHUSER;
210 inode->i_mapping = mapping;
211 + dynlock_init(&inode->i_dcache_lock);
215 Index: linux-2.4.24/include/linux/fs.h
216 ===================================================================
217 --- linux-2.4.24.orig/include/linux/fs.h 2004-06-24 09:08:29.000000000 +0400
218 +++ linux-2.4.24/include/linux/fs.h 2004-06-24 09:08:29.000000000 +0400
220 #include <linux/cache.h>
221 #include <linux/stddef.h>
222 #include <linux/string.h>
223 +#include <linux/dynlocks.h>
225 #include <asm/atomic.h>
226 #include <asm/bitops.h>
228 #define S_IMMUTABLE 16 /* Immutable file */
229 #define S_DEAD 32 /* removed, but still open directory */
230 #define S_NOQUOTA 64 /* Inode is not counted to quota */
231 +#define S_PDIROPS 256 /* Parallel directory operations */
234 * Note that nosuid etc flags are inode-specific: setting some file-system
236 #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
237 #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
238 #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
239 +#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
241 #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
244 atomic_t i_writecount;
245 unsigned int i_attr_flags;
247 + struct dynlock i_dcache_lock; /* for parallel directory ops */
249 struct minix_inode_info minix_i;
250 struct ext2_inode_info ext2_i;
254 struct lookup_intent *intent;
259 @@ -1629,12 +1634,6 @@
260 return dget(dentry->d_parent);
263 -static inline void unlock_dir(struct dentry *dir)
265 - up(&dir->d_inode->i_sem);
270 * Whee.. Deadlock country. Happily there are only two VFS
271 * operations that does this..