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