Whamcloud - gitweb
add intent related update to NFS server.
[fs/lustre-release.git] / lustre / patches / patch-2.4.18-chaos1
1 --- kernel-rh-2.4.18-pristine/drivers/block/blkpg.c     Thu Jun 13 12:26:40 2002
2 +++ kernel-rh-2.4.18/drivers/block/blkpg.c      Thu Jun 13 14:49:48 2002
3 @@ -295,3 +295,38 @@
4  }
5  
6  EXPORT_SYMBOL(blk_ioctl);
7 +
8 +#define NUM_DEV_NO_WRITE 16
9 +static int dev_no_write[NUM_DEV_NO_WRITE];
10 +
11 +/*
12 + * Debug code for turning block devices "read-only" (will discard writes
13 + * silently).  This is for filesystem crash/recovery testing.
14 + */
15 +void dev_set_rdonly(kdev_t dev, int no_write)
16 +{
17 +       if (dev) {
18 +               printk(KERN_WARNING "Turning device %s read-only\n", 
19 +                      bdevname(dev));
20 +               dev_no_write[no_write] = 0xdead0000 + dev;
21 +       }
22 +}
23 +
24 +int dev_check_rdonly(kdev_t dev) {
25 +       int i;
26 +
27 +       for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
28 +               if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
29 +                   dev == (dev_no_write[i] & 0xffff))
30 +                       return 1;
31 +       }
32 +       return 0;
33 +}
34 +
35 +void dev_clear_rdonly(int no_write) {
36 +       dev_no_write[no_write] = 0;
37 +}
38 +
39 +EXPORT_SYMBOL(dev_set_rdonly);
40 +EXPORT_SYMBOL(dev_check_rdonly);
41 +EXPORT_SYMBOL(dev_clear_rdonly);
42 --- kernel-rh-2.4.18-pristine/drivers/block/loop.c      Thu Jun 13 12:26:40 2002
43 +++ kernel-rh-2.4.18/drivers/block/loop.c       Thu Jun 13 14:49:48 2002
44 @@ -503,6 +503,11 @@
45         spin_unlock_irq(&lo->lo_lock);
46  
47         if (rw == WRITE) {
48 +#ifdef CONFIG_DEV_RDONLY
49 +               if (dev_check_rdonly(rbh->b_rdev))
50 +                       goto err;
51 +#endif
52 +
53                 if (lo->lo_flags & LO_FLAGS_READ_ONLY)
54                         goto err;
55         } else if (rw == READA) {
56 --- kernel-rh-2.4.18-pristine/drivers/ide/ide-disk.c    Thu Jun 13 12:26:43 2002
57 +++ kernel-rh-2.4.18/drivers/ide/ide-disk.c     Thu Jun 13 14:49:48 2002
58 @@ -557,6 +557,12 @@
59   */
60  static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
61  {
62 +#ifdef CONFIG_DEV_RDONLY
63 +       if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
64 +               ide_end_request(1, HWGROUP(drive));
65 +               return ide_stopped;
66 +       }
67 +#endif
68         if (IDE_CONTROL_REG)
69                 OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
70  
71 --- kernel-rh-2.4.18-pristine/fs/ext3/Makefile  Thu Jun 13 12:27:00 2002
72 +++ kernel-rh-2.4.18/fs/ext3/Makefile   Thu Jun 13 14:49:48 2002
73 @@ -9,6 +9,8 @@
74  
75  O_TARGET := ext3.o
76  
77 +export-objs := super.o
78 +
79  obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
80                 ioctl.o namei.o super.o symlink.o
81  obj-m    := $(O_TARGET)
82 --- kernel-rh-2.4.18-pristine/fs/ext3/super.c   Thu Jun 13 12:27:01 2002
83 +++ kernel-rh-2.4.18/fs/ext3/super.c    Thu Jun 13 14:49:48 2002
84 @@ -1746,7 +1746,7 @@
85         unregister_filesystem(&ext3_fs_type);
86  }
87  
88 -EXPORT_NO_SYMBOLS;
89 +EXPORT_SYMBOL(ext3_bread);
90  
91  MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
92  MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
93 --- kernel-rh-2.4.18-pristine/fs/jbd/commit.c   Thu Jun 13 12:27:05 2002
94 +++ kernel-rh-2.4.18/fs/jbd/commit.c    Thu Jun 13 14:49:48 2002
95 @@ -482,7 +482,7 @@
96             transaction's t_log_list queue, and metadata buffers are on
97             the t_iobuf_list queue.
98  
99 -          Wait for the transactions in reverse order.  That way we are
100 +          Wait for the buffers in reverse order.  That way we are
101            less likely to be woken up until all IOs have completed, and
102            so we incur less scheduling load.
103         */
104 @@ -575,8 +575,10 @@
105  
106         jbd_debug(3, "JBD: commit phase 6\n");
107  
108 -       if (is_journal_aborted(journal))
109 +       if (is_journal_aborted(journal)) {
110 +               unlock_journal(journal);
111                 goto skip_commit;
112 +       }
113  
114         /* Done it all: now write the commit record.  We should have
115          * cleaned up our previous buffers by now, so if we are in abort
116 @@ -586,9 +588,10 @@
117         descriptor = journal_get_descriptor_buffer(journal);
118         if (!descriptor) {
119                 __journal_abort_hard(journal);
120 +               unlock_journal(journal);
121                 goto skip_commit;
122         }
123 -       
124 +
125         /* AKPM: buglet - add `i' to tmp! */
126         for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
127                 journal_header_t *tmp =
128 @@ -609,7 +612,6 @@
129                 put_bh(bh);             /* One for getblk() */
130                 journal_unlock_journal_head(descriptor);
131         }
132 -       lock_journal(journal);
133  
134         /* End of a transaction!  Finally, we can do checkpoint
135             processing: any buffers committed as a result of this
136 @@ -618,6 +620,25 @@
137  
138  skip_commit:
139  
140 +       /* Call any callbacks that had been registered for handles in this
141 +        * transaction.  It is up to the callback to free any allocated
142 +        * memory.
143 +        */
144 +       if (!list_empty(&commit_transaction->t_jcb)) {
145 +               struct list_head *p, *n;
146 +               int error = is_journal_aborted(journal);
147 +
148 +               list_for_each_safe(p, n, &commit_transaction->t_jcb) {
149 +                       struct journal_callback *jcb;
150 +
151 +                       jcb = list_entry(p, struct journal_callback, jcb_list);
152 +                       list_del(p);
153 +                       jcb->jcb_func(jcb, error);
154 +               }
155 +       }
156 +
157 +       lock_journal(journal);
158 +
159         jbd_debug(3, "JBD: commit phase 7\n");
160  
161         J_ASSERT(commit_transaction->t_sync_datalist == NULL);
162 --- kernel-rh-2.4.18-pristine/fs/jbd/journal.c  Thu Jun 13 12:27:05 2002
163 +++ kernel-rh-2.4.18/fs/jbd/journal.c   Thu Jun 13 14:49:48 2002
164 @@ -58,6 +58,7 @@
165  #endif
166  EXPORT_SYMBOL(journal_flush);
167  EXPORT_SYMBOL(journal_revoke);
168 +EXPORT_SYMBOL(journal_callback_set);
169  
170  EXPORT_SYMBOL(journal_init_dev);
171  EXPORT_SYMBOL(journal_init_inode);
172 --- kernel-rh-2.4.18-pristine/fs/jbd/transaction.c      Thu Jun 13 12:27:05 2002
173 +++ kernel-rh-2.4.18/fs/jbd/transaction.c       Thu Jun 13 14:49:48 2002
174 @@ -57,6 +57,7 @@
175         transaction->t_state = T_RUNNING;
176         transaction->t_tid = journal->j_transaction_sequence++;
177         transaction->t_expires = jiffies + journal->j_commit_interval;
178 +       INIT_LIST_HEAD(&transaction->t_jcb);
179  
180         /* Set up the commit timer for the new transaction. */
181         J_ASSERT (!journal->j_commit_timer_active);
182 @@ -201,6 +202,20 @@
183         return 0;
184  }
185  
186 +/* Allocate a new handle.  This should probably be in a slab... */
187 +static handle_t *get_handle(int nblocks)
188 +{
189 +       handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
190 +       if (!handle)
191 +               return NULL;
192 +       memset(handle, 0, sizeof (handle_t));
193 +       handle->h_buffer_credits = nblocks;
194 +       handle->h_ref = 1;
195 +       INIT_LIST_HEAD(&handle->h_jcb);
196 +
197 +       return handle;
198 +}
199 +
200  /*
201   * Obtain a new handle.  
202   *
203 @@ -227,14 +242,11 @@
204                 handle->h_ref++;
205                 return handle;
206         }
207 -       
208 -       handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
209 +
210 +       handle = get_handle(nblocks);
211         if (!handle)
212                 return ERR_PTR(-ENOMEM);
213 -       memset (handle, 0, sizeof (handle_t));
214  
215 -       handle->h_buffer_credits = nblocks;
216 -       handle->h_ref = 1;
217         current->journal_info = handle;
218  
219         err = start_this_handle(journal, handle);
220 @@ -333,14 +345,11 @@
221         
222         if (is_journal_aborted(journal))
223                 return ERR_PTR(-EIO);
224 -       
225 -       handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
226 +
227 +       handle = get_handle(nblocks);
228         if (!handle)
229                 return ERR_PTR(-ENOMEM);
230 -       memset (handle, 0, sizeof (handle_t));
231  
232 -       handle->h_buffer_credits = nblocks;
233 -       handle->h_ref = 1;
234         current->journal_info = handle;
235  
236         err = try_start_this_handle(journal, handle);
237 @@ -1319,6 +1328,29 @@
238  #endif
239  
240  /*
241 + * Register a callback function for this handle.  The function will be
242 + * called when the transaction that this handle is part of has been
243 + * committed to disk with the original callback data struct and the
244 + * error status of the journal as parameters.  There is no guarantee of
245 + * ordering between handles within a single transaction, nor between
246 + * callbacks registered on the same handle.
247 + *
248 + * The caller is responsible for allocating the journal_callback struct.
249 + * This is to allow the caller to add as much extra data to the callback
250 + * as needed, but reduce the overhead of multiple allocations.  The caller
251 + * allocated struct must start with a struct journal_callback at offset 0,
252 + * and has the caller-specific data afterwards.
253 + */
254 +void journal_callback_set(handle_t *handle, void (*func)(void *, int),
255 +                         void *cb_data)
256 +{
257 +       struct journal_callback *jcb = cb_data;
258 +
259 +       list_add(&jcb->jcb_list, &handle->h_jcb);
260 +       jcb->jcb_func = func;
261 +}
262 +
263 +/*
264   * All done for a particular handle.
265   *
266   * There is not much action needed here.  We just return any remaining
267 @@ -1383,7 +1415,10 @@
268                         wake_up(&journal->j_wait_transaction_locked);
269         }
270  
271 -       /* 
272 +       /* Move callbacks from the handle to the transaction. */
273 +       list_splice(&handle->h_jcb, &transaction->t_jcb);
274 +
275 +       /*
276          * If the handle is marked SYNC, we need to set another commit
277          * going!  We also want to force a commit if the current
278          * transaction is occupying too much of the log, or if the
279 --- kernel-rh-2.4.18-pristine/include/linux/blkdev.h    Thu Jun 13 12:27:14 2002
280 +++ kernel-rh-2.4.18/include/linux/blkdev.h     Thu Jun 13 15:18:33 2002
281 @@ -276,4 +276,9 @@
282         }
283         return retval;
284  }
285 +
286 +#define CONFIG_DEV_RDONLY
287 +void dev_set_rdonly(kdev_t, int);
288 +int dev_check_rdonly(kdev_t);
289 +void dev_clear_rdonly(int);
290  #endif
291 --- kernel-rh-2.4.18-pristine/include/linux/jbd.h       Thu Jun 13 12:27:14 2002
292 +++ kernel-rh-2.4.18/include/linux/jbd.h        Thu Jun 13 15:18:35 2002
293 @@ -257,6 +257,13 @@
294         return bh->b_private;
295  }
296  
297 +#define HAVE_JOURNAL_CALLBACK_STATUS
298 +struct journal_callback {
299 +       struct list_head jcb_list;
300 +       void (*jcb_func)(void *cb_data, int error);
301 +       /* user data goes here */
302 +};
303 +
304  struct jbd_revoke_table_s;
305  
306  /* The handle_t type represents a single atomic update being performed
307 @@ -287,6 +294,12 @@
308            operations */
309         int                     h_err;
310  
311 +       /* List of application registered callbacks for this handle.
312 +        * The function(s) will be called after the transaction that
313 +        * this handle is part of has been committed to disk.
314 +        */
315 +       struct list_head        h_jcb;
316 +
317         /* Flags */
318         unsigned int    h_sync:         1;      /* sync-on-close */
319         unsigned int    h_jdata:        1;      /* force data journaling */
320 @@ -406,6 +419,10 @@
321  
322         /* How many handles used this transaction? */
323         int t_handle_count;
324 +
325 +       /* List of registered callback functions for this transaction.
326 +        * Called when the transaction is committed. */
327 +       struct list_head        t_jcb;
328  };
329  
330  
331 @@ -654,6 +671,8 @@
332  extern int      journal_try_to_free_buffers(journal_t *, struct page *, int);
333  extern int      journal_stop(handle_t *);
334  extern int      journal_flush (journal_t *);
335 +extern void     journal_callback_set(handle_t *handle, void (*fn)(void *, int),
336 +                                     void *cb_data);
337  
338  extern void     journal_lock_updates (journal_t *);
339  extern void     journal_unlock_updates (journal_t *);
340 --- kernel-rh-2.4.18-pristine/kernel/ksyms.c    Thu Jun 13 12:27:15 2002
341 +++ kernel-rh-2.4.18/kernel/ksyms.c     Thu Jun 13 14:49:48 2002
342 @@ -305,6 +305,11 @@
343  EXPORT_SYMBOL(lock_may_write);
344  EXPORT_SYMBOL(dcache_readdir);
345  
346 +/* lustre */
347 +EXPORT_SYMBOL(pagecache_lock);
348 +EXPORT_SYMBOL(do_kern_mount);
349 +
350 +
351  /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
352  EXPORT_SYMBOL(default_llseek);
353  EXPORT_SYMBOL(dentry_open);
354 --- kernel-rh-2.4.18-pristine/include/linux/dcache.h    Thu Jun 13 12:27:14 2002
355 +++ kernel-rh-2.4.18/include/linux/dcache.h     Thu Jun 13 15:18:21 2002
356 @@ -6,6 +6,31 @@
357  #include <asm/atomic.h>
358  #include <linux/mount.h>
359  
360 +#define IT_OPEN  (1)
361 +#define IT_CREAT  (1<<1)
362 +#define IT_MKDIR  (1<<2)
363 +#define IT_LINK  (1<<3)
364 +#define IT_SYMLINK  (1<<4)
365 +#define IT_UNLINK  (1<<5)
366 +#define IT_RMDIR  (1<<6)
367 +#define IT_RENAME  (1<<7)
368 +#define IT_RENAME2  (1<<8)
369 +#define IT_READDIR  (1<<9)
370 +#define IT_GETATTR  (1<<10)
371 +#define IT_SETATTR  (1<<11)
372 +#define IT_READLINK  (1<<12)
373 +
374 +struct lookup_intent { 
375 +       int it_op;
376 +       int it_mode;
377 +       int it_disposition;
378 +       int it_status; 
379 +       struct iattr *it_iattr;
380 +        __u64 it_lock_handle[2];
381 +        int it_lock_mode;
382 +       void *it_data;
383 +};
384 +
385  /*
386   * linux/include/linux/dcache.h
387   *
388 @@ -78,6 +103,7 @@
389         unsigned long d_time;           /* used by d_revalidate */
390         struct dentry_operations  *d_op;
391         struct super_block * d_sb;      /* The root of the dentry tree */
392 +       struct lookup_intent *d_it;
393         unsigned long d_vfs_flags;
394         void * d_fsdata;                /* fs-specific data */
395         void * d_extra_attributes;      /* TUX-specific data */
396 @@ -91,6 +117,8 @@
397         int (*d_delete)(struct dentry *);
398         void (*d_release)(struct dentry *);
399         void (*d_iput)(struct dentry *, struct inode *);
400 +       int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
401 +       void (*d_intent_release)(struct dentry *);
402  };
403  
404  /* the dentry parameter passed to d_hash and d_compare is the parent
405 --- kernel-rh-2.4.18-pristine/include/linux/fs.h        Thu Jun 13 12:27:14 2002
406 +++ kernel-rh-2.4.18/include/linux/fs.h Thu Jun 13 15:18:21 2002
407 @@ -570,6 +570,7 @@
408  
409         /* needed for tty driver, and maybe others */
410         void                    *private_data;
411 +        struct lookup_intent    *f_intent;
412  
413         /* preallocated helper kiobuf to speedup O_DIRECT */
414         struct kiobuf           *f_iobuf;
415 @@ -827,7 +828,9 @@
416  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
417  extern int vfs_rmdir(struct inode *, struct dentry *);
418  extern int vfs_unlink(struct inode *, struct dentry *);
419 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
420 +int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
421 +               struct inode *new_dir, struct dentry *new_dentry, 
422 +               struct lookup_intent *it);
423  
424  /*
425   * File types
426 @@ -888,6 +891,7 @@
427  struct inode_operations {
428         int (*create) (struct inode *,struct dentry *,int);
429         struct dentry * (*lookup) (struct inode *,struct dentry *);
430 +        struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
431         int (*link) (struct dentry *,struct inode *,struct dentry *);
432         int (*unlink) (struct inode *,struct dentry *);
433         int (*symlink) (struct inode *,struct dentry *,const char *);
434 @@ -1034,6 +1038,7 @@
435  extern struct vfsmount *kern_mount(struct file_system_type *);
436  extern int may_umount(struct vfsmount *);
437  extern long do_mount(char *, char *, char *, unsigned long, void *);
438 +struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
439  extern void umount_tree(struct vfsmount *);
440  
441  #define kern_umount mntput
442 @@ -1360,6 +1365,7 @@
443  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
444  
445  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
446 +extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
447  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
448  extern int FASTCALL(path_walk(const char *, struct nameidata *));
449  extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
450 @@ -1370,6 +1376,8 @@
451  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
452  #define user_path_walk(name,nd)         __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
453  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
454 +#define user_path_walk_it(name,nd,it)  __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
455 +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
456  
457  extern void iput(struct inode *);
458  extern void force_delete(struct inode *);
459 --- kernel-rh-2.4.18-pristine/fs/namei.c        Thu Jun 13 12:27:05 2002
460 +++ kernel-rh-2.4.18/fs/namei.c Thu Jun 13 15:08:19 2002
461 @@ -94,6 +94,14 @@
462   * XEmacs seems to be relying on it...
463   */
464  
465 +void intent_release(struct dentry *de) 
466 +{
467 +       if (de->d_op && de->d_op->d_intent_release)
468 +               de->d_op->d_intent_release(de);
469 +       de->d_it = NULL;
470 +}
471 +
472 +
473  /* In order to reduce some races, while at the same time doing additional
474   * checking and hopefully speeding things up, we copy filenames to the
475   * kernel data space before using them..
476 @@ -260,10 +268,18 @@
477   * Internal lookup() using the new generic dcache.
478   * SMP-safe
479   */
480 -static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
481 +static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
482  {
483         struct dentry * dentry = d_lookup(parent, name);
484  
485 +       if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
486 +               if (!dentry->d_op->d_revalidate2(dentry, flags, it) && !d_invalidate(dentry)) {
487 +                       dput(dentry);
488 +                       dentry = NULL;
489 +               }
490 +               return dentry; 
491 +       }
492 +
493         if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
494                 if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
495                         dput(dentry);
496 @@ -281,7 +297,7 @@
497   * make sure that nobody added the entry to the dcache in the meantime..
498   * SMP-safe
499   */
500 -static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
501 +static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags, struct lookup_intent *it)
502  {
503         struct dentry * result;
504         struct inode *dir = parent->d_inode;
505 @@ -300,6 +316,9 @@
506                 result = ERR_PTR(-ENOMEM);
507                 if (dentry) {
508                         lock_kernel();
509 +                       if (dir->i_op->lookup2) 
510 +                               result = dir->i_op->lookup2(dir, dentry, it);
511 +                       else 
512                         result = dir->i_op->lookup(dir, dentry);
513                         unlock_kernel();
514                         if (result)
515 @@ -322,6 +341,12 @@
516                         result = ERR_PTR(-ENOENT);
517                 }
518         }
519 +       if (result->d_op && result->d_op->d_revalidate2) {
520 +               if (!result->d_op->d_revalidate2(result, flags, it) && !d_invalidate(result)) {
521 +                       dput(result);
522 +                       result = ERR_PTR(-ENOENT);
523 +               }
524 +       }
525         return result;
526  }
527  
528 @@ -447,7 +472,7 @@
529   *
530   * We expect 'base' to be positive and a directory.
531   */
532 -int link_path_walk(const char * name, struct nameidata *nd)
533 +int link_path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
534  {
535         struct dentry *dentry;
536         struct inode *inode;
537 @@ -524,12 +549,12 @@
538                                 break;
539                 }
540                 /* This does the actual lookups.. */
541 -               dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
542 +               dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
543                 if (!dentry) {
544                         err = -EWOULDBLOCKIO;
545                         if (atomic)
546                                 break;
547 -                       dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
548 +                       dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
549                         err = PTR_ERR(dentry);
550                         if (IS_ERR(dentry))
551                                 break;
552 @@ -563,7 +588,7 @@
553                         nd->dentry = dentry;
554                 }
555                 err = -ENOTDIR; 
556 -               if (!inode->i_op->lookup)
557 +               if (!inode->i_op->lookup && !inode->i_op->lookup2)
558                         break;
559                 continue;
560                 /* here ends the main loop */
561 @@ -590,12 +615,12 @@
562                         if (err < 0)
563                                 break;
564                 }
565 -               dentry = cached_lookup(nd->dentry, &this, 0);
566 +               dentry = cached_lookup(nd->dentry, &this, 0, it);
567                 if (!dentry) {
568                         err = -EWOULDBLOCKIO;
569                         if (atomic)
570                                 break;
571 -                       dentry = real_lookup(nd->dentry, &this, 0);
572 +                       dentry = real_lookup(nd->dentry, &this, 0, it);
573                         err = PTR_ERR(dentry);
574                         if (IS_ERR(dentry))
575                                 break;
576 @@ -619,7 +644,8 @@
577                         goto no_inode;
578                 if (lookup_flags & LOOKUP_DIRECTORY) {
579                         err = -ENOTDIR; 
580 -                       if (!inode->i_op || !inode->i_op->lookup)
581 +                       if (!inode->i_op || (!inode->i_op->lookup && 
582 +                                            !inode->i_op->lookup2))
583                                 break;
584                 }
585                 goto return_base;
586 @@ -648,12 +674,24 @@
587         return err;
588  }
589  
590 +int link_path_walk(const char * name, struct nameidata *nd)
591 +{
592 +       return link_path_walk_it(name, nd, NULL);
593 +}
594 +
595 +int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
596 +{
597 +       current->total_link_count = 0;
598 +       return link_path_walk_it(name, nd, it);
599 +}
600 +
601  int path_walk(const char * name, struct nameidata *nd)
602  {
603         current->total_link_count = 0;
604 -       return link_path_walk(name, nd);
605 +       return link_path_walk_it(name, nd, NULL);
606  }
607  
608 +
609  /* SMP-safe */
610  /* returns 1 if everything is done */
611  static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
612 @@ -754,7 +792,8 @@
613   * needs parent already locked. Doesn't follow mounts.
614   * SMP-safe.
615   */
616 -struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
617 +struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, 
618 +                           struct lookup_intent *it)
619  {
620         struct dentry * dentry;
621         struct inode *inode;
622 @@ -777,13 +816,16 @@
623                         goto out;
624         }
625  
626 -       dentry = cached_lookup(base, name, 0);
627 +       dentry = cached_lookup(base, name, 0, it);
628         if (!dentry) {
629                 struct dentry *new = d_alloc(base, name);
630                 dentry = ERR_PTR(-ENOMEM);
631                 if (!new)
632                         goto out;
633                 lock_kernel();
634 +               if (inode->i_op->lookup2) 
635 +                       dentry = inode->i_op->lookup2(inode, new, it);
636 +               else 
637                 dentry = inode->i_op->lookup(inode, new);
638                 unlock_kernel();
639                 if (!dentry)
640 @@ -795,6 +837,12 @@
641         return dentry;
642  }
643  
644 +struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
645 +{
646 +       return lookup_hash_it(name, base, NULL);
647 +}
648 +
649 +
650  /* SMP-safe */
651  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
652  {
653 @@ -816,7 +864,7 @@
654         }
655         this.hash = end_name_hash(hash);
656  
657 -       return lookup_hash(&this, base);
658 +       return lookup_hash_it(&this, base, NULL);
659  access:
660         return ERR_PTR(-EACCES);
661  }
662 @@ -848,6 +896,22 @@
663         return err;
664  }
665  
666 +int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, struct lookup_intent *it)
667 +{
668 +       char *tmp;
669 +       int err;
670 +
671 +       tmp = getname(name);
672 +       err = PTR_ERR(tmp);
673 +       if (!IS_ERR(tmp)) {
674 +               err = 0;
675 +               if (path_init(tmp, flags, nd))
676 +                       err = path_walk_it(tmp, nd, it);
677 +               putname(tmp);
678 +       }
679 +       return err;
680 +}
681 +
682  /*
683   * It's inline, so penalty for filesystems that don't use sticky bit is
684   * minimal.
685 @@ -984,7 +1048,8 @@
686   * for symlinks (where the permissions are checked later).
687   * SMP-safe
688   */
689 -int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
690 +int open_namei_it(const char * pathname, int flag, int mode, struct nameidata *nd, 
691 +               struct lookup_intent *it)
692  {
693         int acc_mode, error = 0;
694         struct inode *inode;
695 @@ -998,8 +1063,9 @@
696          * The simplest case - just a plain lookup.
697          */
698         if (!(flag & O_CREAT)) {
699 +
700                 if (path_init(pathname, lookup_flags(flag), nd))
701 -                       error = path_walk(pathname, nd);
702 +                       error = path_walk_it(pathname, nd, it);
703                 if (error)
704                         return error;
705                 dentry = nd->dentry;
706 @@ -1009,6 +1075,8 @@
707         /*
708          * Create - we need to know the parent.
709          */
710 +       if (it) 
711 +               it->it_op |= IT_CREAT;
712         if (path_init(pathname, LOOKUP_PARENT, nd))
713                 error = path_walk(pathname, nd);
714         if (error)
715 @@ -1025,7 +1093,7 @@
716  
717         dir = nd->dentry;
718         down(&dir->d_inode->i_sem);
719 -       dentry = lookup_hash(&nd->last, nd->dentry);
720 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
721  
722  do_last:
723         error = PTR_ERR(dentry);
724 @@ -1036,6 +1104,7 @@
725  
726         /* Negative dentry, just create the file */
727         if (!dentry->d_inode) {
728 +               dentry->d_it = it;
729                 error = vfs_create(dir->d_inode, dentry,
730                                    mode & ~current->fs->umask);
731                 up(&dir->d_inode->i_sem);
732 @@ -1195,13 +1264,20 @@
733         }
734         dir = nd->dentry;
735         down(&dir->d_inode->i_sem);
736 -       dentry = lookup_hash(&nd->last, nd->dentry);
737 +       dentry = lookup_hash_it(&nd->last, nd->dentry, NULL);
738         putname(nd->last.name);
739         goto do_last;
740  }
741  
742 +int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
743 +{
744 +       return open_namei_it(pathname, flag, mode, nd, NULL); 
745 +}
746 +
747 +
748  /* SMP-safe */
749 -static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
750 +static struct dentry *lookup_create(struct nameidata *nd, int is_dir, 
751 +                                   struct lookup_intent *it)
752  {
753         struct dentry *dentry;
754  
755 @@ -1209,7 +1285,7 @@
756         dentry = ERR_PTR(-EEXIST);
757         if (nd->last_type != LAST_NORM)
758                 goto fail;
759 -       dentry = lookup_hash(&nd->last, nd->dentry);
760 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
761         if (IS_ERR(dentry))
762                 goto fail;
763         if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
764 @@ -1255,6 +1331,7 @@
765         char * tmp;
766         struct dentry * dentry;
767         struct nameidata nd;
768 +       struct lookup_intent it = { IT_CREAT , mode };
769  
770         if (S_ISDIR(mode))
771                 return -EPERM;
772 @@ -1266,11 +1343,12 @@
773                 error = path_walk(tmp, &nd);
774         if (error)
775                 goto out;
776 -       dentry = lookup_create(&nd, 0);
777 +       dentry = lookup_create(&nd, 0, &it);
778         error = PTR_ERR(dentry);
779  
780         mode &= ~current->fs->umask;
781         if (!IS_ERR(dentry)) {
782 +               dentry->d_it = &it;
783                 switch (mode & S_IFMT) {
784                 case 0: case S_IFREG:
785                         error = vfs_create(nd.dentry->d_inode,dentry,mode);
786 @@ -1286,6 +1364,7 @@
787                 }
788                 dput(dentry);
789         }
790 +       intent_release(dentry); 
791         up(&nd.dentry->d_inode->i_sem);
792         path_release(&nd);
793  out:
794 @@ -1324,6 +1403,7 @@
795  {
796         int error = 0;
797         char * tmp;
798 +       struct lookup_intent it = { IT_MKDIR, mode };
799  
800         tmp = getname(pathname);
801         error = PTR_ERR(tmp);
802 @@ -1335,13 +1415,15 @@
803                         error = path_walk(tmp, &nd);
804                 if (error)
805                         goto out;
806 -               dentry = lookup_create(&nd, 1);
807 +               dentry = lookup_create(&nd, 1, &it);
808                 error = PTR_ERR(dentry);
809                 if (!IS_ERR(dentry)) {
810 +                       dentry->d_it = &it;
811                         error = vfs_mkdir(nd.dentry->d_inode, dentry,
812                                           mode & ~current->fs->umask);
813                         dput(dentry);
814                 }
815 +               intent_release(dentry); 
816                 up(&nd.dentry->d_inode->i_sem);
817                 path_release(&nd);
818  out:
819 @@ -1421,6 +1503,7 @@
820         char * name;
821         struct dentry *dentry;
822         struct nameidata nd;
823 +       struct lookup_intent it = { IT_RMDIR, 0 };
824  
825         name = getname(pathname);
826         if(IS_ERR(name))
827 @@ -1443,10 +1526,12 @@
828                         goto exit1;
829         }
830         down(&nd.dentry->d_inode->i_sem);
831 -       dentry = lookup_hash(&nd.last, nd.dentry);
832 +       dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
833         error = PTR_ERR(dentry);
834         if (!IS_ERR(dentry)) {
835 +               dentry->d_it = &it; 
836                 error = vfs_rmdir(nd.dentry->d_inode, dentry);
837 +               intent_release(dentry); 
838                 dput(dentry);
839         }
840         up(&nd.dentry->d_inode->i_sem);
841 @@ -1490,6 +1575,7 @@
842         char * name;
843         struct dentry *dentry;
844         struct nameidata nd;
845 +       struct lookup_intent it = { IT_UNLINK, 0 };
846  
847         name = getname(pathname);
848         if(IS_ERR(name))
849 @@ -1503,14 +1589,16 @@
850         if (nd.last_type != LAST_NORM)
851                 goto exit1;
852         down(&nd.dentry->d_inode->i_sem);
853 -       dentry = lookup_hash(&nd.last, nd.dentry);
854 +       dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
855         error = PTR_ERR(dentry);
856         if (!IS_ERR(dentry)) {
857 +               dentry->d_it = &it;
858                 /* Why not before? Because we want correct error value */
859                 if (nd.last.name[nd.last.len])
860                         goto slashes;
861                 error = vfs_unlink(nd.dentry->d_inode, dentry);
862         exit2:
863 +               intent_release(dentry); 
864                 dput(dentry);
865         }
866         up(&nd.dentry->d_inode->i_sem);
867 @@ -1557,6 +1645,7 @@
868         int error = 0;
869         char * from;
870         char * to;
871 +       struct lookup_intent it = { IT_SYMLINK, 0 };
872  
873         from = getname(oldname);
874         if(IS_ERR(from))
875 @@ -1571,12 +1660,14 @@
876                         error = path_walk(to, &nd);
877                 if (error)
878                         goto out;
879 -               dentry = lookup_create(&nd, 0);
880 +               dentry = lookup_create(&nd, 0, &it);
881                 error = PTR_ERR(dentry);
882                 if (!IS_ERR(dentry)) {
883 +                       dentry->d_it = &it;
884                         error = vfs_symlink(nd.dentry->d_inode, dentry, from);
885                         dput(dentry);
886                 }
887 +               intent_release(dentry); 
888                 up(&nd.dentry->d_inode->i_sem);
889                 path_release(&nd);
890  out:
891 @@ -1640,6 +1731,7 @@
892         int error;
893         char * from;
894         char * to;
895 +       struct lookup_intent it = { IT_LINK, 0 };
896  
897         from = getname(oldname);
898         if(IS_ERR(from))
899 @@ -1662,12 +1754,14 @@
900                 error = -EXDEV;
901                 if (old_nd.mnt != nd.mnt)
902                         goto out_release;
903 -               new_dentry = lookup_create(&nd, 0);
904 +               new_dentry = lookup_create(&nd, 0, &it);
905                 error = PTR_ERR(new_dentry);
906                 if (!IS_ERR(new_dentry)) {
907 +                       new_dentry->d_it = &it;
908                         error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
909                         dput(new_dentry);
910                 }
911 +               intent_release(new_dentry); 
912                 up(&nd.dentry->d_inode->i_sem);
913  out_release:
914                 path_release(&nd);
915 @@ -1708,7 +1802,8 @@
916   *        locking].
917   */
918  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
919 -              struct inode *new_dir, struct dentry *new_dentry)
920 +                  struct inode *new_dir, struct dentry *new_dentry,
921 +                  struct lookup_intent *it)
922  {
923         int error;
924         struct inode *target;
925 @@ -1762,12 +1857,14 @@
926         } else
927                 double_down(&old_dir->i_zombie,
928                             &new_dir->i_zombie);
929 +       new_dentry->d_it = it;
930         if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
931                 error = -ENOENT;
932         else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
933                 error = -EBUSY;
934         else 
935                 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
936 +       intent_release(new_dentry); 
937         if (target) {
938                 if (!error)
939                         target->i_flags |= S_DEAD;
940 @@ -1789,7 +1886,8 @@
941  }
942  
943  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
944 -              struct inode *new_dir, struct dentry *new_dentry)
945 +               struct inode *new_dir, struct dentry *new_dentry, 
946 +                    struct lookup_intent *it)
947  {
948         int error;
949  
950 @@ -1816,10 +1914,12 @@
951         DQUOT_INIT(old_dir);
952         DQUOT_INIT(new_dir);
953         double_down(&old_dir->i_zombie, &new_dir->i_zombie);
954 +       new_dentry->d_it = it;
955         if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
956                 error = -EBUSY;
957         else
958                 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
959 +       intent_release(new_dentry); 
960         double_up(&old_dir->i_zombie, &new_dir->i_zombie);
961         if (error)
962                 return error;
963 @@ -1831,13 +1931,14 @@
964  }
965  
966  int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
967 -              struct inode *new_dir, struct dentry *new_dentry)
968 +               struct inode *new_dir, struct dentry *new_dentry, 
969 +               struct lookup_intent *it)
970  {
971         int error;
972         if (S_ISDIR(old_dentry->d_inode->i_mode))
973 -               error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
974 +               error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry, it);
975         else
976 -               error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
977 +               error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry, it);
978         if (!error) {
979                 if (old_dir == new_dir)
980                         inode_dir_notify(old_dir, DN_RENAME);
981 @@ -1855,6 +1956,7 @@
982         struct dentry * old_dir, * new_dir;
983         struct dentry * old_dentry, *new_dentry;
984         struct nameidata oldnd, newnd;
985 +       struct lookup_intent it = {IT_RENAME, 0};
986  
987         if (path_init(oldname, LOOKUP_PARENT, &oldnd))
988                 error = path_walk(oldname, &oldnd);
989 @@ -1882,7 +1984,9 @@
990  
991         double_lock(new_dir, old_dir);
992  
993 -       old_dentry = lookup_hash(&oldnd.last, old_dir);
994 +       it.it_op = IT_RENAME;
995 +       it.it_mode = 0;
996 +       old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
997         error = PTR_ERR(old_dentry);
998         if (IS_ERR(old_dentry))
999                 goto exit3;
1000 @@ -1898,14 +2002,15 @@
1001                 if (newnd.last.name[newnd.last.len])
1002                         goto exit4;
1003         }
1004 -       new_dentry = lookup_hash(&newnd.last, new_dir);
1005 +       it.it_op = IT_RENAME2;
1006 +       new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
1007         error = PTR_ERR(new_dentry);
1008         if (IS_ERR(new_dentry))
1009                 goto exit4;
1010  
1011         lock_kernel();
1012         error = vfs_rename(old_dir->d_inode, old_dentry,
1013 -                                  new_dir->d_inode, new_dentry);
1014 +                                  new_dir->d_inode, new_dentry, &it);
1015         unlock_kernel();
1016  
1017         dput(new_dentry);
1018 --- kernel-rh-2.4.18-pristine/fs/open.c Thu Jun 13 12:27:08 2002
1019 +++ kernel-rh-2.4.18/fs/open.c  Thu Jun 13 14:54:40 2002
1020 @@ -19,6 +19,8 @@
1021  #include <asm/uaccess.h>
1022  
1023  #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
1024 +extern int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it);
1025 +extern void intent_release(struct dentry *de);
1026  
1027  int vfs_statfs(struct super_block *sb, struct statfs *buf)
1028  {
1029 @@ -94,14 +96,19 @@
1030         struct nameidata nd;
1031         struct inode * inode;
1032         int error;
1033 +       struct lookup_intent it;
1034 +       
1035 +       it.it_op = IT_SETATTR;
1036 +
1037  
1038         error = -EINVAL;
1039         if (length < 0) /* sorry, but loff_t says... */
1040                 goto out;
1041  
1042 -       error = user_path_walk(path, &nd);
1043 +       error = user_path_walk_it(path, &nd, &it);
1044         if (error)
1045                 goto out;
1046 +       nd.dentry->d_it = &it;
1047         inode = nd.dentry->d_inode;
1048  
1049         /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
1050 @@ -144,6 +151,7 @@
1051         put_write_access(inode);
1052  
1053  dput_and_out:
1054 +       intent_release(nd.dentry);
1055         path_release(&nd);
1056  out:
1057         return error;
1058 @@ -235,10 +243,14 @@
1059         struct nameidata nd;
1060         struct inode * inode;
1061         struct iattr newattrs;
1062 +       struct lookup_intent it;
1063 +
1064 +       it.it_op = IT_SETATTR;
1065  
1066 -       error = user_path_walk(filename, &nd);
1067 +       error = user_path_walk_it(filename, &nd, &it);
1068         if (error)
1069                 goto out;
1070 +       nd.dentry->d_it = &it;
1071         inode = nd.dentry->d_inode;
1072  
1073         error = -EROFS;
1074 @@ -262,6 +274,7 @@
1075         }
1076         error = notify_change(nd.dentry, &newattrs);
1077  dput_and_out:
1078 +       intent_release(nd.dentry);
1079         path_release(&nd);
1080  out:
1081         return error;
1082 @@ -279,11 +292,15 @@
1083         struct nameidata nd;
1084         struct inode * inode;
1085         struct iattr newattrs;
1086 +       struct lookup_intent it;
1087 +       
1088 +       it.it_op = IT_SETATTR;
1089  
1090 -       error = user_path_walk(filename, &nd);
1091 +       error = user_path_walk_it(filename, &nd, &it);
1092  
1093         if (error)
1094                 goto out;
1095 +       nd.dentry->d_it = &it;
1096         inode = nd.dentry->d_inode;
1097  
1098         error = -EROFS;
1099 @@ -306,6 +323,7 @@
1100         }
1101         error = notify_change(nd.dentry, &newattrs);
1102  dput_and_out:
1103 +       intent_release(nd.dentry);
1104         path_release(&nd);
1105  out:
1106         return error;
1107 @@ -322,6 +340,9 @@
1108         int old_fsuid, old_fsgid;
1109         kernel_cap_t old_cap;
1110         int res;
1111 +       struct lookup_intent it;
1112 +       
1113 +       it.it_op = IT_GETATTR;
1114  
1115         if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
1116                 return -EINVAL;
1117 @@ -339,7 +360,7 @@
1118         else
1119                 current->cap_effective = current->cap_permitted;
1120  
1121 -       res = user_path_walk(filename, &nd);
1122 +       res = user_path_walk_it(filename, &nd, &it);
1123         if (!res) {
1124                 res = permission(nd.dentry->d_inode, mode);
1125                 /* SuS v2 requires we report a read only fs too */
1126 @@ -361,6 +382,9 @@
1127         int error;
1128         struct nameidata nd;
1129         char *name;
1130 +       struct lookup_intent it;
1131 +       
1132 +       it.it_op = IT_GETATTR;
1133  
1134         name = getname(filename);
1135         error = PTR_ERR(name);
1136 @@ -369,11 +393,12 @@
1137  
1138         error = 0;
1139         if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd))
1140 -               error = path_walk(name, &nd);
1141 +               error = path_walk_it(name, &nd, &it);
1142         putname(name);
1143         if (error)
1144                 goto out;
1145  
1146 +       nd.dentry->d_it = &it;
1147         error = permission(nd.dentry->d_inode,MAY_EXEC);
1148         if (error)
1149                 goto dput_and_out;
1150 @@ -381,6 +406,7 @@
1151         set_fs_pwd(current->fs, nd.mnt, nd.dentry);
1152  
1153  dput_and_out:
1154 +       intent_release(nd.dentry);
1155         path_release(&nd);
1156  out:
1157         return error;
1158 @@ -421,6 +447,9 @@
1159         int error;
1160         struct nameidata nd;
1161         char *name;
1162 +       struct lookup_intent it;
1163
1164 +       it.it_op = IT_GETATTR;
1165  
1166         name = getname(filename);
1167         error = PTR_ERR(name);
1168 @@ -429,11 +458,12 @@
1169  
1170         path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
1171                       LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
1172 -       error = path_walk(name, &nd);   
1173 +       error = path_walk_it(name, &nd, &it);   
1174         putname(name);
1175         if (error)
1176                 goto out;
1177  
1178 +       nd.dentry->d_it = &it;
1179         error = permission(nd.dentry->d_inode,MAY_EXEC);
1180         if (error)
1181                 goto dput_and_out;
1182 @@ -446,6 +476,7 @@
1183         set_fs_altroot();
1184         error = 0;
1185  dput_and_out:
1186 +       intent_release(nd.dentry);
1187         path_release(&nd);
1188  out:
1189         return error;
1190 @@ -490,12 +521,15 @@
1191         struct inode * inode;
1192         int error;
1193         struct iattr newattrs;
1194 +       struct lookup_intent it;
1195  
1196 -       error = user_path_walk(filename, &nd);
1197 +       it.it_op = IT_SETATTR;
1198 +       error = user_path_walk_it(filename, &nd, &it);
1199         if (error)
1200                 goto out;
1201         inode = nd.dentry->d_inode;
1202  
1203 +       nd.dentry->d_it = &it;
1204         error = -EROFS;
1205         if (IS_RDONLY(inode))
1206                 goto dput_and_out;
1207 @@ -511,6 +545,7 @@
1208         error = notify_change(nd.dentry, &newattrs);
1209  
1210  dput_and_out:
1211 +       intent_release(nd.dentry);
1212         path_release(&nd);
1213  out:
1214         return error;
1215 @@ -580,10 +615,15 @@
1216  {
1217         struct nameidata nd;
1218         int error;
1219 +       struct lookup_intent it;
1220 +       
1221 +       it.it_op = IT_SETATTR;
1222  
1223 -       error = user_path_walk(filename, &nd);
1224 +       error = user_path_walk_it(filename, &nd, &it);
1225         if (!error) {
1226 +               nd.dentry->d_it = &it;
1227                 error = chown_common(nd.dentry, user, group);
1228 +               intent_release(nd.dentry);
1229                 path_release(&nd);
1230         }
1231         return error;
1232 @@ -593,10 +633,15 @@
1233  {
1234         struct nameidata nd;
1235         int error;
1236 +       struct lookup_intent it;
1237  
1238 -       error = user_path_walk_link(filename, &nd);
1239 +       it.it_op = IT_SETATTR;
1240 +
1241 +       error = user_path_walk_link_it(filename, &nd, &it);
1242         if (!error) {
1243 +               nd.dentry->d_it = &it;
1244                 error = chown_common(nd.dentry, user, group);
1245 +               intent_release(nd.dentry);
1246                 path_release(&nd);
1247         }
1248         return error;
1249 @@ -630,10 +675,15 @@
1250   * for the internal routines (ie open_namei()/follow_link() etc). 00 is
1251   * used by symlinks.
1252   */
1253 +extern int open_namei_it(const char *filename, int namei_flags, int mode, 
1254 +                        struct nameidata *nd, struct lookup_intent *it);
1255 +struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, int flags, struct lookup_intent *it);
1256 +
1257  struct file *filp_open(const char * filename, int flags, int mode)
1258  {
1259         int namei_flags, error;
1260         struct nameidata nd;
1261 +       struct lookup_intent it = {IT_OPEN, 0};
1262  
1263         namei_flags = flags;
1264         if ((namei_flags+1) & O_ACCMODE)
1265 @@ -641,14 +691,14 @@
1266         if (namei_flags & O_TRUNC)
1267                 namei_flags |= 2;
1268  
1269 -       error = open_namei(filename, namei_flags, mode, &nd);
1270 +       error = open_namei_it(filename, namei_flags, mode, &nd, &it);
1271         if (!error)
1272 -               return dentry_open(nd.dentry, nd.mnt, flags);
1273 +               return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
1274  
1275         return ERR_PTR(error);
1276  }
1277  
1278 -struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
1279 +struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, int flags, struct lookup_intent *it)
1280  {
1281         struct file * f;
1282         struct inode *inode;
1283 @@ -690,6 +740,7 @@
1284                         goto cleanup_all;
1285         }
1286         f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
1287 +       f->f_intent = it;
1288  
1289         return f;
1290  
1291 @@ -710,6 +761,13 @@
1292         return ERR_PTR(error);
1293  }
1294  
1295 +struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
1296 +{
1297 +       return dentry_open_it(dentry, mnt, flags, NULL);
1298 +
1299 +}
1300 +
1301 +
1302  /*
1303   * Find an empty file descriptor entry, and mark it busy.
1304   */
1305 --- kernel-rh-2.4.18-pristine/fs/stat.c Thu Jun 13 12:27:08 2002
1306 +++ kernel-rh-2.4.18/fs/stat.c  Thu Jun 13 15:12:21 2002
1307 @@ -117,8 +117,11 @@
1308  {
1309         struct nameidata nd;
1310         int error;
1311 +       struct lookup_intent it;
1312 +       it.it_op = IT_GETATTR;
1313  
1314 -       error = user_path_walk_link(name, &nd);
1315 +
1316 +       error = user_path_walk_link_it(name, &nd, &it);
1317         if (!error) {
1318                 error = do_getattr(nd.mnt, nd.dentry, stat);
1319                 path_release(&nd);
1320 @@ -269,14 +272,16 @@
1321  {
1322         struct nameidata nd;
1323         int error;
1324 +       struct lookup_intent it;
1325 +       it.it_op = IT_READLINK;
1326  
1327         if (bufsiz <= 0)
1328                 return -EINVAL;
1329  
1330 -       error = user_path_walk_link(path, &nd);
1331 +       error = user_path_walk_link_it(path, &nd, &it);
1332         if (!error) {
1333                 struct inode * inode = nd.dentry->d_inode;
1334 -
1335 +               nd.dentry->d_it = &it;
1336                 error = -EINVAL;
1337                 if (inode->i_op && inode->i_op->readlink &&
1338                     !(error = do_revalidate(nd.dentry))) {
1339 --- kernel-rh-2.4.18/fs/nfsd/vfs.c.orig-lustre  Thu Jun 13 15:28:25 2002
1340 +++ kernel-rh-2.4.18/fs/nfsd/vfs.c      Thu Jun 13 15:28:40 2002
1341 @@ -1285,7 +1285,7 @@
1342                         err = nfserr_perm;
1343         } else
1344  #endif
1345 -       err = vfs_rename(fdir, odentry, tdir, ndentry);
1346 +       err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
1347         if (!err && EX_ISSYNC(tfhp->fh_export)) {
1348                 nfsd_sync_dir(tdentry);
1349                 nfsd_sync_dir(fdentry);