Whamcloud - gitweb
7587ad28a61c4d8009c81b3edd3b6fdd070da245
[fs/lustre-release.git] / lustre / kernel_patches / patches / vfs_intent-2.4.21-chaos.patch
1  fs/dcache.c               |   19 ++
2  fs/exec.c                 |   17 +-
3  fs/namei.c                |  295 +++++++++++++++++++++++++++++++++++++++-------
4  fs/namespace.c            |   28 +++-
5  fs/open.c                 |  172 +++++++++++++++++++-------
6  fs/stat.c                 |   52 +++++---
7  include/linux/dcache.h    |   60 +++++++++
8  include/linux/fs.h        |   32 ++++
9  include/linux/fs_struct.h |    4 
10  kernel/exit.c             |    3 
11  kernel/fork.c             |    3 
12  kernel/ksyms.c            |    1 
13  12 files changed, 558 insertions(+), 128 deletions(-)
14
15 Index: linux-2.4.21-chaos/fs/dcache.c
16 ===================================================================
17 --- linux-2.4.21-chaos.orig/fs/dcache.c 2003-09-19 03:49:54.000000000 +0400
18 +++ linux-2.4.21-chaos/fs/dcache.c      2003-12-12 17:02:47.000000000 +0300
19 @@ -186,6 +186,13 @@
20                 spin_unlock(&dcache_lock);
21                 return 0;
22         }
23 +
24 +       /* network invalidation by Lustre */
25 +       if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
26 +               spin_unlock(&dcache_lock);
27 +               return 0;
28 +       }
29 +
30         /*
31          * Check whether to do a partial shrink_dcache
32          * to get rid of unused child entries.
33 @@ -847,13 +854,19 @@
34   * Adds a dentry to the hash according to its name.
35   */
36   
37 -void d_rehash(struct dentry * entry)
38 +void __d_rehash(struct dentry * entry, int lock)
39  {
40         struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
41         if (!list_empty(&entry->d_hash)) BUG();
42 -       spin_lock(&dcache_lock);
43 +       if (lock) spin_lock(&dcache_lock);
44         list_add(&entry->d_hash, list);
45 -       spin_unlock(&dcache_lock);
46 +       if (lock) spin_unlock(&dcache_lock);
47 +}
48 +EXPORT_SYMBOL(__d_rehash);
49 +
50 +void d_rehash(struct dentry * entry)
51 +{
52 +       __d_rehash(entry, 1);
53  }
54  
55  #define do_switch(x,y) do { \
56 Index: linux-2.4.21-chaos/fs/exec.c
57 ===================================================================
58 --- linux-2.4.21-chaos.orig/fs/exec.c   2003-12-05 07:55:47.000000000 +0300
59 +++ linux-2.4.21-chaos/fs/exec.c        2003-12-12 17:02:47.000000000 +0300
60 @@ -119,8 +119,10 @@
61         struct file * file;
62         struct nameidata nd;
63         int error;
64 +       struct lookup_intent it = { .it_op = IT_OPEN,
65 +                                   .it_flags = FMODE_READ|FMODE_EXEC };
66  
67 -       error = user_path_walk(library, &nd);
68 +       error = user_path_walk_it(library, &nd, &it);
69         if (error)
70                 goto out;
71  
72 @@ -132,7 +134,8 @@
73         if (error)
74                 goto exit;
75  
76 -       file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
77 +       file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
78 +       intent_release(&it);
79         error = PTR_ERR(file);
80         if (IS_ERR(file))
81                 goto out;
82 @@ -400,8 +403,10 @@
83         struct inode *inode;
84         struct file *file;
85         int err = 0;
86 +       struct lookup_intent it = { .it_op = IT_OPEN,
87 +                                   .it_flags = FMODE_READ|FMODE_EXEC };
88  
89 -       err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
90 +       err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
91         file = ERR_PTR(err);
92         if (!err) {
93                 inode = nd.dentry->d_inode;
94 @@ -413,7 +418,8 @@
95                                 err = -EACCES;
96                         file = ERR_PTR(err);
97                         if (!err) {
98 -                               file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
99 +                               file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
100 +                               intent_release(&it);
101                                 if (!IS_ERR(file)) {
102                                         err = deny_write_access(file);
103                                         if (err) {
104 @@ -425,6 +431,7 @@
105                                 return file;
106                         }
107                 }
108 +               intent_release(&it);
109                 path_release(&nd);
110         }
111         goto out;
112 @@ -1348,7 +1355,7 @@
113                 goto close_fail;
114         if (!file->f_op->write)
115                 goto close_fail;
116 -       if (do_truncate(file->f_dentry, 0) != 0)
117 +       if (do_truncate(file->f_dentry, 0, 0) != 0)
118                 goto close_fail;
119  
120         retval = binfmt->core_dump(signr, regs, file);
121 Index: linux-2.4.21-chaos/fs/namei.c
122 ===================================================================
123 --- linux-2.4.21-chaos.orig/fs/namei.c  2003-07-15 04:41:01.000000000 +0400
124 +++ linux-2.4.21-chaos/fs/namei.c       2003-12-12 17:03:37.000000000 +0300
125 @@ -94,6 +94,13 @@
126   * XEmacs seems to be relying on it...
127   */
128  
129 +void intent_release(struct lookup_intent *it)
130 +{
131 +       if (it && it->it_op_release)
132 +               it->it_op_release(it);
133 +
134 +}
135 +
136  /* In order to reduce some races, while at the same time doing additional
137   * checking and hopefully speeding things up, we copy filenames to the
138   * kernel data space before using them..
139 @@ -260,10 +267,19 @@
140   * Internal lookup() using the new generic dcache.
141   * SMP-safe
142   */
143 -static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
144 +static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
145 +                                   int flags, struct lookup_intent *it)
146  {
147         struct dentry * dentry = d_lookup(parent, name);
148  
149 +       if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
150 +               if (!dentry->d_op->d_revalidate_it(dentry, flags, it) &&
151 +                   !d_invalidate(dentry)) {
152 +                       dput(dentry);
153 +                       dentry = NULL;
154 +               }
155 +               return dentry;
156 +       } else
157         if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
158                 if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
159                         dput(dentry);
160 @@ -281,11 +297,15 @@
161   * make sure that nobody added the entry to the dcache in the meantime..
162   * SMP-safe
163   */
164 -static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
165 +static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
166 +                                 int flags, struct lookup_intent *it)
167  {
168         struct dentry * result;
169         struct inode *dir = parent->d_inode;
170 +       int counter = 0;
171  
172 +again:
173 +       counter++;
174         down(&dir->i_sem);
175         /*
176          * First re-do the cached lookup just in case it was created
177 @@ -300,6 +320,9 @@
178                 result = ERR_PTR(-ENOMEM);
179                 if (dentry) {
180                         lock_kernel();
181 +                       if (dir->i_op->lookup_it)
182 +                               result = dir->i_op->lookup_it(dir, dentry, it, flags);
183 +                       else
184                         result = dir->i_op->lookup(dir, dentry);
185                         unlock_kernel();
186                         if (result)
187 @@ -321,6 +344,15 @@
188                         dput(result);
189                         result = ERR_PTR(-ENOENT);
190                 }
191 +       } else if (result->d_op && result->d_op->d_revalidate_it) {
192 +               if (!result->d_op->d_revalidate_it(result, flags, it) &&
193 +                   !d_invalidate(result)) {
194 +                       dput(result);
195 +                       if (counter > 10)
196 +                               result = ERR_PTR(-ESTALE);
197 +                       if (!IS_ERR(result))
198 +                               goto again;
199 +               }
200         }
201         return result;
202  }
203 @@ -332,7 +364,8 @@
204   * Without that kind of total limit, nasty chains of consecutive
205   * symlinks can cause almost arbitrarily long lookups. 
206   */
207 -static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
208 +static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
209 +                                struct lookup_intent *it)
210  {
211         int err;
212         if (current->link_count >= 8)
213 @@ -346,10 +379,12 @@
214         current->link_count++;
215         current->total_link_count++;
216         UPDATE_ATIME(dentry->d_inode);
217 +       nd->intent = it;
218         err = dentry->d_inode->i_op->follow_link(dentry, nd);
219         current->link_count--;
220         return err;
221  loop:
222 +       intent_release(it);
223         path_release(nd);
224         return -ELOOP;
225  }
226 @@ -447,7 +482,8 @@
227   *
228   * We expect 'base' to be positive and a directory.
229   */
230 -int link_path_walk(const char * name, struct nameidata *nd)
231 +int link_path_walk_it(const char *name, struct nameidata *nd,
232 +                     struct lookup_intent *it)
233  {
234         struct dentry *dentry;
235         struct inode *inode;
236 @@ -524,12 +560,12 @@
237                                 break;
238                 }
239                 /* This does the actual lookups.. */
240 -               dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
241 +               dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
242                 if (!dentry) {
243                         err = -EWOULDBLOCKIO;
244                         if (atomic)
245                                 break;
246 -                       dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
247 +                       dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
248                         err = PTR_ERR(dentry);
249                         if (IS_ERR(dentry))
250                                 break;
251 @@ -547,7 +583,7 @@
252                         goto out_dput;
253  
254                 if (inode->i_op->follow_link) {
255 -                       err = do_follow_link(dentry, nd);
256 +                       err = do_follow_link(dentry, nd, NULL);
257                         dput(dentry);
258                         if (err)
259                                 goto return_err;
260 @@ -563,7 +599,7 @@
261                         nd->dentry = dentry;
262                 }
263                 err = -ENOTDIR; 
264 -               if (!inode->i_op->lookup)
265 +               if (!inode->i_op->lookup && !inode->i_op->lookup_it)
266                         break;
267                 continue;
268                 /* here ends the main loop */
269 @@ -590,12 +626,12 @@
270                         if (err < 0)
271                                 break;
272                 }
273 -               dentry = cached_lookup(nd->dentry, &this, 0);
274 +               dentry = cached_lookup(nd->dentry, &this, 0, it);
275                 if (!dentry) {
276                         err = -EWOULDBLOCKIO;
277                         if (atomic)
278                                 break;
279 -                       dentry = real_lookup(nd->dentry, &this, 0);
280 +                       dentry = real_lookup(nd->dentry, &this, 0, it);
281                         err = PTR_ERR(dentry);
282                         if (IS_ERR(dentry))
283                                 break;
284 @@ -605,7 +641,7 @@
285                 inode = dentry->d_inode;
286                 if ((lookup_flags & LOOKUP_FOLLOW)
287                     && inode && inode->i_op && inode->i_op->follow_link) {
288 -                       err = do_follow_link(dentry, nd);
289 +                       err = do_follow_link(dentry, nd, it);
290                         dput(dentry);
291                         if (err)
292                                 goto return_err;
293 @@ -619,7 +655,8 @@
294                         goto no_inode;
295                 if (lookup_flags & LOOKUP_DIRECTORY) {
296                         err = -ENOTDIR; 
297 -                       if (!inode->i_op || !inode->i_op->lookup)
298 +                       if (!inode->i_op ||
299 +                           (!inode->i_op->lookup && !inode->i_op->lookup_it))
300                                 break;
301                 }
302                 goto return_base;
303 @@ -643,6 +680,25 @@
304                  * Check the cached dentry for staleness.
305                  */
306                 dentry = nd->dentry;
307 +               if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
308 +                       err = -ESTALE;
309 +                       if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) {
310 +                               struct dentry *new;
311 +                               err = permission(dentry->d_parent->d_inode,
312 +                                               MAY_EXEC);
313 +                               if (err)
314 +                                       break;
315 +                               new = real_lookup(dentry->d_parent,
316 +                                               &dentry->d_name, 0, NULL);
317 +                               d_invalidate(dentry);
318 +                               dput(dentry);
319 +                               if (IS_ERR(new)) { 
320 +                                       err = PTR_ERR(new);
321 +                                       break;
322 +                               }
323 +                               nd->dentry = new;
324 +                       }
325 +               } else
326                 if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
327                         err = -ESTALE;
328                         if (!dentry->d_op->d_revalidate(dentry, 0)) {
329 @@ -656,15 +712,28 @@
330                 dput(dentry);
331                 break;
332         }
333 +       if (err)
334 +               intent_release(it);
335         path_release(nd);
336  return_err:
337         return err;
338  }
339  
340 +int link_path_walk(const char * name, struct nameidata *nd)
341 +{
342 +       return link_path_walk_it(name, nd, NULL);
343 +}
344 +
345 +int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
346 +{
347 +       current->total_link_count = 0;
348 +       return link_path_walk_it(name, nd, it);
349 +}
350 +
351  int path_walk(const char * name, struct nameidata *nd)
352  {
353         current->total_link_count = 0;
354 -       return link_path_walk(name, nd);
355 +       return link_path_walk_it(name, nd, NULL);
356  }
357  
358  /* SMP-safe */
359 @@ -749,6 +818,17 @@
360  }
361  
362  /* SMP-safe */
363 +int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
364 +                  struct lookup_intent *it)
365 +{
366 +       int error = 0;
367 +       if (path_init(path, flags, nd))
368 +               error = path_walk_it(path, nd, it);
369 +       return error;
370 +}
371 +
372 +
373 +/* SMP-safe */
374  int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
375  {
376         int error = 0;
377 @@ -763,6 +843,7 @@
378  {
379         nd->last_type = LAST_ROOT; /* if there are only slashes... */
380         nd->flags = flags;
381 +       nd->intent = NULL;
382         if (*name=='/')
383                 return walk_init_root(name,nd);
384         read_lock(&current->fs->lock);
385 @@ -777,7 +858,8 @@
386   * needs parent already locked. Doesn't follow mounts.
387   * SMP-safe.
388   */
389 -struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
390 +struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
391 +                              struct lookup_intent *it)
392  {
393         struct dentry * dentry;
394         struct inode *inode;
395 @@ -800,13 +882,16 @@
396                         goto out;
397         }
398  
399 -       dentry = cached_lookup(base, name, 0);
400 +       dentry = cached_lookup(base, name, 0, it);
401         if (!dentry) {
402                 struct dentry *new = d_alloc(base, name);
403                 dentry = ERR_PTR(-ENOMEM);
404                 if (!new)
405                         goto out;
406                 lock_kernel();
407 +               if (inode->i_op->lookup_it)
408 +                       dentry = inode->i_op->lookup_it(inode, new, it, 0);
409 +               else
410                 dentry = inode->i_op->lookup(inode, new);
411                 unlock_kernel();
412                 if (!dentry)
413 @@ -818,6 +903,12 @@
414         return dentry;
415  }
416  
417 +struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
418 +{
419 +       return lookup_hash_it(name, base, NULL);
420 +}
421 +
422 +
423  /* SMP-safe */
424  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
425  {
426 @@ -839,7 +930,7 @@
427         }
428         this.hash = end_name_hash(hash);
429  
430 -       return lookup_hash(&this, base);
431 +       return lookup_hash_it(&this, base, NULL);
432  access:
433         return ERR_PTR(-EACCES);
434  }
435 @@ -870,6 +961,23 @@
436         return err;
437  }
438  
439 +int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
440 +                  struct lookup_intent *it)
441 +{
442 +       char *tmp;
443 +       int err;
444 +
445 +       tmp = getname(name);
446 +       err = PTR_ERR(tmp);
447 +       if (!IS_ERR(tmp)) {
448 +               err = 0;
449 +               if (path_init(tmp, flags, nd))
450 +                       err = path_walk_it(tmp, nd, it);
451 +               putname(tmp);
452 +       }
453 +       return err;
454 +}
455 +
456  /*
457   * It's inline, so penalty for filesystems that don't use sticky bit is
458   * minimal.
459 @@ -967,7 +1075,8 @@
460         return retval;
461  }
462  
463 -int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
464 +static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode,
465 +                        struct lookup_intent *it)
466  {
467         int error;
468  
469 @@ -980,12 +1089,15 @@
470                 goto exit_lock;
471  
472         error = -EACCES;        /* shouldn't it be ENOSYS? */
473 -       if (!dir->i_op || !dir->i_op->create)
474 +       if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it))
475                 goto exit_lock;
476  
477         DQUOT_INIT(dir);
478         lock_kernel();
479 -       error = dir->i_op->create(dir, dentry, mode);
480 +       if (dir->i_op->create_it)
481 +               error = dir->i_op->create_it(dir, dentry, mode, it);
482 +       else
483 +               error = dir->i_op->create(dir, dentry, mode);
484         unlock_kernel();
485  exit_lock:
486         up(&dir->i_zombie);
487 @@ -994,6 +1106,11 @@
488         return error;
489  }
490  
491 +int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
492 +{
493 +       return vfs_create_it(dir, dentry, mode, NULL);
494 +}
495 +
496  /*
497   *     open_namei()
498   *
499 @@ -1008,7 +1125,8 @@
500   * for symlinks (where the permissions are checked later).
501   * SMP-safe
502   */
503 -int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
504 +int open_namei_it(const char *pathname, int flag, int mode,
505 +                 struct nameidata *nd, struct lookup_intent *it)
506  {
507         int acc_mode, error = 0;
508         struct inode *inode;
509 @@ -1018,11 +1136,14 @@
510  
511         acc_mode = ACC_MODE(flag);
512  
513 +       if (it)
514 +               it->it_flags = flag;
515 +
516         /*
517          * The simplest case - just a plain lookup.
518          */
519         if (!(flag & O_CREAT)) {
520 -               error = path_lookup(pathname, lookup_flags(flag), nd);
521 +               error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
522                 if (error)
523                         return error;
524                 dentry = nd->dentry;
525 @@ -1032,6 +1153,10 @@
526         /*
527          * Create - we need to know the parent.
528          */
529 +       if (it) {
530 +               it->it_create_mode = mode;
531 +               it->it_op |= IT_CREAT;
532 +       }
533         error = path_lookup(pathname, LOOKUP_PARENT, nd);
534         if (error)
535                 return error;
536 @@ -1047,7 +1172,7 @@
537  
538         dir = nd->dentry;
539         down(&dir->d_inode->i_sem);
540 -       dentry = lookup_hash(&nd->last, nd->dentry);
541 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
542  
543  do_last:
544         error = PTR_ERR(dentry);
545 @@ -1056,11 +1181,12 @@
546                 goto exit;
547         }
548  
549 +       it->it_create_mode = mode;
550         /* Negative dentry, just create the file */
551         if (!dentry->d_inode) {
552                 if (!IS_POSIXACL(dir->d_inode))
553                         mode &= ~current->fs->umask;
554 -               error = vfs_create(dir->d_inode, dentry, mode);
555 +               error = vfs_create_it(dir->d_inode, dentry, mode, it);
556                 up(&dir->d_inode->i_sem);
557                 dput(nd->dentry);
558                 nd->dentry = dentry;
559 @@ -1164,7 +1290,7 @@
560                 if (!error) {
561                         DQUOT_INIT(inode);
562                         
563 -                       error = do_truncate(dentry, 0);
564 +                       error = do_truncate(dentry, 0, 1);
565                 }
566                 put_write_access(inode);
567                 if (error)
568 @@ -1176,8 +1302,10 @@
569         return 0;
570  
571  exit_dput:
572 +       intent_release(it);
573         dput(dentry);
574  exit:
575 +       intent_release(it);
576         path_release(nd);
577         return error;
578  
579 @@ -1196,7 +1324,10 @@
580          * are done. Procfs-like symlinks just set LAST_BIND.
581          */
582         UPDATE_ATIME(dentry->d_inode);
583 +       nd->intent = it;
584         error = dentry->d_inode->i_op->follow_link(dentry, nd);
585 +       if (error)
586 +               intent_release(it);
587         dput(dentry);
588         if (error)
589                 return error;
590 @@ -1218,13 +1349,20 @@
591         }
592         dir = nd->dentry;
593         down(&dir->d_inode->i_sem);
594 -       dentry = lookup_hash(&nd->last, nd->dentry);
595 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
596         putname(nd->last.name);
597         goto do_last;
598  }
599  
600 +int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
601 +{
602 +       return open_namei_it(pathname, flag, mode, nd, NULL);
603 +}
604 +
605 +
606  /* SMP-safe */
607 -static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
608 +static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
609 +                                   struct lookup_intent *it)
610  {
611         struct dentry *dentry;
612  
613 @@ -1232,7 +1370,7 @@
614         dentry = ERR_PTR(-EEXIST);
615         if (nd->last_type != LAST_NORM)
616                 goto fail;
617 -       dentry = lookup_hash(&nd->last, nd->dentry);
618 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
619         if (IS_ERR(dentry))
620                 goto fail;
621         if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
622 @@ -1288,7 +1426,16 @@
623         error = path_lookup(tmp, LOOKUP_PARENT, &nd);
624         if (error)
625                 goto out;
626 -       dentry = lookup_create(&nd, 0);
627 +
628 +       if (nd.dentry->d_inode->i_op->mknod_raw) {
629 +               struct inode_operations *op = nd.dentry->d_inode->i_op;
630 +               error = op->mknod_raw(&nd, mode, dev);
631 +               /* the file system wants to use normal vfs path now */
632 +               if (error != -EOPNOTSUPP)
633 +                       goto out2;
634 +       }
635 +
636 +       dentry = lookup_create(&nd, 0, NULL);
637         error = PTR_ERR(dentry);
638  
639         if (!IS_POSIXACL(nd.dentry->d_inode))
640 @@ -1310,6 +1457,7 @@
641                 dput(dentry);
642         }
643         up(&nd.dentry->d_inode->i_sem);
644 +out2:
645         path_release(&nd);
646  out:
647         putname(tmp);
648 @@ -1357,7 +1505,14 @@
649                 error = path_lookup(tmp, LOOKUP_PARENT, &nd);
650                 if (error)
651                         goto out;
652 -               dentry = lookup_create(&nd, 1);
653 +               if (nd.dentry->d_inode->i_op->mkdir_raw) {
654 +                       struct inode_operations *op = nd.dentry->d_inode->i_op;
655 +                       error = op->mkdir_raw(&nd, mode);
656 +                       /* the file system wants to use normal vfs path now */
657 +                       if (error != -EOPNOTSUPP)
658 +                               goto out2;
659 +               }
660 +               dentry = lookup_create(&nd, 1, NULL);
661                 error = PTR_ERR(dentry);
662                 if (!IS_ERR(dentry)) {
663                         if (!IS_POSIXACL(nd.dentry->d_inode))
664 @@ -1366,6 +1521,7 @@
665                         dput(dentry);
666                 }
667                 up(&nd.dentry->d_inode->i_sem);
668 +out2:
669                 path_release(&nd);
670  out:
671                 putname(tmp);
672 @@ -1466,8 +1622,16 @@
673                         error = -EBUSY;
674                         goto exit1;
675         }
676 +       if (nd.dentry->d_inode->i_op->rmdir_raw) {
677 +               struct inode_operations *op = nd.dentry->d_inode->i_op;
678 +
679 +               error = op->rmdir_raw(&nd);
680 +               /* the file system wants to use normal vfs path now */
681 +               if (error != -EOPNOTSUPP)
682 +                       goto exit1;
683 +       }
684         down(&nd.dentry->d_inode->i_sem);
685 -       dentry = lookup_hash(&nd.last, nd.dentry);
686 +       dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
687         error = PTR_ERR(dentry);
688         if (!IS_ERR(dentry)) {
689                 error = vfs_rmdir(nd.dentry->d_inode, dentry);
690 @@ -1525,8 +1689,15 @@
691         error = -EISDIR;
692         if (nd.last_type != LAST_NORM)
693                 goto exit1;
694 +       if (nd.dentry->d_inode->i_op->unlink_raw) {
695 +               struct inode_operations *op = nd.dentry->d_inode->i_op;
696 +               error = op->unlink_raw(&nd);
697 +               /* the file system wants to use normal vfs path now */
698 +               if (error != -EOPNOTSUPP)
699 +                       goto exit1;
700 +       }
701         down(&nd.dentry->d_inode->i_sem);
702 -       dentry = lookup_hash(&nd.last, nd.dentry);
703 +       dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
704         error = PTR_ERR(dentry);
705         if (!IS_ERR(dentry)) {
706                 /* Why not before? Because we want correct error value */
707 @@ -1593,15 +1764,23 @@
708                 error = path_lookup(to, LOOKUP_PARENT, &nd);
709                 if (error)
710                         goto out;
711 -               dentry = lookup_create(&nd, 0);
712 +               if (nd.dentry->d_inode->i_op->symlink_raw) {
713 +                       struct inode_operations *op = nd.dentry->d_inode->i_op;
714 +                       error = op->symlink_raw(&nd, from);
715 +                       /* the file system wants to use normal vfs path now */
716 +                       if (error != -EOPNOTSUPP)
717 +                               goto out2;
718 +               }
719 +               dentry = lookup_create(&nd, 0, NULL);
720                 error = PTR_ERR(dentry);
721                 if (!IS_ERR(dentry)) {
722                         error = vfs_symlink(nd.dentry->d_inode, dentry, from);
723                         dput(dentry);
724                 }
725                 up(&nd.dentry->d_inode->i_sem);
726 +       out2:
727                 path_release(&nd);
728 -out:
729 +       out:
730                 putname(to);
731         }
732         putname(from);
733 @@ -1677,7 +1856,14 @@
734                 error = -EXDEV;
735                 if (old_nd.mnt != nd.mnt)
736                         goto out_release;
737 -               new_dentry = lookup_create(&nd, 0);
738 +               if (nd.dentry->d_inode->i_op->link_raw) {
739 +                       struct inode_operations *op = nd.dentry->d_inode->i_op;
740 +                       error = op->link_raw(&old_nd, &nd);
741 +                       /* the file system wants to use normal vfs path now */
742 +                       if (error != -EOPNOTSUPP)
743 +                               goto out_release;
744 +               }
745 +               new_dentry = lookup_create(&nd, 0, NULL);
746                 error = PTR_ERR(new_dentry);
747                 if (!IS_ERR(new_dentry)) {
748                         error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
749 @@ -1721,7 +1907,7 @@
750   *        locking].
751   */
752  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
753 -              struct inode *new_dir, struct dentry *new_dentry)
754 +                  struct inode *new_dir, struct dentry *new_dentry)
755  {
756         int error;
757         struct inode *target;
758 @@ -1800,7 +1986,7 @@
759  }
760  
761  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
762 -              struct inode *new_dir, struct dentry *new_dentry)
763 +                    struct inode *new_dir, struct dentry *new_dentry)
764  {
765         int error;
766  
767 @@ -1888,9 +2074,18 @@
768         if (newnd.last_type != LAST_NORM)
769                 goto exit2;
770  
771 +       if (old_dir->d_inode->i_op->rename_raw) {
772 +               lock_kernel();
773 +               error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
774 +               unlock_kernel();
775 +               /* the file system wants to use normal vfs path now */
776 +               if (error != -EOPNOTSUPP)
777 +                       goto exit2;
778 +       }
779 +
780         double_lock(new_dir, old_dir);
781  
782 -       old_dentry = lookup_hash(&oldnd.last, old_dir);
783 +       old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL);
784         error = PTR_ERR(old_dentry);
785         if (IS_ERR(old_dentry))
786                 goto exit3;
787 @@ -1906,16 +2101,16 @@
788                 if (newnd.last.name[newnd.last.len])
789                         goto exit4;
790         }
791 -       new_dentry = lookup_hash(&newnd.last, new_dir);
792 +       new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL);
793         error = PTR_ERR(new_dentry);
794         if (IS_ERR(new_dentry))
795                 goto exit4;
796  
797 +
798         lock_kernel();
799         error = vfs_rename(old_dir->d_inode, old_dentry,
800                                    new_dir->d_inode, new_dentry);
801         unlock_kernel();
802 -
803         dput(new_dentry);
804  exit4:
805         dput(old_dentry);
806 @@ -1966,20 +2161,26 @@
807  }
808  
809  static inline int
810 -__vfs_follow_link(struct nameidata *nd, const char *link)
811 +__vfs_follow_link(struct nameidata *nd, const char *link,
812 +                 struct lookup_intent *it)
813  {
814         int res = 0;
815         char *name;
816         if (IS_ERR(link))
817                 goto fail;
818  
819 +       if (it == NULL)
820 +               it = nd->intent;
821 +       else if (it != nd->intent)
822 +               printk("it != nd->intent: tell phil@clusterfs.com\n");
823 +
824         if (*link == '/') {
825                 path_release(nd);
826                 if (!walk_init_root(link, nd))
827                         /* weird __emul_prefix() stuff did it */
828                         goto out;
829         }
830 -       res = link_path_walk(link, nd);
831 +       res = link_path_walk_it(link, nd, it);
832  out:
833         if (current->link_count || res || nd->last_type!=LAST_NORM)
834                 return res;
835 @@ -2003,7 +2204,13 @@
836  
837  int vfs_follow_link(struct nameidata *nd, const char *link)
838  {
839 -       return __vfs_follow_link(nd, link);
840 +       return __vfs_follow_link(nd, link, NULL);
841 +}
842 +
843 +int vfs_follow_link_it(struct nameidata *nd, const char *link,
844 +                      struct lookup_intent *it)
845 +{
846 +       return __vfs_follow_link(nd, link, it);
847  }
848  
849  /* get the link contents into pagecache */
850 @@ -2045,7 +2252,7 @@
851  {
852         struct page *page = NULL;
853         char *s = page_getlink(dentry, &page);
854 -       int res = __vfs_follow_link(nd, s);
855 +       int res = __vfs_follow_link(nd, s, NULL);
856         if (page) {
857                 kunmap(page);
858                 page_cache_release(page);
859 Index: linux-2.4.21-chaos/fs/namespace.c
860 ===================================================================
861 --- linux-2.4.21-chaos.orig/fs/namespace.c      2003-07-15 04:41:01.000000000 +0400
862 +++ linux-2.4.21-chaos/fs/namespace.c   2003-12-12 17:02:47.000000000 +0300
863 @@ -98,6 +98,7 @@
864  {
865         old_nd->dentry = mnt->mnt_mountpoint;
866         old_nd->mnt = mnt->mnt_parent;
867 +       UNPIN(old_nd->dentry, old_nd->mnt, 1);
868         mnt->mnt_parent = mnt;
869         mnt->mnt_mountpoint = mnt->mnt_root;
870         list_del_init(&mnt->mnt_child);
871 @@ -109,6 +110,7 @@
872  {
873         mnt->mnt_parent = mntget(nd->mnt);
874         mnt->mnt_mountpoint = dget(nd->dentry);
875 +       PIN(nd->dentry, nd->mnt, 1);
876         list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
877         list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
878         nd->dentry->d_mounted++;
879 @@ -488,14 +490,17 @@
880  {
881         struct nameidata old_nd;
882         struct vfsmount *mnt = NULL;
883 +       struct lookup_intent it = { .it_op = IT_GETATTR };
884         int err = mount_is_safe(nd);
885         if (err)
886                 return err;
887         if (!old_name || !*old_name)
888                 return -EINVAL;
889 -       err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
890 -       if (err)
891 +       err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it);
892 +       if (err) {
893 +               intent_release(&it);
894                 return err;
895 +       }
896  
897         down_write(&current->namespace->sem);
898         err = -EINVAL;
899 @@ -518,6 +523,7 @@
900         }
901  
902         up_write(&current->namespace->sem);
903 +       intent_release(&it);
904         path_release(&old_nd);
905         return err;
906  }
907 @@ -701,6 +707,7 @@
908                   unsigned long flags, void *data_page)
909  {
910         struct nameidata nd;
911 +       struct lookup_intent it = { .it_op = IT_GETATTR };
912         int retval = 0;
913         int mnt_flags = 0;
914  
915 @@ -725,10 +732,11 @@
916         flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
917  
918         /* ... and get the mountpoint */
919 -       retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
920 -       if (retval)
921 +       retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
922 +       if (retval) {
923 +               intent_release(&it);
924                 return retval;
925 -
926 +       }
927         if (flags & MS_REMOUNT)
928                 retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
929                                     data_page);
930 @@ -739,6 +747,8 @@
931         else
932                 retval = do_add_mount(&nd, type_page, flags, mnt_flags,
933                                       dev_name, data_page);
934 +
935 +       intent_release(&it);
936         path_release(&nd);
937         return retval;
938  }
939 @@ -904,6 +914,8 @@
940  {
941         struct vfsmount *tmp;
942         struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
943 +       struct lookup_intent new_it = { .it_op = IT_GETATTR };
944 +       struct lookup_intent old_it = { .it_op = IT_GETATTR };
945         int error;
946  
947         if (!capable(CAP_SYS_ADMIN))
948 @@ -911,14 +923,14 @@
949  
950         lock_kernel();
951  
952 -       error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd);
953 +       error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it);
954         if (error)
955                 goto out0;
956         error = -EINVAL;
957         if (!check_mnt(new_nd.mnt))
958                 goto out1;
959  
960 -       error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd);
961 +       error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it);
962         if (error)
963                 goto out1;
964  
965 @@ -973,8 +985,10 @@
966         up(&old_nd.dentry->d_inode->i_zombie);
967         up_write(&current->namespace->sem);
968         path_release(&user_nd);
969 +       intent_release(&old_it);
970         path_release(&old_nd);
971  out1:
972 +       intent_release(&new_it);
973         path_release(&new_nd);
974  out0:
975         unlock_kernel();
976 Index: linux-2.4.21-chaos/fs/open.c
977 ===================================================================
978 --- linux-2.4.21-chaos.orig/fs/open.c   2003-07-15 04:41:01.000000000 +0400
979 +++ linux-2.4.21-chaos/fs/open.c        2003-12-12 17:02:47.000000000 +0300
980 @@ -19,6 +19,8 @@
981  #include <asm/uaccess.h>
982  
983  #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
984 +extern int path_walk_it(const char *name, struct nameidata *nd,
985 +                       struct lookup_intent *it);
986  
987  int vfs_statfs(struct super_block *sb, struct statfs *buf)
988  {
989 @@ -95,9 +97,10 @@
990         write_unlock(&files->file_lock);
991  }
992  
993 -int do_truncate(struct dentry *dentry, loff_t length)
994 +int do_truncate(struct dentry *dentry, loff_t length, int called_from_open)
995  {
996         struct inode *inode = dentry->d_inode;
997 +       struct inode_operations *op = dentry->d_inode->i_op;
998         int error;
999         struct iattr newattrs;
1000  
1001 @@ -109,7 +112,13 @@
1002         down(&inode->i_sem);
1003         newattrs.ia_size = length;
1004         newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
1005 -       error = notify_change(dentry, &newattrs);
1006 +       if (called_from_open)
1007 +               newattrs.ia_valid |= ATTR_FROM_OPEN;
1008 +       if (op->setattr_raw) {
1009 +               newattrs.ia_valid |= ATTR_RAW;
1010 +               error = op->setattr_raw(inode, &newattrs);
1011 +       } else
1012 +               error = notify_change(dentry, &newattrs);
1013         up(&inode->i_sem);
1014         up_write(&inode->i_alloc_sem);
1015         return error;
1016 @@ -120,12 +129,13 @@
1017         struct nameidata nd;
1018         struct inode * inode;
1019         int error;
1020 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1021  
1022         error = -EINVAL;
1023         if (length < 0) /* sorry, but loff_t says... */
1024                 goto out;
1025  
1026 -       error = user_path_walk(path, &nd);
1027 +       error = user_path_walk_it(path, &nd, &it);
1028         if (error)
1029                 goto out;
1030         inode = nd.dentry->d_inode;
1031 @@ -165,11 +175,13 @@
1032         error = locks_verify_truncate(inode, NULL, length);
1033         if (!error) {
1034                 DQUOT_INIT(inode);
1035 -               error = do_truncate(nd.dentry, length);
1036 +               intent_release(&it);
1037 +               error = do_truncate(nd.dentry, length, 0);
1038         }
1039         put_write_access(inode);
1040  
1041  dput_and_out:
1042 +       intent_release(&it);
1043         path_release(&nd);
1044  out:
1045         return error;
1046 @@ -217,7 +229,7 @@
1047  
1048         error = locks_verify_truncate(inode, file, length);
1049         if (!error)
1050 -               error = do_truncate(dentry, length);
1051 +               error = do_truncate(dentry, length, 0);
1052  out_putf:
1053         fput(file);
1054  out:
1055 @@ -262,11 +274,13 @@
1056         struct inode * inode;
1057         struct iattr newattrs;
1058  
1059 -       error = user_path_walk(filename, &nd);
1060 +       error = user_path_walk_it(filename, &nd, NULL);
1061         if (error)
1062                 goto out;
1063         inode = nd.dentry->d_inode;
1064  
1065 +       /* this is safe without a Lustre lock because it only depends
1066 +          on the super block */
1067         error = -EROFS;
1068         if (IS_RDONLY(inode))
1069                 goto dput_and_out;
1070 @@ -281,11 +295,25 @@
1071                         goto dput_and_out;
1072  
1073                 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
1074 -       } else {
1075 +       }
1076 +
1077 +       if (inode->i_op->setattr_raw) {
1078 +               struct inode_operations *op = nd.dentry->d_inode->i_op;
1079 +
1080 +               newattrs.ia_valid |= ATTR_RAW;
1081 +               error = op->setattr_raw(inode, &newattrs);
1082 +               /* the file system wants to use normal vfs path now */
1083 +               if (error != -EOPNOTSUPP)
1084 +                       goto dput_and_out;
1085 +       }
1086 +
1087 +       error = -EPERM;
1088 +       if (!times) {
1089                 if (current->fsuid != inode->i_uid &&
1090                     (error = permission(inode,MAY_WRITE)) != 0)
1091                         goto dput_and_out;
1092         }
1093 +
1094         error = notify_change(nd.dentry, &newattrs);
1095  dput_and_out:
1096         path_release(&nd);
1097 @@ -306,12 +334,14 @@
1098         struct inode * inode;
1099         struct iattr newattrs;
1100  
1101 -       error = user_path_walk(filename, &nd);
1102 +       error = user_path_walk_it(filename, &nd, NULL);
1103  
1104         if (error)
1105                 goto out;
1106         inode = nd.dentry->d_inode;
1107  
1108 +       /* this is safe without a Lustre lock because it only depends
1109 +          on the super block */
1110         error = -EROFS;
1111         if (IS_RDONLY(inode))
1112                 goto dput_and_out;
1113 @@ -326,7 +356,20 @@
1114                 newattrs.ia_atime = times[0].tv_sec;
1115                 newattrs.ia_mtime = times[1].tv_sec;
1116                 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
1117 -       } else {
1118 +       }
1119 +
1120 +       if (inode->i_op->setattr_raw) {
1121 +               struct inode_operations *op = nd.dentry->d_inode->i_op;
1122 +
1123 +               newattrs.ia_valid |= ATTR_RAW;
1124 +               error = op->setattr_raw(inode, &newattrs);
1125 +               /* the file system wants to use normal vfs path now */
1126 +               if (error != -EOPNOTSUPP)
1127 +                       goto dput_and_out;
1128 +       }
1129 +
1130 +       error = -EPERM;
1131 +       if (!utimes) {
1132                 if (current->fsuid != inode->i_uid &&
1133                     (error = permission(inode,MAY_WRITE)) != 0)
1134                         goto dput_and_out;
1135 @@ -349,6 +392,7 @@
1136         int old_fsuid, old_fsgid;
1137         kernel_cap_t old_cap;
1138         int res;
1139 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1140  
1141         if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
1142                 return -EINVAL;
1143 @@ -366,13 +410,14 @@
1144         else
1145                 current->cap_effective = current->cap_permitted;
1146  
1147 -       res = user_path_walk(filename, &nd);
1148 +       res = user_path_walk_it(filename, &nd, &it);
1149         if (!res) {
1150                 res = permission(nd.dentry->d_inode, mode);
1151                 /* SuS v2 requires we report a read only fs too */
1152                 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
1153                    && !special_file(nd.dentry->d_inode->i_mode))
1154                         res = -EROFS;
1155 +               intent_release(&it);
1156                 path_release(&nd);
1157         }
1158  
1159 @@ -387,8 +432,9 @@
1160  {
1161         int error;
1162         struct nameidata nd;
1163 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1164  
1165 -       error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
1166 +       error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it);
1167         if (error)
1168                 goto out;
1169  
1170 @@ -399,6 +445,7 @@
1171         set_fs_pwd(current->fs, nd.mnt, nd.dentry);
1172  
1173  dput_and_out:
1174 +       intent_release(&it);
1175         path_release(&nd);
1176  out:
1177         return error;
1178 @@ -438,9 +485,10 @@
1179  {
1180         int error;
1181         struct nameidata nd;
1182 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1183  
1184 -       error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
1185 -                     LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
1186 +       error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
1187 +                     LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
1188         if (error)
1189                 goto out;
1190  
1191 @@ -456,39 +504,56 @@
1192         set_fs_altroot();
1193         error = 0;
1194  dput_and_out:
1195 +       intent_release(&it);
1196         path_release(&nd);
1197  out:
1198         return error;
1199  }
1200  
1201 -asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
1202 +int chmod_common(struct dentry *dentry, mode_t mode)
1203  {
1204 -       struct inode * inode;
1205 -       struct dentry * dentry;
1206 -       struct file * file;
1207 -       int err = -EBADF;
1208 +       struct inode *inode = dentry->d_inode;
1209         struct iattr newattrs;
1210 +       int err = -EROFS;
1211  
1212 -       file = fget(fd);
1213 -       if (!file)
1214 +       if (IS_RDONLY(inode))
1215                 goto out;
1216  
1217 -       dentry = file->f_dentry;
1218 -       inode = dentry->d_inode;
1219 +       if (inode->i_op->setattr_raw) {
1220 +               newattrs.ia_mode = mode;
1221 +               newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1222 +               newattrs.ia_valid |= ATTR_RAW;
1223 +               err = inode->i_op->setattr_raw(inode, &newattrs);
1224 +               /* the file system wants to use normal vfs path now */
1225 +               if (err != -EOPNOTSUPP)
1226 +                       goto out;
1227 +       }
1228  
1229 -       err = -EROFS;
1230 -       if (IS_RDONLY(inode))
1231 -               goto out_putf;
1232         err = -EPERM;
1233         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1234 -               goto out_putf;
1235 +               goto out;
1236 +
1237         if (mode == (mode_t) -1)
1238                 mode = inode->i_mode;
1239         newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1240         newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1241         err = notify_change(dentry, &newattrs);
1242  
1243 -out_putf:
1244 +out:
1245 +       return err;
1246 +}
1247 +
1248 +asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
1249 +{
1250 +       struct file * file;
1251 +       int err = -EBADF;
1252 +
1253 +       file = fget(fd);
1254 +       if (!file)
1255 +               goto out;
1256 +
1257 +       err = chmod_common(file->f_dentry, mode);
1258 +
1259         fput(file);
1260  out:
1261         return err;
1262 @@ -497,30 +562,14 @@
1263  asmlinkage long sys_chmod(const char * filename, mode_t mode)
1264  {
1265         struct nameidata nd;
1266 -       struct inode * inode;
1267         int error;
1268 -       struct iattr newattrs;
1269  
1270         error = user_path_walk(filename, &nd);
1271         if (error)
1272                 goto out;
1273 -       inode = nd.dentry->d_inode;
1274 -
1275 -       error = -EROFS;
1276 -       if (IS_RDONLY(inode))
1277 -               goto dput_and_out;
1278  
1279 -       error = -EPERM;
1280 -       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1281 -               goto dput_and_out;
1282 +       error = chmod_common(nd.dentry, mode);
1283  
1284 -       if (mode == (mode_t) -1)
1285 -               mode = inode->i_mode;
1286 -       newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1287 -       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1288 -       error = notify_change(nd.dentry, &newattrs);
1289 -
1290 -dput_and_out:
1291         path_release(&nd);
1292  out:
1293         return error;
1294 @@ -540,6 +589,20 @@
1295         error = -EROFS;
1296         if (IS_RDONLY(inode))
1297                 goto out;
1298 +
1299 +       if (inode->i_op->setattr_raw) {
1300 +               struct inode_operations *op = dentry->d_inode->i_op;
1301 +
1302 +               newattrs.ia_uid = user;
1303 +               newattrs.ia_gid = group;
1304 +               newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
1305 +               newattrs.ia_valid |= ATTR_RAW;
1306 +               error = op->setattr_raw(inode, &newattrs);
1307 +               /* the file system wants to use normal vfs path now */
1308 +               if (error != -EOPNOTSUPP)
1309 +                       return error;
1310 +       }
1311 +
1312         error = -EPERM;
1313         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1314                 goto out;
1315 @@ -644,6 +707,7 @@
1316  {
1317         int namei_flags, error;
1318         struct nameidata nd;
1319 +       struct lookup_intent it = { .it_op = IT_OPEN };
1320  
1321         namei_flags = flags;
1322         if ((namei_flags+1) & O_ACCMODE)
1323 @@ -651,14 +715,15 @@
1324         if (namei_flags & O_TRUNC)
1325                 namei_flags |= 2;
1326  
1327 -       error = open_namei(filename, namei_flags, mode, &nd);
1328 -       if (!error)
1329 -               return dentry_open(nd.dentry, nd.mnt, flags);
1330 +       error = open_namei_it(filename, namei_flags, mode, &nd, &it);
1331 +       if (error)
1332 +               return ERR_PTR(error);
1333  
1334 -       return ERR_PTR(error);
1335 +       return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
1336  }
1337  
1338 -struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
1339 +struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
1340 +                           int flags, struct lookup_intent *it)
1341  {
1342         struct file * f;
1343         struct inode *inode;
1344 @@ -695,7 +760,9 @@
1345         }
1346  
1347         if (f->f_op && f->f_op->open) {
1348 +               f->f_it = it;
1349                 error = f->f_op->open(inode,f);
1350 +               f->f_it = NULL;
1351                 if (error)
1352                         goto cleanup_all;
1353         }
1354 @@ -708,6 +775,7 @@
1355                                         inode->i_mapping->a_ops->direct_sector_IO)))
1356                 goto cleanup_all;
1357  
1358 +       intent_release(it);
1359         return f;
1360  
1361  cleanup_all:
1362 @@ -722,11 +790,17 @@
1363  cleanup_file:
1364         put_filp(f);
1365  cleanup_dentry:
1366 +       intent_release(it);
1367         dput(dentry);
1368         mntput(mnt);
1369         return ERR_PTR(error);
1370  }
1371  
1372 +struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
1373 +{
1374 +       return dentry_open_it(dentry, mnt, flags, NULL);
1375 +}
1376 +
1377  /*
1378   * Find an empty file descriptor entry, and mark it busy.
1379   */
1380 Index: linux-2.4.21-chaos/fs/stat.c
1381 ===================================================================
1382 --- linux-2.4.21-chaos.orig/fs/stat.c   2003-09-19 03:49:54.000000000 +0400
1383 +++ linux-2.4.21-chaos/fs/stat.c        2003-12-12 17:02:47.000000000 +0300
1384 @@ -17,10 +17,14 @@
1385   * Revalidate the inode. This is required for proper NFS attribute caching.
1386   */
1387  static __inline__ int
1388 -do_revalidate(struct dentry *dentry)
1389 +do_revalidate(struct dentry *dentry, struct lookup_intent *it)
1390  {
1391         struct inode * inode = dentry->d_inode;
1392 -       if (inode->i_op && inode->i_op->revalidate)
1393 +       if (!inode)
1394 +               return -ENOENT;
1395 +       if (inode->i_op && inode->i_op->revalidate_it)
1396 +               return inode->i_op->revalidate_it(dentry, it);
1397 +       else if (inode->i_op && inode->i_op->revalidate)
1398                 return inode->i_op->revalidate(dentry);
1399         return 0;
1400  }
1401 @@ -143,13 +147,15 @@
1402  asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
1403  {
1404         struct nameidata nd;
1405 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1406         int error;
1407  
1408 -       error = user_path_walk(filename, &nd);
1409 +       error = user_path_walk_it(filename, &nd, &it);
1410         if (!error) {
1411 -               error = do_revalidate(nd.dentry);
1412 +               error = do_revalidate(nd.dentry, &it);
1413                 if (!error)
1414                         error = cp_old_stat(nd.dentry->d_inode, statbuf);
1415 +               intent_release(&it);
1416                 path_release(&nd);
1417         }
1418         return error;
1419 @@ -159,13 +165,15 @@
1420  asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
1421  {
1422         struct nameidata nd;
1423 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1424         int error;
1425  
1426 -       error = user_path_walk(filename, &nd);
1427 +       error = user_path_walk_it(filename, &nd, &it);
1428         if (!error) {
1429 -               error = do_revalidate(nd.dentry);
1430 +               error = do_revalidate(nd.dentry, &it);
1431                 if (!error)
1432                         error = cp_new_stat(nd.dentry->d_inode, statbuf);
1433 +               intent_release(&it);
1434                 path_release(&nd);
1435         }
1436         return error;
1437 @@ -180,13 +188,15 @@
1438  asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
1439  {
1440         struct nameidata nd;
1441 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1442         int error;
1443  
1444 -       error = user_path_walk_link(filename, &nd);
1445 +       error = user_path_walk_link_it(filename, &nd, &it);
1446         if (!error) {
1447 -               error = do_revalidate(nd.dentry);
1448 +               error = do_revalidate(nd.dentry, &it);
1449                 if (!error)
1450                         error = cp_old_stat(nd.dentry->d_inode, statbuf);
1451 +               intent_release(&it);
1452                 path_release(&nd);
1453         }
1454         return error;
1455 @@ -197,13 +207,15 @@
1456  asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
1457  {
1458         struct nameidata nd;
1459 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1460         int error;
1461  
1462 -       error = user_path_walk_link(filename, &nd);
1463 +       error = user_path_walk_link_it(filename, &nd, &it);
1464         if (!error) {
1465 -               error = do_revalidate(nd.dentry);
1466 +               error = do_revalidate(nd.dentry, &it);
1467                 if (!error)
1468                         error = cp_new_stat(nd.dentry->d_inode, statbuf);
1469 +               intent_release(&it);
1470                 path_release(&nd);
1471         }
1472         return error;
1473 @@ -224,7 +236,7 @@
1474         if (f) {
1475                 struct dentry * dentry = f->f_dentry;
1476  
1477 -               err = do_revalidate(dentry);
1478 +               err = do_revalidate(dentry, NULL);
1479                 if (!err)
1480                         err = cp_old_stat(dentry->d_inode, statbuf);
1481                 fput(f);
1482 @@ -243,7 +255,7 @@
1483         if (f) {
1484                 struct dentry * dentry = f->f_dentry;
1485  
1486 -               err = do_revalidate(dentry);
1487 +               err = do_revalidate(dentry, NULL);
1488                 if (!err)
1489                         err = cp_new_stat(dentry->d_inode, statbuf);
1490                 fput(f);
1491 @@ -265,7 +277,7 @@
1492  
1493                 error = -EINVAL;
1494                 if (inode->i_op && inode->i_op->readlink &&
1495 -                   !(error = do_revalidate(nd.dentry))) {
1496 +                   !(error = do_revalidate(nd.dentry, NULL))) {
1497                         UPDATE_ATIME(inode);
1498                         error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
1499                 }
1500 @@ -341,12 +353,14 @@
1501  {
1502         struct nameidata nd;
1503         int error;
1504 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1505  
1506 -       error = user_path_walk(filename, &nd);
1507 +       error = user_path_walk_it(filename, &nd, &it);
1508         if (!error) {
1509 -               error = do_revalidate(nd.dentry);
1510 +               error = do_revalidate(nd.dentry, &it);
1511                 if (!error)
1512                         error = cp_new_stat64(nd.dentry->d_inode, statbuf);
1513 +               intent_release(&it);
1514                 path_release(&nd);
1515         }
1516         return error;
1517 @@ -356,12 +370,14 @@
1518  {
1519         struct nameidata nd;
1520         int error;
1521 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1522  
1523 -       error = user_path_walk_link(filename, &nd);
1524 +       error = user_path_walk_link_it(filename, &nd, &it);
1525         if (!error) {
1526 -               error = do_revalidate(nd.dentry);
1527 +               error = do_revalidate(nd.dentry, &it);
1528                 if (!error)
1529                         error = cp_new_stat64(nd.dentry->d_inode, statbuf);
1530 +               intent_release(&it);
1531                 path_release(&nd);
1532         }
1533         return error;
1534 @@ -376,7 +392,7 @@
1535         if (f) {
1536                 struct dentry * dentry = f->f_dentry;
1537  
1538 -               err = do_revalidate(dentry);
1539 +               err = do_revalidate(dentry, NULL);
1540                 if (!err)
1541                         err = cp_new_stat64(dentry->d_inode, statbuf);
1542                 fput(f);
1543 Index: linux-2.4.21-chaos/include/linux/dcache.h
1544 ===================================================================
1545 --- linux-2.4.21-chaos.orig/include/linux/dcache.h      2003-12-05 16:54:33.000000000 +0300
1546 +++ linux-2.4.21-chaos/include/linux/dcache.h   2003-12-12 17:02:47.000000000 +0300
1547 @@ -6,6 +6,51 @@
1548  #include <asm/atomic.h>
1549  #include <linux/mount.h>
1550  #include <linux/kernel.h>
1551 +#include <linux/string.h>
1552 +
1553 +#define IT_OPEN     0x0001
1554 +#define IT_CREAT    0x0002
1555 +#define IT_READDIR  0x0004
1556 +#define IT_GETATTR  0x0008
1557 +#define IT_LOOKUP   0x0010
1558 +#define IT_UNLINK   0x0020
1559 +#define IT_GETXATTR 0x0040
1560 +#define IT_EXEC     0x0080
1561 +#define IT_PIN      0x0100
1562 +
1563 +#define IT_FL_LOCKED   0x0001
1564 +#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */
1565 +
1566 +#define INTENT_MAGIC 0x19620323
1567 +
1568 +
1569 +struct lustre_intent_data {
1570 +       int       it_disposition;
1571 +       int       it_status;
1572 +       __u64     it_lock_handle;
1573 +       void     *it_data;
1574 +       int       it_lock_mode;
1575 +       int it_int_flags;
1576 +};
1577 +struct lookup_intent {
1578 +       int     it_magic;
1579 +       void    (*it_op_release)(struct lookup_intent *);
1580 +       int     it_op;
1581 +       int     it_flags;
1582 +       int     it_create_mode;
1583 +       union {
1584 +               struct lustre_intent_data lustre;
1585 +       } d;
1586 +};
1587 +
1588 +static inline void intent_init(struct lookup_intent *it, int op, int flags)
1589 +{
1590 +       memset(it, 0, sizeof(*it));
1591 +       it->it_magic = INTENT_MAGIC;
1592 +       it->it_op = op;
1593 +       it->it_flags = flags;
1594 +}
1595 +
1596  
1597  /*
1598   * linux/include/linux/dcache.h
1599 @@ -96,8 +141,22 @@
1600         int (*d_delete)(struct dentry *);
1601         void (*d_release)(struct dentry *);
1602         void (*d_iput)(struct dentry *, struct inode *);
1603 +       int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *);
1604 +       void (*d_pin)(struct dentry *, struct vfsmount * , int);
1605 +       void (*d_unpin)(struct dentry *, struct vfsmount *, int);
1606  };
1607  
1608 +#define PIN(de,mnt,flag)  if (de && de->d_op && de->d_op->d_pin) \
1609 +                               de->d_op->d_pin(de, mnt, flag);
1610 +#define UNPIN(de,mnt,flag)  if (de && de->d_op && de->d_op->d_unpin) \
1611 +                               de->d_op->d_unpin(de, mnt, flag);
1612 +
1613 +
1614 +/* defined in fs/namei.c */
1615 +extern void intent_release(struct lookup_intent *it);
1616 +/* defined in fs/dcache.c */
1617 +extern void __d_rehash(struct dentry * entry, int lock);
1618 +
1619  /* the dentry parameter passed to d_hash and d_compare is the parent
1620   * directory of the entries to be compared. It is used in case these
1621   * functions need any directory specific information for determining
1622 @@ -129,6 +188,7 @@
1623                                          * s_nfsd_free_path semaphore will be down
1624                                          */
1625  #define DCACHE_REFERENCED      0x0008  /* Recently used, don't discard. */
1626 +#define DCACHE_LUSTRE_INVALID  0x0010  /* Lustre invalidated */
1627  
1628  extern spinlock_t dcache_lock;
1629  
1630 Index: linux-2.4.21-chaos/include/linux/fs.h
1631 ===================================================================
1632 --- linux-2.4.21-chaos.orig/include/linux/fs.h  2003-12-12 17:02:46.000000000 +0300
1633 +++ linux-2.4.21-chaos/include/linux/fs.h       2003-12-12 17:02:47.000000000 +0300
1634 @@ -73,6 +73,7 @@
1635  
1636  #define FMODE_READ 1
1637  #define FMODE_WRITE 2
1638 +#define FMODE_EXEC 4
1639  
1640  #define READ 0
1641  #define WRITE 1
1642 @@ -359,6 +360,9 @@
1643  #define ATTR_MTIME_SET 256
1644  #define ATTR_FORCE     512     /* Not a change, but a change it */
1645  #define ATTR_ATTR_FLAG 1024
1646 +#define ATTR_RAW       0x0800  /* file system, not vfs will massage attrs */
1647 +#define ATTR_FROM_OPEN 0x1000  /* called from open path, ie O_TRUNC */
1648 +#define ATTR_CTIME_SET 0x2000
1649  
1650  /*
1651   * This is the Inode Attributes structure, used for notify_change().  It
1652 @@ -496,6 +500,7 @@
1653         struct pipe_inode_info  *i_pipe;
1654         struct block_device     *i_bdev;
1655         struct char_device      *i_cdev;
1656 +       void                    *i_filterdata;
1657  
1658         unsigned long           i_dnotify_mask; /* Directory notify events */
1659         struct dnotify_struct   *i_dnotify; /* for directory notifications */
1660 @@ -598,6 +603,7 @@
1661  
1662         /* needed for tty driver, and maybe others */
1663         void                    *private_data;
1664 +       struct lookup_intent    *f_it;
1665  
1666         /* preallocated helper kiobuf to speedup O_DIRECT */
1667         struct kiobuf           *f_iobuf;
1668 @@ -726,6 +732,7 @@
1669         struct qstr last;
1670         unsigned int flags;
1671         int last_type;
1672 +       struct lookup_intent *intent;
1673  };
1674  
1675  /*
1676 @@ -846,7 +853,8 @@
1677  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
1678  extern int vfs_rmdir(struct inode *, struct dentry *);
1679  extern int vfs_unlink(struct inode *, struct dentry *);
1680 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
1681 +int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1682 +              struct inode *new_dir, struct dentry *new_dentry);
1683  
1684  /*
1685   * File types
1686 @@ -920,21 +928,32 @@
1687  
1688  struct inode_operations {
1689         int (*create) (struct inode *,struct dentry *,int);
1690 +       int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *);
1691         struct dentry * (*lookup) (struct inode *,struct dentry *);
1692 +       struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags);
1693         int (*link) (struct dentry *,struct inode *,struct dentry *);
1694 +       int (*link_raw) (struct nameidata *,struct nameidata *);
1695         int (*unlink) (struct inode *,struct dentry *);
1696 +       int (*unlink_raw) (struct nameidata *);
1697         int (*symlink) (struct inode *,struct dentry *,const char *);
1698 +       int (*symlink_raw) (struct nameidata *,const char *);
1699         int (*mkdir) (struct inode *,struct dentry *,int);
1700 +       int (*mkdir_raw) (struct nameidata *,int);
1701         int (*rmdir) (struct inode *,struct dentry *);
1702 +       int (*rmdir_raw) (struct nameidata *);
1703         int (*mknod) (struct inode *,struct dentry *,int,int);
1704 +       int (*mknod_raw) (struct nameidata *,int,dev_t);
1705         int (*rename) (struct inode *, struct dentry *,
1706                         struct inode *, struct dentry *);
1707 +       int (*rename_raw) (struct nameidata *, struct nameidata *);
1708         int (*readlink) (struct dentry *, char *,int);
1709         int (*follow_link) (struct dentry *, struct nameidata *);
1710         void (*truncate) (struct inode *);
1711         int (*permission) (struct inode *, int);
1712         int (*revalidate) (struct dentry *);
1713 +       int (*revalidate_it) (struct dentry *, struct lookup_intent *);
1714         int (*setattr) (struct dentry *, struct iattr *);
1715 +       int (*setattr_raw) (struct inode *, struct iattr *);
1716         int (*getattr) (struct dentry *, struct iattr *);
1717         int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
1718         ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
1719 @@ -1131,10 +1150,14 @@
1720  
1721  asmlinkage long sys_open(const char *, int, int);
1722  asmlinkage long sys_close(unsigned int);       /* yes, it's really unsigned */
1723 -extern int do_truncate(struct dentry *, loff_t start);
1724 +extern int do_truncate(struct dentry *, loff_t start, int called_from_open);
1725  
1726  extern struct file *filp_open(const char *, int, int);
1727  extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
1728 +extern int open_namei_it(const char *filename, int namei_flags, int mode,
1729 +                        struct nameidata *nd, struct lookup_intent *it);
1730 +extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
1731 +                           int flags, struct lookup_intent *it);
1732  extern int filp_close(struct file *, fl_owner_t id);
1733  extern char * getname(const char *);
1734  
1735 @@ -1425,6 +1448,7 @@
1736  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
1737  
1738  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
1739 +extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
1740  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
1741  extern int FASTCALL(path_walk(const char *, struct nameidata *));
1742  extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
1743 @@ -1436,6 +1460,8 @@
1744  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
1745  #define user_path_walk(name,nd)         __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
1746  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
1747 +#define user_path_walk_it(name,nd,it)  __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
1748 +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
1749  
1750  extern void inode_init_once(struct inode *);
1751  extern void iput(struct inode *);
1752 @@ -1599,6 +1625,8 @@
1753  
1754  extern int vfs_readlink(struct dentry *, char *, int, const char *);
1755  extern int vfs_follow_link(struct nameidata *, const char *);
1756 +extern int vfs_follow_link_it(struct nameidata *, const char *,
1757 +                             struct lookup_intent *it);
1758  extern int page_readlink(struct dentry *, char *, int);
1759  extern int page_follow_link(struct dentry *, struct nameidata *);
1760  extern struct inode_operations page_symlink_inode_operations;
1761 Index: linux-2.4.21-chaos/include/linux/fs_struct.h
1762 ===================================================================
1763 --- linux-2.4.21-chaos.orig/include/linux/fs_struct.h   2003-12-05 16:54:33.000000000 +0300
1764 +++ linux-2.4.21-chaos/include/linux/fs_struct.h        2003-12-12 17:02:47.000000000 +0300
1765 @@ -37,10 +37,12 @@
1766         write_lock(&fs->lock);
1767         old_root = fs->root;
1768         old_rootmnt = fs->rootmnt;
1769 +       PIN(dentry, mnt, 1);
1770         fs->rootmnt = mntget(mnt);
1771         fs->root = dget(dentry);
1772         write_unlock(&fs->lock);
1773         if (old_root) {
1774 +               UNPIN(old_root, old_rootmnt, 1);
1775                 dput(old_root);
1776                 mntput(old_rootmnt);
1777         }
1778 @@ -60,10 +62,12 @@
1779         write_lock(&fs->lock);
1780         old_pwd = fs->pwd;
1781         old_pwdmnt = fs->pwdmnt;
1782 +       PIN(dentry, mnt, 0);
1783         fs->pwdmnt = mntget(mnt);
1784         fs->pwd = dget(dentry);
1785         write_unlock(&fs->lock);
1786         if (old_pwd) {
1787 +               UNPIN(old_pwd, old_pwdmnt, 0);
1788                 dput(old_pwd);
1789                 mntput(old_pwdmnt);
1790         }
1791 Index: linux-2.4.21-chaos/kernel/exit.c
1792 ===================================================================
1793 --- linux-2.4.21-chaos.orig/kernel/exit.c       2003-09-19 03:50:00.000000000 +0400
1794 +++ linux-2.4.21-chaos/kernel/exit.c    2003-12-12 17:02:47.000000000 +0300
1795 @@ -347,11 +347,14 @@
1796  {
1797         /* No need to hold fs->lock if we are killing it */
1798         if (atomic_dec_and_test(&fs->count)) {
1799 +               UNPIN(fs->pwd, fs->pwdmnt, 0);
1800 +               UNPIN(fs->root, fs->rootmnt, 1);
1801                 dput(fs->root);
1802                 mntput(fs->rootmnt);
1803                 dput(fs->pwd);
1804                 mntput(fs->pwdmnt);
1805                 if (fs->altroot) {
1806 +                       UNPIN(fs->altroot, fs->altrootmnt, 1);
1807                         dput(fs->altroot);
1808                         mntput(fs->altrootmnt);
1809                 }
1810 Index: linux-2.4.21-chaos/kernel/fork.c
1811 ===================================================================
1812 --- linux-2.4.21-chaos.orig/kernel/fork.c       2003-12-05 07:55:51.000000000 +0300
1813 +++ linux-2.4.21-chaos/kernel/fork.c    2003-12-12 17:02:47.000000000 +0300
1814 @@ -463,10 +463,13 @@
1815                 fs->umask = old->umask;
1816                 read_lock(&old->lock);
1817                 fs->rootmnt = mntget(old->rootmnt);
1818 +               PIN(old->pwd, old->pwdmnt, 0);
1819 +               PIN(old->root, old->rootmnt, 1);
1820                 fs->root = dget(old->root);
1821                 fs->pwdmnt = mntget(old->pwdmnt);
1822                 fs->pwd = dget(old->pwd);
1823                 if (old->altroot) {
1824 +                       PIN(old->altroot, old->altrootmnt, 1);
1825                         fs->altrootmnt = mntget(old->altrootmnt);
1826                         fs->altroot = dget(old->altroot);
1827                 } else {
1828 Index: linux-2.4.21-chaos/kernel/ksyms.c
1829 ===================================================================
1830 --- linux-2.4.21-chaos.orig/kernel/ksyms.c      2003-12-12 17:02:46.000000000 +0300
1831 +++ linux-2.4.21-chaos/kernel/ksyms.c   2003-12-12 17:02:47.000000000 +0300
1832 @@ -318,6 +318,7 @@
1833  EXPORT_SYMBOL(set_page_dirty);
1834  EXPORT_SYMBOL(vfs_readlink);
1835  EXPORT_SYMBOL(vfs_follow_link);
1836 +EXPORT_SYMBOL(vfs_follow_link_it);
1837  EXPORT_SYMBOL(page_readlink);
1838  EXPORT_SYMBOL(page_follow_link);
1839  EXPORT_SYMBOL(page_symlink_inode_operations);