Whamcloud - gitweb
- Phil's intent fix for middle of symlink lookups.
[fs/lustre-release.git] / lustre / kernel_patches / patches / vfs_intent.patch
1
2
3
4  0 files changed
5
6 --- linux-2.4.18-17.8.0/fs/dcache.c~vfs_intent  2002-12-06 14:52:31.000000000 -0800
7 +++ linux-2.4.18-17.8.0-zab/fs/dcache.c 2002-12-06 14:52:31.000000000 -0800
8 @@ -150,6 +150,8 @@ repeat:
9  unhash_it:
10         list_del_init(&dentry->d_hash);
11  
12 +
13 +
14  kill_it: {
15                 struct dentry *parent;
16                 list_del(&dentry->d_child);
17 @@ -645,6 +647,7 @@ struct dentry * d_alloc(struct dentry * 
18         dentry->d_fsdata = NULL;
19         dentry->d_extra_attributes = NULL;
20         dentry->d_mounted = 0;
21 +       dentry->d_it = NULL;
22         INIT_LIST_HEAD(&dentry->d_hash);
23         INIT_LIST_HEAD(&dentry->d_lru);
24         INIT_LIST_HEAD(&dentry->d_subdirs);
25 --- linux-2.4.18-17.8.0/fs/namei.c~vfs_intent   2002-12-06 14:52:31.000000000 -0800
26 +++ linux-2.4.18-17.8.0-zab/fs/namei.c  2002-12-06 14:52:31.000000000 -0800
27 @@ -1,3 +1,6 @@
28 +
29 +
30 +
31  /*
32   *  linux/fs/namei.c
33   *
34 @@ -94,6 +97,14 @@
35   * XEmacs seems to be relying on it...
36   */
37  
38 +void intent_release(struct dentry *de, struct lookup_intent *it)
39 +{
40 +       if (it && de->d_op && de->d_op->d_intent_release)
41 +               de->d_op->d_intent_release(de, it);
42 +
43 +}
44 +
45 +
46  /* In order to reduce some races, while at the same time doing additional
47   * checking and hopefully speeding things up, we copy filenames to the
48   * kernel data space before using them..
49 @@ -260,10 +271,19 @@ void path_release(struct nameidata *nd)
50   * Internal lookup() using the new generic dcache.
51   * SMP-safe
52   */
53 -static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
54 +static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
55 +                                   int flags, struct lookup_intent *it)
56  {
57         struct dentry * dentry = d_lookup(parent, name);
58  
59 +       if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
60 +               if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
61 +                   !d_invalidate(dentry)) {
62 +                       dput(dentry);
63 +                       dentry = NULL;
64 +               }
65 +               return dentry;
66 +       } else
67         if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
68                 if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
69                         dput(dentry);
70 @@ -281,7 +301,8 @@ static struct dentry * cached_lookup(str
71   * make sure that nobody added the entry to the dcache in the meantime..
72   * SMP-safe
73   */
74 -static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
75 +static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
76 +                                 int flags, struct lookup_intent *it)
77  {
78         struct dentry * result;
79         struct inode *dir = parent->d_inode;
80 @@ -300,6 +321,9 @@ static struct dentry * real_lookup(struc
81                 result = ERR_PTR(-ENOMEM);
82                 if (dentry) {
83                         lock_kernel();
84 +                       if (dir->i_op->lookup2)
85 +                               result = dir->i_op->lookup2(dir, dentry, it);
86 +                       else
87                         result = dir->i_op->lookup(dir, dentry);
88                         unlock_kernel();
89                         if (result)
90 @@ -321,6 +345,12 @@ static struct dentry * real_lookup(struc
91                         dput(result);
92                         result = ERR_PTR(-ENOENT);
93                 }
94 +       } else if (result->d_op && result->d_op->d_revalidate2) {
95 +               if (!result->d_op->d_revalidate2(result, flags, it) &&
96 +                   !d_invalidate(result)) {
97 +                       dput(result);
98 +                       result = ERR_PTR(-ENOENT);
99 +               }
100         }
101         return result;
102  }
103 @@ -334,7 +364,8 @@ int max_recursive_link = 5;
104   * Without that kind of total limit, nasty chains of consecutive
105   * symlinks can cause almost arbitrarily long lookups. 
106   */
107 -static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
108 +static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, 
109 +                                 struct lookup_intent *it)
110  {
111         int err;
112         if (current->link_count >= max_recursive_link)
113 @@ -348,10 +379,14 @@ static inline int do_follow_link(struct 
114         current->link_count++;
115         current->total_link_count++;
116         UPDATE_ATIME(dentry->d_inode);
117 -       err = dentry->d_inode->i_op->follow_link(dentry, nd);
118 +        if (dentry->d_inode->i_op->follow_link2)
119 +                err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
120 +        else 
121 +                err = dentry->d_inode->i_op->follow_link(dentry, nd);
122         current->link_count--;
123         return err;
124  loop:
125 +        intent_release(dentry, it);
126         path_release(nd);
127         return -ELOOP;
128  }
129 @@ -449,7 +484,8 @@ static inline void follow_dotdot(struct 
130   *
131   * We expect 'base' to be positive and a directory.
132   */
133 -int link_path_walk(const char * name, struct nameidata *nd)
134 +int link_path_walk_it(const char *name, struct nameidata *nd,
135 +                     struct lookup_intent *it)
136  {
137         struct dentry *dentry;
138         struct inode *inode;
139 @@ -526,12 +562,12 @@ int link_path_walk(const char * name, st
140                                 break;
141                 }
142                 /* This does the actual lookups.. */
143 -               dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
144 +               dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
145                 if (!dentry) {
146                         err = -EWOULDBLOCKIO;
147                         if (atomic)
148                                 break;
149 -                       dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
150 +                       dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
151                         err = PTR_ERR(dentry);
152                         if (IS_ERR(dentry))
153                                 break;
154 @@ -548,8 +584,8 @@ int link_path_walk(const char * name, st
155                 if (!inode->i_op)
156                         goto out_dput;
157  
158 -               if (inode->i_op->follow_link) {
159 -                       err = do_follow_link(dentry, nd);
160 +               if (inode->i_op->follow_link || inode->i_op->follow_link2) {
161 +                       err = do_follow_link(dentry, nd, NULL);
162                         dput(dentry);
163                         if (err)
164                                 goto return_err;
165 @@ -565,7 +601,7 @@ int link_path_walk(const char * name, st
166                         nd->dentry = dentry;
167                 }
168                 err = -ENOTDIR; 
169 -               if (!inode->i_op->lookup)
170 +               if (!inode->i_op->lookup && !inode->i_op->lookup2)
171                         break;
172                 continue;
173                 /* here ends the main loop */
174 @@ -592,12 +628,12 @@ last_component:
175                         if (err < 0)
176                                 break;
177                 }
178 -               dentry = cached_lookup(nd->dentry, &this, 0);
179 +               dentry = cached_lookup(nd->dentry, &this, 0, it);
180                 if (!dentry) {
181                         err = -EWOULDBLOCKIO;
182                         if (atomic)
183                                 break;
184 -                       dentry = real_lookup(nd->dentry, &this, 0);
185 +                       dentry = real_lookup(nd->dentry, &this, 0, it);
186                         err = PTR_ERR(dentry);
187                         if (IS_ERR(dentry))
188                                 break;
189 @@ -606,8 +642,10 @@ last_component:
190                         ;
191                 inode = dentry->d_inode;
192                 if ((lookup_flags & LOOKUP_FOLLOW)
193 -                   && inode && inode->i_op && inode->i_op->follow_link) {
194 -                       err = do_follow_link(dentry, nd);
195 +                   && inode && inode->i_op && 
196 +                    (inode->i_op->follow_link || 
197 +                     inode->i_op->follow_link2)) {
198 +                       err = do_follow_link(dentry, nd, it);
199                         dput(dentry);
200                         if (err)
201                                 goto return_err;
202 @@ -621,7 +659,8 @@ last_component:
203                         goto no_inode;
204                 if (lookup_flags & LOOKUP_DIRECTORY) {
205                         err = -ENOTDIR; 
206 -                       if (!inode->i_op || !inode->i_op->lookup)
207 +                       if (!inode->i_op || (!inode->i_op->lookup &&
208 +                                            !inode->i_op->lookup2))
209                                 break;
210                 }
211                 goto return_base;
212 @@ -663,10 +702,21 @@ return_err:
213         return err;
214  }
215  
216 +int link_path_walk(const char * name, struct nameidata *nd)
217 +{
218 +       return link_path_walk_it(name, nd, NULL);
219 +}
220 +
221 +int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
222 +{
223 +       current->total_link_count = 0;
224 +       return link_path_walk_it(name, nd, it);
225 +}
226 +
227  int path_walk(const char * name, struct nameidata *nd)
228  {
229         current->total_link_count = 0;
230 -       return link_path_walk(name, nd);
231 +       return link_path_walk_it(name, nd, NULL);
232  }
233  
234  /* SMP-safe */
235 @@ -751,6 +801,17 @@ walk_init_root(const char *name, struct 
236  }
237  
238  /* SMP-safe */
239 +int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
240 +                  struct lookup_intent *it)
241 +{
242 +       int error = 0;
243 +       if (path_init(path, flags, nd))
244 +               error = path_walk_it(path, nd, it);
245 +       return error;
246 +}
247 +
248 +
249 +/* SMP-safe */
250  int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
251  {
252         int error = 0;
253 @@ -779,7 +840,8 @@ int path_init(const char *name, unsigned
254   * needs parent already locked. Doesn't follow mounts.
255   * SMP-safe.
256   */
257 -struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
258 +struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
259 +                              struct lookup_intent *it)
260  {
261         struct dentry * dentry;
262         struct inode *inode;
263 @@ -802,13 +864,16 @@ struct dentry * lookup_hash(struct qstr 
264                         goto out;
265         }
266  
267 -       dentry = cached_lookup(base, name, 0);
268 +       dentry = cached_lookup(base, name, 0, it);
269         if (!dentry) {
270                 struct dentry *new = d_alloc(base, name);
271                 dentry = ERR_PTR(-ENOMEM);
272                 if (!new)
273                         goto out;
274                 lock_kernel();
275 +               if (inode->i_op->lookup2)
276 +                       dentry = inode->i_op->lookup2(inode, new, it);
277 +               else
278                 dentry = inode->i_op->lookup(inode, new);
279                 unlock_kernel();
280                 if (!dentry)
281 @@ -820,6 +885,12 @@ out:
282         return dentry;
283  }
284  
285 +struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
286 +{
287 +       return lookup_hash_it(name, base, NULL);
288 +}
289 +
290 +
291  /* SMP-safe */
292  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
293  {
294 @@ -841,7 +912,7 @@ struct dentry * lookup_one_len(const cha
295         }
296         this.hash = end_name_hash(hash);
297  
298 -       return lookup_hash(&this, base);
299 +       return lookup_hash_it(&this, base, NULL);
300  access:
301         return ERR_PTR(-EACCES);
302  }
303 @@ -872,6 +943,23 @@ int __user_walk(const char *name, unsign
304         return err;
305  }
306  
307 +int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
308 +                  struct lookup_intent *it)
309 +{
310 +       char *tmp;
311 +       int err;
312 +
313 +       tmp = getname(name);
314 +       err = PTR_ERR(tmp);
315 +       if (!IS_ERR(tmp)) {
316 +               err = 0;
317 +               if (path_init(tmp, flags, nd))
318 +                       err = path_walk_it(tmp, nd, it);
319 +               putname(tmp);
320 +       }
321 +       return err;
322 +}
323 +
324  /*
325   * It's inline, so penalty for filesystems that don't use sticky bit is
326   * minimal.
327 @@ -1010,7 +1098,8 @@ exit_lock:
328   * for symlinks (where the permissions are checked later).
329   * SMP-safe
330   */
331 -int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
332 +int open_namei_it(const char *pathname, int flag, int mode,
333 +                 struct nameidata *nd, struct lookup_intent *it)
334  {
335         int acc_mode, error = 0;
336         struct inode *inode;
337 @@ -1024,7 +1113,7 @@ int open_namei(const char * pathname, in
338          * The simplest case - just a plain lookup.
339          */
340         if (!(flag & O_CREAT)) {
341 -               error = path_lookup(pathname, lookup_flags(flag), nd);
342 +               error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
343                 if (error)
344                         return error;
345                 dentry = nd->dentry;
346 @@ -1034,6 +1123,10 @@ int open_namei(const char * pathname, in
347         /*
348          * Create - we need to know the parent.
349          */
350 +       if (it) {
351 +               it->it_mode = mode;
352 +               it->it_op |= IT_CREAT;
353 +       }
354         error = path_lookup(pathname, LOOKUP_PARENT, nd);
355         if (error)
356                 return error;
357 @@ -1049,7 +1142,7 @@ int open_namei(const char * pathname, in
358  
359         dir = nd->dentry;
360         down(&dir->d_inode->i_sem);
361 -       dentry = lookup_hash(&nd->last, nd->dentry);
362 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
363  
364  do_last:
365         error = PTR_ERR(dentry);
366 @@ -1058,6 +1151,7 @@ do_last:
367                 goto exit;
368         }
369  
370 +       it->it_mode = mode;
371         /* Negative dentry, just create the file */
372         if (!dentry->d_inode) {
373                 error = vfs_create(dir->d_inode, dentry,
374 @@ -1091,7 +1185,8 @@ do_last:
375         error = -ENOENT;
376         if (!dentry->d_inode)
377                 goto exit_dput;
378 -       if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
379 +       if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link || 
380 +                                      dentry->d_inode->i_op->follow_link2))
381                 goto do_link;
382  
383         dput(nd->dentry);
384 @@ -1177,8 +1272,10 @@ ok:
385         return 0;
386  
387  exit_dput:
388 +       intent_release(dentry, it);
389         dput(dentry);
390  exit:
391 +       intent_release(nd->dentry, it);
392         path_release(nd);
393         return error;
394  
395 @@ -1197,7 +1294,12 @@ do_link:
396          * are done. Procfs-like symlinks just set LAST_BIND.
397          */
398         UPDATE_ATIME(dentry->d_inode);
399 -       error = dentry->d_inode->i_op->follow_link(dentry, nd);
400 +        if (dentry->d_inode->i_op->follow_link2) 
401 +                error = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
402 +        else 
403 +                error = dentry->d_inode->i_op->follow_link(dentry, nd);
404 +       if (error)
405 +               intent_release(dentry, it);
406         dput(dentry);
407         if (error)
408                 return error;
409 @@ -1219,13 +1321,20 @@ do_link:
410         }
411         dir = nd->dentry;
412         down(&dir->d_inode->i_sem);
413 -       dentry = lookup_hash(&nd->last, nd->dentry);
414 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
415         putname(nd->last.name);
416         goto do_last;
417  }
418  
419 +int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
420 +{
421 +       return open_namei_it(pathname, flag, mode, nd, NULL);
422 +}
423 +
424 +
425  /* SMP-safe */
426 -static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
427 +static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
428 +                                   struct lookup_intent *it)
429  {
430         struct dentry *dentry;
431  
432 @@ -1233,7 +1342,7 @@ static struct dentry *lookup_create(stru
433         dentry = ERR_PTR(-EEXIST);
434         if (nd->last_type != LAST_NORM)
435                 goto fail;
436 -       dentry = lookup_hash(&nd->last, nd->dentry);
437 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
438         if (IS_ERR(dentry))
439                 goto fail;
440         if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
441 @@ -1279,6 +1388,7 @@ asmlinkage long sys_mknod(const char * f
442         char * tmp;
443         struct dentry * dentry;
444         struct nameidata nd;
445 +       struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
446  
447         if (S_ISDIR(mode))
448                 return -EPERM;
449 @@ -1289,7 +1399,7 @@ asmlinkage long sys_mknod(const char * f
450         error = path_lookup(tmp, LOOKUP_PARENT, &nd);
451         if (error)
452                 goto out;
453 -       dentry = lookup_create(&nd, 0);
454 +       dentry = lookup_create(&nd, 0, &it);
455         error = PTR_ERR(dentry);
456  
457         mode &= ~current->fs->umask;
458 @@ -1307,6 +1417,7 @@ asmlinkage long sys_mknod(const char * f
459                 default:
460                         error = -EINVAL;
461                 }
462 +               intent_release(dentry, &it);
463                 dput(dentry);
464         }
465         up(&nd.dentry->d_inode->i_sem);
466 @@ -1347,6 +1458,7 @@ asmlinkage long sys_mkdir(const char * p
467  {
468         int error = 0;
469         char * tmp;
470 +       struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
471  
472         tmp = getname(pathname);
473         error = PTR_ERR(tmp);
474 @@ -1357,11 +1469,12 @@ asmlinkage long sys_mkdir(const char * p
475                 error = path_lookup(tmp, LOOKUP_PARENT, &nd);
476                 if (error)
477                         goto out;
478 -               dentry = lookup_create(&nd, 1);
479 +               dentry = lookup_create(&nd, 1, &it);
480                 error = PTR_ERR(dentry);
481                 if (!IS_ERR(dentry)) {
482                         error = vfs_mkdir(nd.dentry->d_inode, dentry,
483                                           mode & ~current->fs->umask);
484 +                       intent_release(dentry, &it);
485                         dput(dentry);
486                 }
487                 up(&nd.dentry->d_inode->i_sem);
488 @@ -1445,6 +1558,7 @@ asmlinkage long sys_rmdir(const char * p
489         char * name;
490         struct dentry *dentry;
491         struct nameidata nd;
492 +       struct lookup_intent it = { .it_op = IT_RMDIR };
493  
494         name = getname(pathname);
495         if(IS_ERR(name))
496 @@ -1466,10 +1580,11 @@ asmlinkage long sys_rmdir(const char * p
497                         goto exit1;
498         }
499         down(&nd.dentry->d_inode->i_sem);
500 -       dentry = lookup_hash(&nd.last, nd.dentry);
501 +       dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
502         error = PTR_ERR(dentry);
503         if (!IS_ERR(dentry)) {
504                 error = vfs_rmdir(nd.dentry->d_inode, dentry);
505 +               intent_release(dentry, &it);
506                 dput(dentry);
507         }
508         up(&nd.dentry->d_inode->i_sem);
509 @@ -1513,6 +1628,7 @@ asmlinkage long sys_unlink(const char * 
510         char * name;
511         struct dentry *dentry;
512         struct nameidata nd;
513 +       struct lookup_intent it = { .it_op = IT_UNLINK };
514  
515         name = getname(pathname);
516         if(IS_ERR(name))
517 @@ -1525,7 +1641,7 @@ asmlinkage long sys_unlink(const char * 
518         if (nd.last_type != LAST_NORM)
519                 goto exit1;
520         down(&nd.dentry->d_inode->i_sem);
521 -       dentry = lookup_hash(&nd.last, nd.dentry);
522 +       dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
523         error = PTR_ERR(dentry);
524         if (!IS_ERR(dentry)) {
525                 /* Why not before? Because we want correct error value */
526 @@ -1533,6 +1649,7 @@ asmlinkage long sys_unlink(const char * 
527                         goto slashes;
528                 error = vfs_unlink(nd.dentry->d_inode, dentry);
529         exit2:
530 +               intent_release(dentry, &it);
531                 dput(dentry);
532         }
533         up(&nd.dentry->d_inode->i_sem);
534 @@ -1579,6 +1696,7 @@ asmlinkage long sys_symlink(const char *
535         int error = 0;
536         char * from;
537         char * to;
538 +       struct lookup_intent it = { .it_op = IT_SYMLINK };
539  
540         from = getname(oldname);
541         if(IS_ERR(from))
542 @@ -1592,10 +1710,12 @@ asmlinkage long sys_symlink(const char *
543                 error = path_lookup(to, LOOKUP_PARENT, &nd);
544                 if (error)
545                         goto out;
546 -               dentry = lookup_create(&nd, 0);
547 +               it.it_data = from;
548 +               dentry = lookup_create(&nd, 0, &it);
549                 error = PTR_ERR(dentry);
550                 if (!IS_ERR(dentry)) {
551                         error = vfs_symlink(nd.dentry->d_inode, dentry, from);
552 +                       intent_release(dentry, &it);
553                         dput(dentry);
554                 }
555                 up(&nd.dentry->d_inode->i_sem);
556 @@ -1660,6 +1780,7 @@ asmlinkage long sys_link(const char * ol
557  {
558         int error;
559         char * to;
560 +       struct lookup_intent it = { .it_op = IT_LINK };
561  
562         to = getname(newname);
563         error = PTR_ERR(to);
564 @@ -1667,7 +1788,7 @@ asmlinkage long sys_link(const char * ol
565                 struct dentry *new_dentry;
566                 struct nameidata nd, old_nd;
567  
568 -               error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd);
569 +               error = __user_walk_it(oldname, LOOKUP_POSITIVE, &old_nd, &it);
570                 if (error)
571                         goto exit;
572                 error = path_lookup(to, LOOKUP_PARENT, &nd);
573 @@ -1676,10 +1797,12 @@ asmlinkage long sys_link(const char * ol
574                 error = -EXDEV;
575                 if (old_nd.mnt != nd.mnt)
576                         goto out_release;
577 -               new_dentry = lookup_create(&nd, 0);
578 +               it.it_op = IT_LINK2;
579 +               new_dentry = lookup_create(&nd, 0, &it);
580                 error = PTR_ERR(new_dentry);
581                 if (!IS_ERR(new_dentry)) {
582                         error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
583 +                       intent_release(new_dentry, &it);
584                         dput(new_dentry);
585                 }
586                 up(&nd.dentry->d_inode->i_sem);
587 @@ -1720,7 +1843,8 @@ exit:
588   *        locking].
589   */
590  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
591 -              struct inode *new_dir, struct dentry *new_dentry)
592 +                  struct inode *new_dir, struct dentry *new_dentry,
593 +                  struct lookup_intent *it)
594  {
595         int error;
596         struct inode *target;
597 @@ -1778,6 +1902,7 @@ int vfs_rename_dir(struct inode *old_dir
598                 error = -EBUSY;
599         else 
600                 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
601 +       intent_release(new_dentry, it);
602         if (target) {
603                 if (!error)
604                         target->i_flags |= S_DEAD;
605 @@ -1799,7 +1924,8 @@ out_unlock:
606  }
607  
608  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
609 -              struct inode *new_dir, struct dentry *new_dentry)
610 +                    struct inode *new_dir, struct dentry *new_dentry,
611 +                    struct lookup_intent *it)
612  {
613         int error;
614  
615 @@ -1830,6 +1956,7 @@ int vfs_rename_other(struct inode *old_d
616                 error = -EBUSY;
617         else
618                 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
619 +       intent_release(new_dentry, it);
620         double_up(&old_dir->i_zombie, &new_dir->i_zombie);
621         if (error)
622                 return error;
623 @@ -1841,13 +1968,14 @@ int vfs_rename_other(struct inode *old_d
624  }
625  
626  int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
627 -              struct inode *new_dir, struct dentry *new_dentry)
628 +              struct inode *new_dir, struct dentry *new_dentry,
629 +              struct lookup_intent *it)
630  {
631         int error;
632         if (S_ISDIR(old_dentry->d_inode->i_mode))
633 -               error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
634 +               error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
635         else
636 -               error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
637 +               error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
638         if (!error) {
639                 if (old_dir == new_dir)
640                         inode_dir_notify(old_dir, DN_RENAME);
641 @@ -1864,6 +1992,7 @@ static inline int do_rename(const char *
642         int error = 0;
643         struct dentry * old_dir, * new_dir;
644         struct dentry * old_dentry, *new_dentry;
645 +       struct lookup_intent it = { .it_op = IT_RENAME };
646         struct nameidata oldnd, newnd;
647  
648         error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
649 @@ -1889,7 +2018,7 @@ static inline int do_rename(const char *
650  
651         double_lock(new_dir, old_dir);
652  
653 -       old_dentry = lookup_hash(&oldnd.last, old_dir);
654 +       old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
655         error = PTR_ERR(old_dentry);
656         if (IS_ERR(old_dentry))
657                 goto exit3;
658 @@ -1905,18 +2034,21 @@ static inline int do_rename(const char *
659                 if (newnd.last.name[newnd.last.len])
660                         goto exit4;
661         }
662 -       new_dentry = lookup_hash(&newnd.last, new_dir);
663 +       it.it_op = IT_RENAME2;
664 +       new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
665         error = PTR_ERR(new_dentry);
666         if (IS_ERR(new_dentry))
667                 goto exit4;
668  
669         lock_kernel();
670         error = vfs_rename(old_dir->d_inode, old_dentry,
671 -                                  new_dir->d_inode, new_dentry);
672 +                                  new_dir->d_inode, new_dentry, &it);
673         unlock_kernel();
674  
675 +       intent_release(new_dentry, &it);
676         dput(new_dentry);
677  exit4:
678 +       intent_release(old_dentry, &it);
679         dput(old_dentry);
680  exit3:
681         double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
682 @@ -1965,7 +2097,8 @@ out:
683  }
684  
685  static inline int
686 -__vfs_follow_link(struct nameidata *nd, const char *link)
687 +__vfs_follow_link(struct nameidata *nd, const char *link, 
688 +                     struct lookup_intent *it)
689  {
690         int res = 0;
691         char *name;
692 @@ -1978,7 +2111,7 @@ __vfs_follow_link(struct nameidata *nd, 
693                         /* weird __emul_prefix() stuff did it */
694                         goto out;
695         }
696 -       res = link_path_walk(link, nd);
697 +       res = link_path_walk_it(link, nd, it);
698  out:
699         if (current->link_count || res || nd->last_type!=LAST_NORM)
700                 return res;
701 @@ -2000,7 +2133,13 @@ fail:
702  
703  int vfs_follow_link(struct nameidata *nd, const char *link)
704  {
705 -       return __vfs_follow_link(nd, link);
706 +       return __vfs_follow_link(nd, link, NULL);
707 +}
708 +
709 +int vfs_follow_link_it(struct nameidata *nd, const char *link, 
710 +                       struct lookup_intent *it)
711 +{
712 +       return __vfs_follow_link(nd, link, it);
713  }
714  
715  /* get the link contents into pagecache */
716 @@ -2042,7 +2181,7 @@ int page_follow_link(struct dentry *dent
717  {
718         struct page *page = NULL;
719         char *s = page_getlink(dentry, &page);
720 -       int res = __vfs_follow_link(nd, s);
721 +       int res = __vfs_follow_link(nd, s, NULL);
722         if (page) {
723                 kunmap(page);
724                 page_cache_release(page);
725 --- linux-2.4.18-17.8.0/fs/nfsd/vfs.c~vfs_intent        2002-12-06 14:52:31.000000000 -0800
726 +++ linux-2.4.18-17.8.0-zab/fs/nfsd/vfs.c       2002-12-06 14:52:31.000000000 -0800
727 @@ -1298,7 +1298,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
728                         err = nfserr_perm;
729         } else
730  #endif
731 -       err = vfs_rename(fdir, odentry, tdir, ndentry);
732 +       err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
733         unlock_kernel();
734         if (!err && EX_ISSYNC(tfhp->fh_export)) {
735                 nfsd_sync_dir(tdentry);
736 --- linux-2.4.18-17.8.0/fs/open.c~vfs_intent    2002-12-06 14:52:31.000000000 -0800
737 +++ linux-2.4.18-17.8.0-zab/fs/open.c   2002-12-06 14:52:31.000000000 -0800
738 @@ -19,6 +19,9 @@
739  #include <asm/uaccess.h>
740  
741  #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
742 +extern int path_walk_it(const char *name, struct nameidata *nd,
743 +                       struct lookup_intent *it);
744 +extern void intent_release(struct dentry *de, struct lookup_intent *it);
745  
746  int vfs_statfs(struct super_block *sb, struct statfs *buf)
747  {
748 @@ -118,12 +121,13 @@ static inline long do_sys_truncate(const
749         struct nameidata nd;
750         struct inode * inode;
751         int error;
752 +       struct lookup_intent it = { .it_op = IT_SETATTR };
753  
754         error = -EINVAL;
755         if (length < 0) /* sorry, but loff_t says... */
756                 goto out;
757  
758 -       error = user_path_walk(path, &nd);
759 +       error = user_path_walk_it(path, &nd, &it);
760         if (error)
761                 goto out;
762         inode = nd.dentry->d_inode;
763 @@ -168,6 +172,7 @@ static inline long do_sys_truncate(const
764         put_write_access(inode);
765  
766  dput_and_out:
767 +       intent_release(nd.dentry, &it);
768         path_release(&nd);
769  out:
770         return error;
771 @@ -259,8 +264,9 @@ asmlinkage long sys_utime(char * filenam
772         struct nameidata nd;
773         struct inode * inode;
774         struct iattr newattrs;
775 +       struct lookup_intent it = { .it_op = IT_SETATTR };
776  
777 -       error = user_path_walk(filename, &nd);
778 +       error = user_path_walk_it(filename, &nd, &it);
779         if (error)
780                 goto out;
781         inode = nd.dentry->d_inode;
782 @@ -286,6 +292,7 @@ asmlinkage long sys_utime(char * filenam
783         }
784         error = notify_change(nd.dentry, &newattrs);
785  dput_and_out:
786 +       intent_release(nd.dentry, &it);
787         path_release(&nd);
788  out:
789         return error;
790 @@ -303,8 +310,9 @@ asmlinkage long sys_utimes(char * filena
791         struct nameidata nd;
792         struct inode * inode;
793         struct iattr newattrs;
794 +       struct lookup_intent it = { .it_op = IT_SETATTR };
795  
796 -       error = user_path_walk(filename, &nd);
797 +       error = user_path_walk_it(filename, &nd, &it);
798  
799         if (error)
800                 goto out;
801 @@ -331,6 +339,7 @@ asmlinkage long sys_utimes(char * filena
802         }
803         error = notify_change(nd.dentry, &newattrs);
804  dput_and_out:
805 +       intent_release(nd.dentry, &it);
806         path_release(&nd);
807  out:
808         return error;
809 @@ -347,6 +356,7 @@ asmlinkage long sys_access(const char * 
810         int old_fsuid, old_fsgid;
811         kernel_cap_t old_cap;
812         int res;
813 +       struct lookup_intent it = { .it_op = IT_GETATTR };
814  
815         if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
816                 return -EINVAL;
817 @@ -364,13 +374,14 @@ asmlinkage long sys_access(const char * 
818         else
819                 current->cap_effective = current->cap_permitted;
820  
821 -       res = user_path_walk(filename, &nd);
822 +       res = user_path_walk_it(filename, &nd, &it);
823         if (!res) {
824                 res = permission(nd.dentry->d_inode, mode);
825                 /* SuS v2 requires we report a read only fs too */
826                 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
827                    && !special_file(nd.dentry->d_inode->i_mode))
828                         res = -EROFS;
829 +               intent_release(nd.dentry, &it);
830                 path_release(&nd);
831         }
832  
833 @@ -385,8 +396,11 @@ asmlinkage long sys_chdir(const char * f
834  {
835         int error;
836         struct nameidata nd;
837 +       struct lookup_intent it = { .it_op = IT_GETATTR };
838  
839 -       error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
840 +       error = __user_walk_it(filename,
841 +                              LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,
842 +                              &nd, &it);
843         if (error)
844                 goto out;
845  
846 @@ -397,6 +411,7 @@ asmlinkage long sys_chdir(const char * f
847         set_fs_pwd(current->fs, nd.mnt, nd.dentry);
848  
849  dput_and_out:
850 +       intent_release(nd.dentry, &it);
851         path_release(&nd);
852  out:
853         return error;
854 @@ -436,9 +451,10 @@ asmlinkage long sys_chroot(const char * 
855  {
856         int error;
857         struct nameidata nd;
858 +       struct lookup_intent it = { .it_op = IT_GETATTR };
859  
860 -       error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
861 -                     LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
862 +       error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
863 +                              LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
864         if (error)
865                 goto out;
866  
867 @@ -454,6 +470,7 @@ asmlinkage long sys_chroot(const char * 
868         set_fs_altroot();
869         error = 0;
870  dput_and_out:
871 +       intent_release(nd.dentry, &it);
872         path_release(&nd);
873  out:
874         return error;
875 @@ -498,8 +515,9 @@ asmlinkage long sys_chmod(const char * f
876         struct inode * inode;
877         int error;
878         struct iattr newattrs;
879 +       struct lookup_intent it = { .it_op = IT_SETATTR };
880  
881 -       error = user_path_walk(filename, &nd);
882 +       error = user_path_walk_it(filename, &nd, &it);
883         if (error)
884                 goto out;
885         inode = nd.dentry->d_inode;
886 @@ -519,6 +537,7 @@ asmlinkage long sys_chmod(const char * f
887         error = notify_change(nd.dentry, &newattrs);
888  
889  dput_and_out:
890 +       intent_release(nd.dentry, &it);
891         path_release(&nd);
892  out:
893         return error;
894 @@ -588,10 +607,12 @@ asmlinkage long sys_chown(const char * f
895  {
896         struct nameidata nd;
897         int error;
898 +       struct lookup_intent it = { .it_op = IT_SETATTR };
899  
900 -       error = user_path_walk(filename, &nd);
901 +       error = user_path_walk_it(filename, &nd, &it);
902         if (!error) {
903                 error = chown_common(nd.dentry, user, group);
904 +               intent_release(nd.dentry, &it);
905                 path_release(&nd);
906         }
907         return error;
908 @@ -601,10 +622,12 @@ asmlinkage long sys_lchown(const char * 
909  {
910         struct nameidata nd;
911         int error;
912 +       struct lookup_intent it = { .it_op = IT_SETATTR };
913  
914 -       error = user_path_walk_link(filename, &nd);
915 +       error = user_path_walk_link_it(filename, &nd, &it);
916         if (!error) {
917                 error = chown_common(nd.dentry, user, group);
918 +               intent_release(nd.dentry, &it);
919                 path_release(&nd);
920         }
921         return error;
922 @@ -638,10 +661,16 @@ asmlinkage long sys_fchown(unsigned int 
923   * for the internal routines (ie open_namei()/follow_link() etc). 00 is
924   * used by symlinks.
925   */
926 +extern int open_namei_it(const char *filename, int namei_flags, int mode,
927 +                        struct nameidata *nd, struct lookup_intent *it);
928 +struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
929 +                           int flags, struct lookup_intent *it);
930 +
931  struct file *filp_open(const char * filename, int flags, int mode)
932  {
933         int namei_flags, error;
934         struct nameidata nd;
935 +       struct lookup_intent it = { .it_op = IT_OPEN };
936  
937         namei_flags = flags;
938         if ((namei_flags+1) & O_ACCMODE)
939 @@ -649,18 +678,19 @@ struct file *filp_open(const char * file
940         if (namei_flags & O_TRUNC)
941                 namei_flags |= 2;
942  
943 -       error = open_namei(filename, namei_flags, mode, &nd);
944 -       if (!error)
945 -               return dentry_open(nd.dentry, nd.mnt, flags);
946 +       error = open_namei_it(filename, namei_flags, mode, &nd, &it);
947 +       if (error)
948 +               return ERR_PTR(error);
949  
950 -       return ERR_PTR(error);
951 +       return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
952  }
953  
954  extern ssize_t do_readahead(struct file *file, unsigned long index, unsigned long nr);
955  /* for files over a certains size it doesn't pay to do readahead on open */
956  #define READAHEAD_CUTOFF 48000
957  
958 -struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
959 +struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
960 +                           int flags, struct lookup_intent *it)
961  {
962         struct file * f;
963         struct inode *inode;
964 @@ -711,6 +741,7 @@ struct file *dentry_open(struct dentry *
965                 do_readahead(f, 0, (48 * 1024) >> PAGE_SHIFT);
966         
967  
968 +       intent_release(dentry, it);
969         return f;
970  
971  cleanup_all:
972 @@ -725,11 +756,17 @@ cleanup_all:
973  cleanup_file:
974         put_filp(f);
975  cleanup_dentry:
976 +       intent_release(dentry, it);
977         dput(dentry);
978         mntput(mnt);
979         return ERR_PTR(error);
980  }
981  
982 +struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
983 +{
984 +       return dentry_open_it(dentry, mnt, flags, NULL);
985 +}
986 +
987  /*
988   * Find an empty file descriptor entry, and mark it busy.
989   */
990 --- linux-2.4.18-17.8.0/fs/stat.c~vfs_intent    2002-12-06 14:52:31.000000000 -0800
991 +++ linux-2.4.18-17.8.0-zab/fs/stat.c   2002-12-06 14:52:31.000000000 -0800
992 @@ -13,6 +13,7 @@
993  
994  #include <asm/uaccess.h>
995  
996 +extern void intent_release(struct dentry *de, struct lookup_intent *it);
997  /*
998   * Revalidate the inode. This is required for proper NFS attribute caching.
999   */
1000 @@ -104,10 +105,12 @@ int vfs_stat(char *name, struct kstat *s
1001  {
1002         struct nameidata nd;
1003         int error;
1004 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1005  
1006 -       error = user_path_walk(name, &nd);
1007 +       error = user_path_walk_it(name, &nd, &it);
1008         if (!error) {
1009                 error = do_getattr(nd.mnt, nd.dentry, stat);
1010 +               intent_release(nd.dentry, &it);
1011                 path_release(&nd);
1012         }
1013         return error;
1014 @@ -117,10 +120,12 @@ int vfs_lstat(char *name, struct kstat *
1015  {
1016         struct nameidata nd;
1017         int error;
1018 +       struct lookup_intent it = { .it_op = IT_GETATTR };
1019  
1020 -       error = user_path_walk_link(name, &nd);
1021 +       error = user_path_walk_link_it(name, &nd, &it);
1022         if (!error) {
1023                 error = do_getattr(nd.mnt, nd.dentry, stat);
1024 +               intent_release(nd.dentry, &it);
1025                 path_release(&nd);
1026         }
1027         return error;
1028 --- linux-2.4.18-17.8.0/include/linux/dcache.h~vfs_intent       2002-12-06 14:52:31.000000000 -0800
1029 +++ linux-2.4.18-17.8.0-zab/include/linux/dcache.h      2002-12-06 14:52:31.000000000 -0800
1030 @@ -6,6 +6,34 @@
1031  #include <asm/atomic.h>
1032  #include <linux/mount.h>
1033  
1034 +#define IT_OPEN  (1)
1035 +#define IT_CREAT  (1<<1)
1036 +#define IT_MKDIR  (1<<2)
1037 +#define IT_LINK  (1<<3)
1038 +#define IT_LINK2  (1<<4)
1039 +#define IT_SYMLINK  (1<<5)
1040 +#define IT_UNLINK  (1<<6)
1041 +#define IT_RMDIR  (1<<7)
1042 +#define IT_RENAME  (1<<8)
1043 +#define IT_RENAME2  (1<<9)
1044 +#define IT_READDIR  (1<<10)
1045 +#define IT_GETATTR  (1<<11)
1046 +#define IT_SETATTR  (1<<12)
1047 +#define IT_READLINK  (1<<13)
1048 +#define IT_MKNOD  (1<<14)
1049 +#define IT_LOOKUP  (1<<15)
1050 +
1051 +struct lookup_intent {
1052 +       int it_op;
1053 +       int it_mode;
1054 +       int it_disposition;
1055 +       int it_status;
1056 +       struct iattr *it_iattr;
1057 +       __u64 it_lock_handle[2];
1058 +       int it_lock_mode;
1059 +       void *it_data;
1060 +};
1061 +
1062  /*
1063   * linux/include/linux/dcache.h
1064   *
1065 @@ -78,6 +106,7 @@ struct dentry {
1066         unsigned long d_time;           /* used by d_revalidate */
1067         struct dentry_operations  *d_op;
1068         struct super_block * d_sb;      /* The root of the dentry tree */
1069 +       struct lookup_intent *d_it;
1070         unsigned long d_vfs_flags;
1071         void * d_fsdata;                /* fs-specific data */
1072         void * d_extra_attributes;      /* TUX-specific data */
1073 @@ -91,6 +120,8 @@ struct dentry_operations {
1074         int (*d_delete)(struct dentry *);
1075         void (*d_release)(struct dentry *);
1076         void (*d_iput)(struct dentry *, struct inode *);
1077 +       int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
1078 +       void (*d_intent_release)(struct dentry *, struct lookup_intent *);
1079  };
1080  
1081  /* the dentry parameter passed to d_hash and d_compare is the parent
1082 --- linux-2.4.18-17.8.0/include/linux/fs.h~vfs_intent   2002-12-06 14:52:31.000000000 -0800
1083 +++ linux-2.4.18-17.8.0-zab/include/linux/fs.h  2002-12-06 14:52:31.000000000 -0800
1084 @@ -576,6 +576,7 @@ struct file {
1085  
1086         /* needed for tty driver, and maybe others */
1087         void                    *private_data;
1088 +       struct lookup_intent    *f_intent;
1089  
1090         /* preallocated helper kiobuf to speedup O_DIRECT */
1091         struct kiobuf           *f_iobuf;
1092 @@ -836,7 +837,9 @@ extern int vfs_symlink(struct inode *, s
1093  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
1094  extern int vfs_rmdir(struct inode *, struct dentry *);
1095  extern int vfs_unlink(struct inode *, struct dentry *);
1096 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
1097 +int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1098 +               struct inode *new_dir, struct dentry *new_dentry,
1099 +               struct lookup_intent *it);
1100  
1101  /*
1102   * File types
1103 @@ -897,6 +900,7 @@ struct file_operations {
1104  struct inode_operations {
1105         int (*create) (struct inode *,struct dentry *,int);
1106         struct dentry * (*lookup) (struct inode *,struct dentry *);
1107 +       struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
1108         int (*link) (struct dentry *,struct inode *,struct dentry *);
1109         int (*unlink) (struct inode *,struct dentry *);
1110         int (*symlink) (struct inode *,struct dentry *,const char *);
1111 @@ -907,6 +911,8 @@ struct inode_operations {
1112                         struct inode *, struct dentry *);
1113         int (*readlink) (struct dentry *, char *,int);
1114         int (*follow_link) (struct dentry *, struct nameidata *);
1115 +       int (*follow_link2) (struct dentry *, struct nameidata *, 
1116 +                            struct lookup_intent *it);
1117         void (*truncate) (struct inode *);
1118         int (*permission) (struct inode *, int);
1119         int (*revalidate) (struct dentry *);
1120 @@ -1381,6 +1387,7 @@ typedef int (*read_actor_t)(read_descrip
1121  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
1122  
1123  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
1124 +extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
1125  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
1126  extern int FASTCALL(path_walk(const char *, struct nameidata *));
1127  extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
1128 @@ -1392,6 +1399,8 @@ extern struct dentry * lookup_one_len(co
1129  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
1130  #define user_path_walk(name,nd)         __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
1131  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
1132 +#define user_path_walk_it(name,nd,it)  __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
1133 +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
1134  
1135  extern void inode_init_once(struct inode *);
1136  extern void iput(struct inode *);
1137 @@ -1492,6 +1501,8 @@ extern struct file_operations generic_ro
1138  
1139  extern int vfs_readlink(struct dentry *, char *, int, const char *);
1140  extern int vfs_follow_link(struct nameidata *, const char *);
1141 +extern int vfs_follow_link_it(struct nameidata *, const char *, 
1142 +                              struct lookup_intent *it);
1143  extern int page_readlink(struct dentry *, char *, int);
1144  extern int page_follow_link(struct dentry *, struct nameidata *);
1145  extern struct inode_operations page_symlink_inode_operations;
1146 --- linux-2.4.18-17.8.0/kernel/ksyms.c~vfs_intent       2002-12-06 14:52:31.000000000 -0800
1147 +++ linux-2.4.18-17.8.0-zab/kernel/ksyms.c      2002-12-06 14:52:31.000000000 -0800
1148 @@ -293,6 +293,7 @@ EXPORT_SYMBOL(read_cache_page);
1149  EXPORT_SYMBOL(set_page_dirty);
1150  EXPORT_SYMBOL(vfs_readlink);
1151  EXPORT_SYMBOL(vfs_follow_link);
1152 +EXPORT_SYMBOL(vfs_follow_link_it);
1153  EXPORT_SYMBOL(page_readlink);
1154  EXPORT_SYMBOL(page_follow_link);
1155  EXPORT_SYMBOL(page_symlink_inode_operations);
1156
1157 _