Whamcloud - gitweb
b=3119
[fs/lustre-release.git] / lustre / kernel_patches / patches / vfs-pdirops-2.4.18-chaos.patch
1  fs/inode.c         |    1 
2  fs/namei.c         |   65 +++++++++++++++++++++++++++++++++++++++--------------
3  include/linux/fs.h |   11 ++++----
4  3 files changed, 54 insertions(+), 23 deletions(-)
5
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
9  
10  }
11  
12 +static void *lock_dir(struct inode *dir, struct qstr *name)
13 +{
14 +       unsigned long hash;
15 +       
16 +       if (!IS_PDIROPS(dir)) {
17 +               down(&dir->i_sem);
18 +               return 0;
19 +       }
20 +
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 */
25 +
26 +       /* calculate name hash */
27 +       hash = full_name_hash(name->name, name->len);
28 +
29 +       /* lock this hash */
30 +       return dynlock_lock(&dir->i_dcache_lock, hash, 1, GFP_ATOMIC);
31 +}
32 +
33 +static void unlock_dir(struct inode *dir, void *lock)
34 +{
35 +       if (!IS_PDIROPS(dir)) {
36 +               up(&dir->i_sem);
37 +               return;
38 +       }
39 +       dynlock_unlock(&dir->i_dcache_lock, lock);
40 +}
41 +
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;
48          int counter = 0;
49 +       void *lock;
50  
51  again:
52 +       lock = lock_dir(dir, name);
53          counter++;
54 -       down(&dir->i_sem);
55         /*
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:
59                         else
60                                 result = dentry;
61                 }
62 -               up(&dir->i_sem);
63 +               unlock_dir(dir, lock);
64                 return result;
65         }
66  
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.
70          */
71 -       up(&dir->i_sem);
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)) {
75                         dput(result);
76 @@ -1240,13 +1271,13 @@ struct file *filp_open(const char * path
77                 goto exit;
78  
79         dir = nd.dentry;
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);
83  
84  do_last:
85         error = PTR_ERR(dentry);
86         if (IS_ERR(dentry)) {
87 -               up(&dir->d_inode->i_sem);
88 +               unlock_dir(dir->d_inode, nd.lock);
89                 goto exit;
90         }
91  
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);
98                 dput(nd.dentry);
99                 nd.dentry = dentry;
100                 if (error)
101 @@ -1270,7 +1301,7 @@ do_last:
102         /*
103          * It already exists.
104          */
105 -       up(&dir->d_inode->i_sem);
106 +       unlock_dir(dir->d_inode, nd.lock);
107  
108         error = -EEXIST;
109         if (flag & O_EXCL)
110 @@ -1350,7 +1381,7 @@ do_link:
111                 goto exit;
112         }
113         dir = nd.dentry;
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);
118         goto do_last;
119 @@ -1363,7 +1394,7 @@ static struct dentry *lookup_create(stru
120  {
121         struct dentry *dentry;
122  
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)
127                 goto fail;
128 @@ -1452,7 +1483,7 @@ asmlinkage long sys_mknod(const char * f
129                 }
130                 dput(dentry);
131         }
132 -       up(&nd.dentry->d_inode->i_sem);
133 +       unlock_dir(nd.dentry->d_inode, nd.lock);
134  out2:
135         path_release(&nd);
136  out:
137 @@ -1515,7 +1546,7 @@ asmlinkage long sys_mkdir(const char * p
138                                           mode & ~current->fs->umask);
139                         dput(dentry);
140                 }
141 -               up(&nd.dentry->d_inode->i_sem);
142 +               unlock_dir(nd.dentry->d_inode, nd.lock);
143  out2:
144                 path_release(&nd);
145  out:
146 @@ -1625,14 +1656,14 @@ asmlinkage long sys_rmdir(const char * p
147                 if (error != -EOPNOTSUPP)
148                         goto exit1;
149         }
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);
156                 dput(dentry);
157         }
158 -       up(&nd.dentry->d_inode->i_sem);
159 +       unlock_dir(nd.dentry->d_inode, nd.lock);
160  exit1:
161         path_release(&nd);
162  exit:
163 @@ -1691,7 +1722,7 @@ asmlinkage long sys_unlink(const char * 
164                 if (error != -EOPNOTSUPP)
165                         goto exit1;
166         }
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 * 
173         exit2:
174                 dput(dentry);
175         }
176 -       up(&nd.dentry->d_inode->i_sem);
177 +       unlock_dir(nd.dentry->d_inode, nd.lock);
178  exit1:
179         path_release(&nd);
180  exit:
181 @@ -1772,7 +1803,7 @@ asmlinkage long sys_symlink(const char *
182                         error = vfs_symlink(nd.dentry->d_inode, dentry, from);
183                         dput(dentry);
184                 }
185 -               up(&nd.dentry->d_inode->i_sem);
186 +               unlock_dir(nd.dentry->d_inode, nd.lock);
187         out2:
188                 path_release(&nd);
189         out:
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);
192                         dput(new_dentry);
193                 }
194 -               up(&nd.dentry->d_inode->i_sem);
195 +               unlock_dir(nd.dentry->d_inode, nd.lock);
196  out_release:
197                 path_release(&nd);
198  out:
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
201 @@ -21,6 +21,7 @@
202  #include <linux/cache.h>
203  #include <linux/stddef.h>
204  #include <linux/string.h>
205 +#include <linux/dynlocks.h>
206  
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 */
214  
215  /*
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)
222  
223  #define IS_DEADDIR(inode)      ((inode)->i_flags & S_DEAD)
224  
225 @@ -491,6 +494,7 @@ struct inode {
226         atomic_t                i_writecount;
227         unsigned int            i_attr_flags;
228         __u32                   i_generation;
229 +       struct dynlock          i_dcache_lock;  /* for parallel directory ops */
230         union {
231                 struct minix_inode_info         minix_i;
232                 struct ext2_inode_info          ext2_i;
233 @@ -714,6 +718,7 @@ struct nameidata {
234         unsigned int flags;
235         int last_type;
236         struct lookup_intent *intent;
237 +       void *lock;
238  };
239  
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);
243  }
244  
245 -static inline void unlock_dir(struct dentry *dir)
246 -{
247 -       up(&dir->d_inode->i_sem);
248 -       dput(dir);
249 -}
250 -
251  /*
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);
261         }
262         return inode;
263  }
264
265 _