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