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