2 fs/namei.c | 65 +++++++++++++++++++++++++++++++++++++++--------------
3 include/linux/fs.h | 11 ++++----
4 3 files changed, 54 insertions(+), 23 deletions(-)
6 --- linux-2.4.18-chaos/fs/namei.c~vfs-pdirops-2.4.18-chaos 2003-09-16 23:33:47.000000000 +0400
7 +++ linux-2.4.18-chaos-alexey/fs/namei.c 2003-09-17 00:18:45.000000000 +0400
8 @@ -101,6 +101,36 @@ void intent_release(struct lookup_intent
12 +static void *lock_dir(struct inode *dir, struct qstr *name)
16 + if (!IS_PDIROPS(dir)) {
21 + /* OK. fs understands parallel directory operations.
22 + * so, we try to acquire lock for hash of requested
23 + * filename in order to prevent any operations with
24 + * same name in same time -bzzz */
26 + /* calculate name hash */
27 + hash = full_name_hash(name->name, name->len);
29 + /* lock this hash */
30 + return dynlock_lock(&dir->i_dcache_lock, hash, 1, GFP_ATOMIC);
33 +static void unlock_dir(struct inode *dir, void *lock)
35 + if (!IS_PDIROPS(dir)) {
39 + dynlock_unlock(&dir->i_dcache_lock, lock);
42 /* In order to reduce some races, while at the same time doing additional
43 * checking and hopefully speeding things up, we copy filenames to the
44 * kernel data space before using them..
45 @@ -303,10 +333,11 @@ static struct dentry *real_lookup(struct
46 struct dentry * result;
47 struct inode *dir = parent->d_inode;
52 + lock = lock_dir(dir, name);
56 * First re-do the cached lookup just in case it was created
57 * while we waited for the directory semaphore..
58 @@ -330,7 +361,7 @@ again:
63 + unlock_dir(dir, lock);
67 @@ -338,7 +369,7 @@ again:
68 * Uhhuh! Nasty case: the cache was re-populated while
69 * we waited on the semaphore. Need to revalidate.
72 + unlock_dir(dir, lock);
73 if (result->d_op && result->d_op->d_revalidate) {
74 if (!result->d_op->d_revalidate(result, flags) && !d_invalidate(result)) {
76 @@ -1240,13 +1271,13 @@ struct file *filp_open(const char * path
80 - down(&dir->d_inode->i_sem);
81 + nd.lock = lock_dir(dir->d_inode, &nd.last);
82 dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
85 error = PTR_ERR(dentry);
87 - up(&dir->d_inode->i_sem);
88 + unlock_dir(dir->d_inode, nd.lock);
92 @@ -1255,7 +1286,7 @@ do_last:
93 if (!dentry->d_inode) {
94 error = vfs_create_it(dir->d_inode, dentry,
95 mode & ~current->fs->umask, &it);
96 - up(&dir->d_inode->i_sem);
97 + unlock_dir(dir->d_inode, nd.lock);
101 @@ -1270,7 +1301,7 @@ do_last:
105 - up(&dir->d_inode->i_sem);
106 + unlock_dir(dir->d_inode, nd.lock);
110 @@ -1350,7 +1381,7 @@ do_link:
114 - down(&dir->d_inode->i_sem);
115 + nd.lock = lock_dir(dir->d_inode, &nd.last);
116 dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
117 putname(nd.last.name);
119 @@ -1363,7 +1394,7 @@ static struct dentry *lookup_create(stru
121 struct dentry *dentry;
123 - down(&nd->dentry->d_inode->i_sem);
124 + nd->lock = lock_dir(nd->dentry->d_inode, &nd->last);
125 dentry = ERR_PTR(-EEXIST);
126 if (nd->last_type != LAST_NORM)
128 @@ -1452,7 +1483,7 @@ asmlinkage long sys_mknod(const char * f
132 - up(&nd.dentry->d_inode->i_sem);
133 + unlock_dir(nd.dentry->d_inode, nd.lock);
137 @@ -1515,7 +1546,7 @@ asmlinkage long sys_mkdir(const char * p
138 mode & ~current->fs->umask);
141 - up(&nd.dentry->d_inode->i_sem);
142 + unlock_dir(nd.dentry->d_inode, nd.lock);
146 @@ -1625,14 +1656,14 @@ asmlinkage long sys_rmdir(const char * p
147 if (error != -EOPNOTSUPP)
150 - down(&nd.dentry->d_inode->i_sem);
151 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
152 dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
153 error = PTR_ERR(dentry);
154 if (!IS_ERR(dentry)) {
155 error = vfs_rmdir(nd.dentry->d_inode, dentry);
158 - up(&nd.dentry->d_inode->i_sem);
159 + unlock_dir(nd.dentry->d_inode, nd.lock);
163 @@ -1691,7 +1722,7 @@ asmlinkage long sys_unlink(const char *
164 if (error != -EOPNOTSUPP)
167 - down(&nd.dentry->d_inode->i_sem);
168 + nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
169 dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
170 error = PTR_ERR(dentry);
171 if (!IS_ERR(dentry)) {
172 @@ -1702,7 +1733,7 @@ asmlinkage long sys_unlink(const char *
176 - up(&nd.dentry->d_inode->i_sem);
177 + unlock_dir(nd.dentry->d_inode, nd.lock);
181 @@ -1772,7 +1803,7 @@ asmlinkage long sys_symlink(const char *
182 error = vfs_symlink(nd.dentry->d_inode, dentry, from);
185 - up(&nd.dentry->d_inode->i_sem);
186 + unlock_dir(nd.dentry->d_inode, nd.lock);
190 @@ -1864,7 +1895,7 @@ asmlinkage long sys_link(const char * ol
191 error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
194 - up(&nd.dentry->d_inode->i_sem);
195 + unlock_dir(nd.dentry->d_inode, nd.lock);
199 --- linux-2.4.18-chaos/include/linux/fs.h~vfs-pdirops-2.4.18-chaos 2003-09-16 23:33:47.000000000 +0400
200 +++ linux-2.4.18-chaos-alexey/include/linux/fs.h 2003-09-17 00:16:08.000000000 +0400
202 #include <linux/cache.h>
203 #include <linux/stddef.h>
204 #include <linux/string.h>
205 +#include <linux/dynlocks.h>
207 #include <asm/atomic.h>
208 #include <asm/bitops.h>
209 @@ -136,6 +137,7 @@ extern int leases_enable, dir_notify_ena
210 #define S_IMMUTABLE 16 /* Immutable file */
211 #define S_DEAD 32 /* removed, but still open directory */
212 #define S_NOQUOTA 64 /* Inode is not counted to quota */
213 +#define S_PDIROPS 256 /* Parallel directory operations */
216 * Note that nosuid etc flags are inode-specific: setting some file-system
217 @@ -162,6 +164,7 @@ extern int leases_enable, dir_notify_ena
218 #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
219 #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
220 #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
221 +#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
223 #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
225 @@ -491,6 +494,7 @@ struct inode {
226 atomic_t i_writecount;
227 unsigned int i_attr_flags;
229 + struct dynlock i_dcache_lock; /* for parallel directory ops */
231 struct minix_inode_info minix_i;
232 struct ext2_inode_info ext2_i;
233 @@ -714,6 +718,7 @@ struct nameidata {
236 struct lookup_intent *intent;
240 #define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
241 @@ -1611,12 +1616,6 @@ static inline struct dentry *get_parent(
242 return dget(dentry->d_parent);
245 -static inline void unlock_dir(struct dentry *dir)
247 - up(&dir->d_inode->i_sem);
252 * Whee.. Deadlock country. Happily there are only two VFS
253 * operations that does this..
254 --- linux-2.4.18-chaos/fs/inode.c~vfs-pdirops-2.4.18-chaos 2003-09-16 23:33:48.000000000 +0400
255 +++ linux-2.4.18-chaos-alexey/fs/inode.c 2003-09-16 23:47:45.000000000 +0400
256 @@ -119,6 +119,7 @@ static struct inode *alloc_inode(struct
257 mapping->host = inode;
258 mapping->gfp_mask = GFP_HIGHUSER;
259 inode->i_mapping = mapping;
260 + dynlock_init(&inode->i_dcache_lock);