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