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