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