2 fs/namei.c | 66 ++++++++++++++++++++++++++++++++++++++---------------
3 include/linux/fs.h | 11 ++++----
4 3 files changed, 54 insertions(+), 24 deletions(-)
6 Index: linux-2.4.20-rh/fs/namei.c
7 ===================================================================
8 --- linux-2.4.20-rh.orig/fs/namei.c 2003-09-04 20:58:33.000000000 +0800
9 +++ linux-2.4.20-rh/fs/namei.c 2003-09-04 21:21:20.000000000 +0800
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 @@ -1180,13 +1210,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, 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 @@ -1209,7 +1239,7 @@
107 - up(&dir->d_inode->i_sem);
108 + unlock_dir(dir->d_inode, nd->lock);
112 @@ -1362,7 +1392,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, it);
119 putname(nd->last.name);
121 @@ -1380,7 +1410,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 @@ -1469,7 +1499,7 @@
134 - up(&nd.dentry->d_inode->i_sem);
135 + unlock_dir(nd.dentry->d_inode, nd.lock);
139 @@ -1532,7 +1562,7 @@
140 mode & ~current->fs->umask);
143 - up(&nd.dentry->d_inode->i_sem);
144 + unlock_dir(nd.dentry->d_inode, nd.lock);
148 @@ -1642,14 +1672,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, 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 @@ -1708,7 +1738,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, NULL);
172 error = PTR_ERR(dentry);
173 if (!IS_ERR(dentry)) {
174 @@ -1719,7 +1749,7 @@
178 - up(&nd.dentry->d_inode->i_sem);
179 + unlock_dir(nd.dentry->d_inode, nd.lock);
183 @@ -1789,7 +1819,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 @@ -1881,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: linux-2.4.20-rh/include/linux/fs.h
202 ===================================================================
203 --- linux-2.4.20-rh.orig/include/linux/fs.h 2003-09-04 20:59:14.000000000 +0800
204 +++ linux-2.4.20-rh/include/linux/fs.h 2003-09-04 21:03:46.000000000 +0800
206 #include <linux/cache.h>
207 #include <linux/stddef.h>
208 #include <linux/string.h>
209 +#include <linux/dynlocks.h>
211 #include <asm/atomic.h>
212 #include <asm/bitops.h>
214 #define S_IMMUTABLE 16 /* Immutable file */
215 #define S_DEAD 32 /* removed, but still open directory */
216 #define S_NOQUOTA 64 /* Inode is not counted to quota */
217 +#define S_PDIROPS 256 /* Parallel directory operations */
220 * Note that nosuid etc flags are inode-specific: setting some file-system
222 #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
223 #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
224 #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
225 +#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
227 #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
230 atomic_t i_writecount;
231 unsigned int i_attr_flags;
233 + struct dynlock i_dcache_lock; /* for parallel directory ops */
235 struct minix_inode_info minix_i;
236 struct ext2_inode_info ext2_i;
240 struct lookup_intent *intent;
245 @@ -1621,12 +1626,6 @@
246 return dget(dentry->d_parent);
249 -static inline void unlock_dir(struct dentry *dir)
251 - up(&dir->d_inode->i_sem);
256 * Whee.. Deadlock country. Happily there are only two VFS
257 * operations that does this..
258 Index: linux-2.4.20-rh/fs/inode.c
259 ===================================================================
260 --- linux-2.4.20-rh.orig/fs/inode.c 2003-09-04 20:58:35.000000000 +0800
261 +++ linux-2.4.20-rh/fs/inode.c 2003-09-04 21:03:46.000000000 +0800
263 mapping->host = inode;
264 mapping->gfp_mask = GFP_HIGHUSER;
265 inode->i_mapping = mapping;
266 + dynlock_init(&inode->i_dcache_lock);