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