2 fs/namei.c | 66 ++++++++++++++++++++++++++++++++++++++---------------
3 include/linux/fs.h | 11 ++++----
4 3 files changed, 54 insertions(+), 24 deletions(-)
7 ===================================================================
8 --- lum.orig/fs/namei.c 2004-06-07 17:19:45.000000000 -0400
9 +++ lum/fs/namei.c 2004-06-07 17:22:39.000000000 -0400
12 EXPORT_SYMBOL(intent_release);
14 +static 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);
35 +static void unlock_dir(struct inode *dir, void *lock)
37 + if (!IS_PDIROPS(dir)) {
41 + dynlock_unlock(&dir->i_dcache_lock, lock);
44 /* In order to reduce some races, while at the same time doing additional
45 * checking and hopefully speeding things up, we copy filenames to the
46 * kernel data space before using them..
48 struct dentry * result;
49 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, flags) && !d_invalidate(result)) {
78 @@ -1169,13 +1200,13 @@
82 - down(&dir->d_inode->i_sem);
83 + nd->lock = lock_dir(dir->d_inode, &nd->last);
84 dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
87 error = PTR_ERR(dentry);
89 - up(&dir->d_inode->i_sem);
90 + unlock_dir(dir->d_inode, nd->lock);
95 if (!dentry->d_inode) {
96 error = vfs_create_it(dir->d_inode, dentry,
97 mode & ~current->fs->umask, it);
98 - up(&dir->d_inode->i_sem);
99 + unlock_dir(dir->d_inode, nd->lock);
103 @@ -1198,7 +1229,7 @@
107 - up(&dir->d_inode->i_sem);
108 + unlock_dir(dir->d_inode, nd->lock);
112 @@ -1345,7 +1376,7 @@
116 - down(&dir->d_inode->i_sem);
117 + nd->lock = lock_dir(dir->d_inode, &nd->last);
118 dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
119 putname(nd->last.name);
121 @@ -1363,7 +1394,7 @@
123 struct dentry *dentry;
125 - down(&nd->dentry->d_inode->i_sem);
126 + nd->lock = lock_dir(nd->dentry->d_inode, &nd->last);
127 dentry = ERR_PTR(-EEXIST);
128 if (nd->last_type != LAST_NORM)
130 @@ -1456,7 +1487,7 @@
134 - up(&nd.dentry->d_inode->i_sem);
135 + unlock_dir(nd.dentry->d_inode, nd.lock);
139 @@ -1523,7 +1554,7 @@
140 mode & ~current->fs->umask);
143 - up(&nd.dentry->d_inode->i_sem);
144 + unlock_dir(nd.dentry->d_inode, nd.lock);
148 @@ -1633,14 +1664,14 @@
149 if (error != -EOPNOTSUPP)
152 - down(&nd.dentry->d_inode->i_sem);
153 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
154 dentry = lookup_hash_it(&nd.last, nd.dentry, &nd, NULL);
155 error = PTR_ERR(dentry);
156 if (!IS_ERR(dentry)) {
157 error = vfs_rmdir(nd.dentry->d_inode, dentry);
160 - up(&nd.dentry->d_inode->i_sem);
161 + unlock_dir(nd.dentry->d_inode, nd.lock);
165 @@ -1699,7 +1730,7 @@
166 if (error != -EOPNOTSUPP)
169 - down(&nd.dentry->d_inode->i_sem);
170 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
171 dentry = lookup_hash_it(&nd.last, nd.dentry, &nd, NULL);
172 error = PTR_ERR(dentry);
173 if (!IS_ERR(dentry)) {
174 @@ -1710,7 +1741,7 @@
178 - up(&nd.dentry->d_inode->i_sem);
179 + unlock_dir(nd.dentry->d_inode, nd.lock);
183 @@ -1784,7 +1815,7 @@
184 error = vfs_symlink(nd.dentry->d_inode, dentry, from);
187 - up(&nd.dentry->d_inode->i_sem);
188 + unlock_dir(nd.dentry->d_inode, nd.lock);
192 @@ -1880,7 +1911,7 @@
193 error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
196 - up(&nd.dentry->d_inode->i_sem);
197 + unlock_dir(nd.dentry->d_inode, nd.lock);
201 Index: lum/fs/inode.c
202 ===================================================================
203 --- lum.orig/fs/inode.c 2004-06-07 17:19:45.000000000 -0400
204 +++ lum/fs/inode.c 2004-06-07 17:21:10.000000000 -0400
206 mapping->host = inode;
207 mapping->gfp_mask = GFP_HIGHUSER;
208 inode->i_mapping = mapping;
209 + dynlock_init(&inode->i_dcache_lock);
213 Index: lum/include/linux/fs.h
214 ===================================================================
215 --- lum.orig/include/linux/fs.h 2004-06-07 17:19:45.000000000 -0400
216 +++ lum/include/linux/fs.h 2004-06-07 17:21:10.000000000 -0400
218 #include <linux/cache.h>
219 #include <linux/stddef.h>
220 #include <linux/string.h>
221 +#include <linux/dynlocks.h>
223 #include <asm/atomic.h>
224 #include <asm/bitops.h>
226 #define S_IMMUTABLE 16 /* Immutable file */
227 #define S_DEAD 32 /* removed, but still open directory */
228 #define S_NOQUOTA 64 /* Inode is not counted to quota */
229 +#define S_PDIROPS 256 /* Parallel directory operations */
232 * Note that nosuid etc flags are inode-specific: setting some file-system
234 #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
235 #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
236 #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
237 +#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
239 #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
242 atomic_t i_writecount;
243 unsigned int i_attr_flags;
245 + struct dynlock i_dcache_lock; /* for parallel directory ops */
247 struct minix_inode_info minix_i;
248 struct ext2_inode_info ext2_i;
252 struct lookup_intent *intent;
257 @@ -1631,12 +1636,6 @@
258 return dget(dentry->d_parent);
261 -static inline void unlock_dir(struct dentry *dir)
263 - up(&dir->d_inode->i_sem);
268 * Whee.. Deadlock country. Happily there are only two VFS
269 * operations that does this..