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