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