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