Whamcloud - gitweb
Distribute obdfs, put modules in /lib/modules//kernel/fs/lustre.
[fs/lustre-release.git] / lustre / patches / patch-2.4.18-chaos11
1 --- linux-2.4.18-chaos5-pristine/drivers/block/blkpg.c  Sat Jun 29 23:07:36 2002
2 +++ linux-2.4.18-chaos5/drivers/block/blkpg.c   Sat Jun 29 23:09:04 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 --- linux-2.4.18-chaos5-pristine/drivers/block/loop.c   Sat Jun 29 23:07:36 2002
43 +++ linux-2.4.18-chaos5/drivers/block/loop.c    Sat Jun 29 23:09:04 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 --- linux-2.4.18-chaos5-pristine/drivers/ide/ide-disk.c Sat Jun 29 23:07:36 2002
57 +++ linux-2.4.18-chaos5/drivers/ide/ide-disk.c  Sat Jun 29 23:09:04 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 --- linux-2.4.18-chaos5-pristine/fs/ext3/Makefile       Sat Jun 29 23:07:56 2002
72 +++ linux-2.4.18-chaos5/fs/ext3/Makefile        Sat Jun 29 23:09:04 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 --- linux-2.4.18-chaos5-pristine/fs/ext3/super.c        Sat Jun 29 23:07:56 2002
83 +++ linux-2.4.18-chaos5/fs/ext3/super.c Sat Jun 29 23:09:04 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 --- linux-2.4.18-chaos5-pristine/fs/jbd/commit.c        Sat Jun 29 23:07:56 2002
94 +++ linux-2.4.18-chaos5/fs/jbd/commit.c Sat Jun 29 23:09:04 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 --- linux-2.4.18-chaos5-pristine/fs/jbd/journal.c       Sat Jun 29 23:07:56 2002
163 +++ linux-2.4.18-chaos5/fs/jbd/journal.c        Sat Jun 29 23:09:04 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 --- linux-2.4.18-chaos5-pristine/fs/jbd/transaction.c   Sat Jun 29 23:07:56 2002
173 +++ linux-2.4.18-chaos5/fs/jbd/transaction.c    Sat Jun 29 23:09:04 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 --- linux-2.4.18-chaos5-pristine/include/linux/blkdev.h Sat Jun 29 23:07:57 2002
280 +++ linux-2.4.18-chaos5/include/linux/blkdev.h  Mon Jul  1 08:51:17 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 --- linux-2.4.18-chaos5-pristine/include/linux/jbd.h    Sat Jun 29 23:07:57 2002
292 +++ linux-2.4.18-chaos5/include/linux/jbd.h     Mon Jul  1 08:51:19 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 --- linux-2.4.18-chaos5-pristine/kernel/ksyms.c Sat Jun 29 23:07:57 2002
341 +++ linux-2.4.18-chaos5/kernel/ksyms.c  Sat Jun 29 23:09:04 2002
342 @@ -306,6 +306,13 @@
343  EXPORT_SYMBOL(lock_may_write);
344  EXPORT_SYMBOL(dcache_readdir);
345  
346 +/* lustre */
347 +EXPORT_SYMBOL(panic_notifier_list);
348 +EXPORT_SYMBOL(pagecache_lock_cacheline);
349 +EXPORT_SYMBOL(kmem_cache_validate);
350 +EXPORT_SYMBOL(do_kern_mount);
351 +
352 +
353  /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
354  EXPORT_SYMBOL(default_llseek);
355  EXPORT_SYMBOL(dentry_open);
356 --- linux-2.4.18-chaos5-pristine/include/linux/dcache.h Sat Jun 29 23:07:57 2002
357 +++ linux-2.4.18-chaos5/include/linux/dcache.h  Mon Jul  1 08:51:12 2002
358 @@ -6,6 +6,33 @@
359  #include <asm/atomic.h>
360  #include <linux/mount.h>
361  
362 +#define IT_OPEN  (1)
363 +#define IT_CREAT  (1<<1)
364 +#define IT_MKDIR  (1<<2)
365 +#define IT_LINK  (1<<3)
366 +#define IT_SYMLINK  (1<<4)
367 +#define IT_UNLINK  (1<<5)
368 +#define IT_RMDIR  (1<<6)
369 +#define IT_RENAME  (1<<7)
370 +#define IT_RENAME2  (1<<8)
371 +#define IT_READDIR  (1<<9)
372 +#define IT_GETATTR  (1<<10)
373 +#define IT_SETATTR  (1<<11)
374 +#define IT_READLINK  (1<<12)
375 +#define IT_MKNOD  (1<<13)
376 +#define IT_LOOKUP  (1<<14)
377 +
378 +struct lookup_intent { 
379 +       int it_op;
380 +       int it_mode;
381 +       int it_disposition;
382 +       int it_status; 
383 +       struct iattr *it_iattr;
384 +       __u64 it_lock_handle[2];
385 +       int it_lock_mode;
386 +       void *it_data;
387 +};
388 +
389  /*
390   * linux/include/linux/dcache.h
391   *
392 @@ -78,6 +105,7 @@
393         unsigned long d_time;           /* used by d_revalidate */
394         struct dentry_operations  *d_op;
395         struct super_block * d_sb;      /* The root of the dentry tree */
396 +       struct lookup_intent *d_it;
397         unsigned long d_vfs_flags;
398         void * d_fsdata;                /* fs-specific data */
399         void * d_extra_attributes;      /* TUX-specific data */
400 @@ -91,6 +119,8 @@
401         int (*d_delete)(struct dentry *);
402         void (*d_release)(struct dentry *);
403         void (*d_iput)(struct dentry *, struct inode *);
404 +       int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
405 +       void (*d_intent_release)(struct dentry *);
406  };
407  
408  /* the dentry parameter passed to d_hash and d_compare is the parent
409 --- linux-2.4.18-chaos5-pristine/include/linux/fs.h     Sat Jun 29 23:07:57 2002
410 +++ linux-2.4.18-chaos5/include/linux/fs.h      Mon Jul  1 08:51:12 2002
411 @@ -572,6 +572,7 @@
412  
413         /* needed for tty driver, and maybe others */
414         void                    *private_data;
415 +        struct lookup_intent    *f_intent;
416  
417         /* preallocated helper kiobuf to speedup O_DIRECT */
418         struct kiobuf           *f_iobuf;
419 @@ -829,7 +830,9 @@
420  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
421  extern int vfs_rmdir(struct inode *, struct dentry *);
422  extern int vfs_unlink(struct inode *, struct dentry *);
423 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
424 +int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
425 +               struct inode *new_dir, struct dentry *new_dentry, 
426 +               struct lookup_intent *it);
427  
428  /*
429   * File types
430 @@ -890,6 +893,7 @@
431  struct inode_operations {
432         int (*create) (struct inode *,struct dentry *,int);
433         struct dentry * (*lookup) (struct inode *,struct dentry *);
434 +        struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
435         int (*link) (struct dentry *,struct inode *,struct dentry *);
436         int (*unlink) (struct inode *,struct dentry *);
437         int (*symlink) (struct inode *,struct dentry *,const char *);
438 @@ -1036,6 +1040,7 @@
439  extern struct vfsmount *kern_mount(struct file_system_type *);
440  extern int may_umount(struct vfsmount *);
441  extern long do_mount(char *, char *, char *, unsigned long, void *);
442 +struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
443  extern void umount_tree(struct vfsmount *);
444  
445  #define kern_umount mntput
446 @@ -1370,6 +1375,7 @@
447  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
448  
449  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
450 +extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
451  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
452  extern int FASTCALL(path_walk(const char *, struct nameidata *));
453  extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
454 @@ -1381,6 +1387,8 @@
455  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
456  #define user_path_walk(name,nd)         __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
457  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
458 +#define user_path_walk_it(name,nd,it)  __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
459 +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
460  
461  extern void iput(struct inode *);
462  extern void force_delete(struct inode *);
463 --- linux-2.4.18-chaos5-pristine/fs/nfsd/vfs.c  Sat Jun 29 23:07:56 2002
464 +++ linux-2.4.18-chaos5/fs/nfsd/vfs.c   Sat Jun 29 23:09:04 2002
465 @@ -1298,7 +1298,7 @@
466                         err = nfserr_perm;
467         } else
468  #endif
469 -       err = vfs_rename(fdir, odentry, tdir, ndentry);
470 +       err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
471         unlock_kernel();
472         if (!err && EX_ISSYNC(tfhp->fh_export)) {
473                 nfsd_sync_dir(tdentry);
474 --- linux-2.4.18-chaos5-pristine/fs/namei.c     Sat Jun 29 23:07:56 2002
475 +++ linux-2.4.18-chaos5/fs/namei.c      Tue Jul  2 16:06:05 2002
476 @@ -94,6 +94,14 @@
477   * XEmacs seems to be relying on it...
478   */
479  
480 +void intent_release(struct dentry *de) 
481 +{
482 +       if (de->d_op && de->d_op->d_intent_release)
483 +               de->d_op->d_intent_release(de);
484 +       de->d_it = NULL;
485 +}
486 +
487 +
488  /* In order to reduce some races, while at the same time doing additional
489   * checking and hopefully speeding things up, we copy filenames to the
490   * kernel data space before using them..
491 @@ -260,10 +268,19 @@
492   * Internal lookup() using the new generic dcache.
493   * SMP-safe
494   */
495 -static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
496 +static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
497 +                                   int flags, struct lookup_intent *it)
498  {
499         struct dentry * dentry = d_lookup(parent, name);
500  
501 +       if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
502 +               if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
503 +                   !d_invalidate(dentry)) {
504 +                       dput(dentry);
505 +                       dentry = NULL;
506 +               }
507 +               return dentry; 
508 +       } else
509         if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
510                 if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
511                         dput(dentry);
512 @@ -281,7 +297,8 @@
513   * make sure that nobody added the entry to the dcache in the meantime..
514   * SMP-safe
515   */
516 -static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
517 +static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
518 +                                 int flags, struct lookup_intent *it)
519  {
520         struct dentry * result;
521         struct inode *dir = parent->d_inode;
522 @@ -300,6 +316,9 @@
523                 result = ERR_PTR(-ENOMEM);
524                 if (dentry) {
525                         lock_kernel();
526 +                       if (dir->i_op->lookup2) 
527 +                               result = dir->i_op->lookup2(dir, dentry, it);
528 +                       else 
529                         result = dir->i_op->lookup(dir, dentry);
530                         unlock_kernel();
531                         if (result)
532 @@ -322,6 +341,13 @@
533                         result = ERR_PTR(-ENOENT);
534                 }
535         }
536 +       else if (result->d_op && result->d_op->d_revalidate2) {
537 +               if (!result->d_op->d_revalidate2(result, flags, it) &&
538 +                   !d_invalidate(result)) {
539 +                       dput(result);
540 +                       result = ERR_PTR(-ENOENT);
541 +               }
542 +       }
543         return result;
544  }
545  
546 @@ -447,7 +472,8 @@
547   *
548   * We expect 'base' to be positive and a directory.
549   */
550 -int link_path_walk(const char * name, struct nameidata *nd)
551 +int link_path_walk_it(const char *name, struct nameidata *nd,
552 +                     struct lookup_intent *it)
553  {
554         struct dentry *dentry;
555         struct inode *inode;
556 @@ -524,12 +549,12 @@
557                                 break;
558                 }
559                 /* This does the actual lookups.. */
560 -               dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
561 +               dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, it);
562                 if (!dentry) {
563                         err = -EWOULDBLOCKIO;
564                         if (atomic)
565                                 break;
566 -                       dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
567 +                       dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, it);
568                         err = PTR_ERR(dentry);
569                         if (IS_ERR(dentry))
570                                 break;
571 @@ -563,7 +588,7 @@
572                         nd->dentry = dentry;
573                 }
574                 err = -ENOTDIR; 
575 -               if (!inode->i_op->lookup)
576 +               if (!inode->i_op->lookup && !inode->i_op->lookup2)
577                         break;
578                 continue;
579                 /* here ends the main loop */
580 @@ -590,12 +615,12 @@
581                         if (err < 0)
582                                 break;
583                 }
584 -               dentry = cached_lookup(nd->dentry, &this, 0);
585 +               dentry = cached_lookup(nd->dentry, &this, 0, it);
586                 if (!dentry) {
587                         err = -EWOULDBLOCKIO;
588                         if (atomic)
589                                 break;
590 -                       dentry = real_lookup(nd->dentry, &this, 0);
591 +                       dentry = real_lookup(nd->dentry, &this, 0, it);
592                         err = PTR_ERR(dentry);
593                         if (IS_ERR(dentry))
594                                 break;
595 @@ -619,7 +644,8 @@
596                         goto no_inode;
597                 if (lookup_flags & LOOKUP_DIRECTORY) {
598                         err = -ENOTDIR; 
599 -                       if (!inode->i_op || !inode->i_op->lookup)
600 +                       if (!inode->i_op || (!inode->i_op->lookup && 
601 +                                            !inode->i_op->lookup2))
602                                 break;
603                 }
604                 goto return_base;
605 @@ -651,6 +677,7 @@
606                         }
607                 }
608  return_base:
609 +               nd->dentry->d_it = it;
610                 return 0;
611  out_dput:
612                 dput(dentry);
613 @@ -658,15 +685,29 @@
614         }
615         path_release(nd);
616  return_err:
617 +       if (!err)
618 +               nd->dentry->d_it = it;
619         return err;
620  }
621  
622 +int link_path_walk(const char * name, struct nameidata *nd)
623 +{
624 +       return link_path_walk_it(name, nd, NULL);
625 +}
626 +
627 +int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
628 +{
629 +       current->total_link_count = 0;
630 +       return link_path_walk_it(name, nd, it);
631 +}
632 +
633  int path_walk(const char * name, struct nameidata *nd)
634  {
635         current->total_link_count = 0;
636 -       return link_path_walk(name, nd);
637 +       return link_path_walk_it(name, nd, NULL);
638  }
639  
640 +
641  /* SMP-safe */
642  /* returns 1 if everything is done */
643  static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
644 @@ -749,6 +790,17 @@
645  }
646  
647  /* SMP-safe */
648 +int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, 
649 +                  struct lookup_intent *it)
650 +{
651 +       int error = 0;
652 +       if (path_init(path, flags, nd))
653 +               error = path_walk_it(path, nd, it);
654 +       return error;
655 +}
656 +
657 +
658 +/* SMP-safe */
659  int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
660  {
661         int error = 0;
662 @@ -777,7 +829,8 @@
663   * needs parent already locked. Doesn't follow mounts.
664   * SMP-safe.
665   */
666 -struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
667 +struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, 
668 +                              struct lookup_intent *it)
669  {
670         struct dentry * dentry;
671         struct inode *inode;
672 @@ -800,13 +853,16 @@
673                         goto out;
674         }
675  
676 -       dentry = cached_lookup(base, name, 0);
677 +       dentry = cached_lookup(base, name, 0, it);
678         if (!dentry) {
679                 struct dentry *new = d_alloc(base, name);
680                 dentry = ERR_PTR(-ENOMEM);
681                 if (!new)
682                         goto out;
683                 lock_kernel();
684 +               if (inode->i_op->lookup2) 
685 +                       dentry = inode->i_op->lookup2(inode, new, it);
686 +               else 
687                 dentry = inode->i_op->lookup(inode, new);
688                 unlock_kernel();
689                 if (!dentry)
690 @@ -818,6 +874,12 @@
691         return dentry;
692  }
693  
694 +struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
695 +{
696 +       return lookup_hash_it(name, base, NULL);
697 +}
698 +
699 +
700  /* SMP-safe */
701  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
702  {
703 @@ -839,7 +901,7 @@
704         }
705         this.hash = end_name_hash(hash);
706  
707 -       return lookup_hash(&this, base);
708 +       return lookup_hash_it(&this, base, NULL);
709  access:
710         return ERR_PTR(-EACCES);
711  }
712 @@ -870,6 +932,23 @@
713         return err;
714  }
715  
716 +int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
717 +                  struct lookup_intent *it)
718 +{
719 +       char *tmp;
720 +       int err;
721 +
722 +       tmp = getname(name);
723 +       err = PTR_ERR(tmp);
724 +       if (!IS_ERR(tmp)) {
725 +               err = 0;
726 +               if (path_init(tmp, flags, nd))
727 +                       err = path_walk_it(tmp, nd, it);
728 +               putname(tmp);
729 +       }
730 +       return err;
731 +}
732 +
733  /*
734   * It's inline, so penalty for filesystems that don't use sticky bit is
735   * minimal.
736 @@ -1008,7 +1086,8 @@
737   * for symlinks (where the permissions are checked later).
738   * SMP-safe
739   */
740 -int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
741 +int open_namei_it(const char *pathname, int flag, int mode,
742 +                 struct nameidata *nd, struct lookup_intent *it)
743  {
744         int acc_mode, error = 0;
745         struct inode *inode;
746 @@ -1022,16 +1101,19 @@
747          * The simplest case - just a plain lookup.
748          */
749         if (!(flag & O_CREAT)) {
750 -               error = path_lookup(pathname, lookup_flags(flag), nd);
751 +               error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
752                 if (error)
753                         return error;
754                 dentry = nd->dentry;
755 +               dentry->d_it = it;
756                 goto ok;
757         }
758  
759         /*
760          * Create - we need to know the parent.
761          */
762 +       if (it) 
763 +               it->it_op |= IT_CREAT;
764         error = path_lookup(pathname, LOOKUP_PARENT, nd);
765         if (error)
766                 return error;
767 @@ -1047,7 +1129,7 @@
768  
769         dir = nd->dentry;
770         down(&dir->d_inode->i_sem);
771 -       dentry = lookup_hash(&nd->last, nd->dentry);
772 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
773  
774  do_last:
775         error = PTR_ERR(dentry);
776 @@ -1056,6 +1138,7 @@
777                 goto exit;
778         }
779  
780 +       dentry->d_it = it;
781         /* Negative dentry, just create the file */
782         if (!dentry->d_inode) {
783                 error = vfs_create(dir->d_inode, dentry,
784 @@ -1172,9 +1255,11 @@
785                 if (flag & FMODE_WRITE)
786                         DQUOT_INIT(inode);
787  
788 +       intent_release(dentry);
789         return 0;
790  
791  exit_dput:
792 +       intent_release(dentry);
793         dput(dentry);
794  exit:
795         path_release(nd);
796 @@ -1217,13 +1302,20 @@
797         }
798         dir = nd->dentry;
799         down(&dir->d_inode->i_sem);
800 -       dentry = lookup_hash(&nd->last, nd->dentry);
801 +       dentry = lookup_hash_it(&nd->last, nd->dentry, NULL);
802         putname(nd->last.name);
803         goto do_last;
804  }
805  
806 +int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
807 +{
808 +       return open_namei_it(pathname, flag, mode, nd, NULL); 
809 +}
810 +
811 +
812  /* SMP-safe */
813 -static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
814 +static struct dentry *lookup_create(struct nameidata *nd, int is_dir, 
815 +                                   struct lookup_intent *it)
816  {
817         struct dentry *dentry;
818  
819 @@ -1231,7 +1323,7 @@
820         dentry = ERR_PTR(-EEXIST);
821         if (nd->last_type != LAST_NORM)
822                 goto fail;
823 -       dentry = lookup_hash(&nd->last, nd->dentry);
824 +       dentry = lookup_hash_it(&nd->last, nd->dentry, it);
825         if (IS_ERR(dentry))
826                 goto fail;
827         if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
828 @@ -1277,6 +1369,7 @@
829         char * tmp;
830         struct dentry * dentry;
831         struct nameidata nd;
832 +       struct lookup_intent it = { IT_MKNOD , mode };
833  
834         if (S_ISDIR(mode))
835                 return -EPERM;
836 @@ -1287,11 +1380,12 @@
837         error = path_lookup(tmp, LOOKUP_PARENT, &nd);
838         if (error)
839                 goto out;
840 -       dentry = lookup_create(&nd, 0);
841 +       dentry = lookup_create(&nd, 0, &it);
842         error = PTR_ERR(dentry);
843  
844         mode &= ~current->fs->umask;
845         if (!IS_ERR(dentry)) {
846 +               dentry->d_it = &it;
847                 switch (mode & S_IFMT) {
848                 case 0: case S_IFREG:
849                         error = vfs_create(nd.dentry->d_inode,dentry,mode);
850 @@ -1305,6 +1399,7 @@
851                 default:
852                         error = -EINVAL;
853                 }
854 +               intent_release(dentry); 
855                 dput(dentry);
856         }
857         up(&nd.dentry->d_inode->i_sem);
858 @@ -1345,6 +1440,7 @@
859  {
860         int error = 0;
861         char * tmp;
862 +       struct lookup_intent it = { IT_MKDIR, mode };
863  
864         tmp = getname(pathname);
865         error = PTR_ERR(tmp);
866 @@ -1355,11 +1451,13 @@
867                 error = path_lookup(tmp, LOOKUP_PARENT, &nd);
868                 if (error)
869                         goto out;
870 -               dentry = lookup_create(&nd, 1);
871 +               dentry = lookup_create(&nd, 1, &it);
872                 error = PTR_ERR(dentry);
873                 if (!IS_ERR(dentry)) {
874 +                       dentry->d_it = &it;
875                         error = vfs_mkdir(nd.dentry->d_inode, dentry,
876                                           mode & ~current->fs->umask);
877 +                       intent_release(dentry); 
878                         dput(dentry);
879                 }
880                 up(&nd.dentry->d_inode->i_sem);
881 @@ -1439,6 +1537,7 @@
882         char * name;
883         struct dentry *dentry;
884         struct nameidata nd;
885 +       struct lookup_intent it = { IT_RMDIR, 0 };
886  
887         name = getname(pathname);
888         if(IS_ERR(name))
889 @@ -1460,10 +1559,12 @@
890                         goto exit1;
891         }
892         down(&nd.dentry->d_inode->i_sem);
893 -       dentry = lookup_hash(&nd.last, nd.dentry);
894 +       dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
895         error = PTR_ERR(dentry);
896         if (!IS_ERR(dentry)) {
897 +               dentry->d_it = &it; 
898                 error = vfs_rmdir(nd.dentry->d_inode, dentry);
899 +               intent_release(dentry); 
900                 dput(dentry);
901         }
902         up(&nd.dentry->d_inode->i_sem);
903 @@ -1507,6 +1608,7 @@
904         char * name;
905         struct dentry *dentry;
906         struct nameidata nd;
907 +       struct lookup_intent it = { IT_UNLINK, 0 };
908  
909         name = getname(pathname);
910         if(IS_ERR(name))
911 @@ -1519,14 +1621,16 @@
912         if (nd.last_type != LAST_NORM)
913                 goto exit1;
914         down(&nd.dentry->d_inode->i_sem);
915 -       dentry = lookup_hash(&nd.last, nd.dentry);
916 +       dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
917         error = PTR_ERR(dentry);
918         if (!IS_ERR(dentry)) {
919 +               dentry->d_it = &it;
920                 /* Why not before? Because we want correct error value */
921                 if (nd.last.name[nd.last.len])
922                         goto slashes;
923                 error = vfs_unlink(nd.dentry->d_inode, dentry);
924         exit2:
925 +               intent_release(dentry); 
926                 dput(dentry);
927         }
928         up(&nd.dentry->d_inode->i_sem);
929 @@ -1573,6 +1677,7 @@
930         int error = 0;
931         char * from;
932         char * to;
933 +       struct lookup_intent it = { IT_SYMLINK, 0 };
934  
935         from = getname(oldname);
936         if(IS_ERR(from))
937 @@ -1586,11 +1691,13 @@
938                 error = path_lookup(to, LOOKUP_PARENT, &nd);
939                 if (error)
940                         goto out;
941 -               dentry = lookup_create(&nd, 0);
942 +               dentry = lookup_create(&nd, 0, &it);
943                 error = PTR_ERR(dentry);
944                 if (!IS_ERR(dentry)) {
945 +                       dentry->d_it = &it;
946                         error = vfs_symlink(nd.dentry->d_inode, dentry, from);
947 -                       dput(dentry);
948 +                       intent_release(dentry); 
949 +                       dput(dentry);
950                 }
951                 up(&nd.dentry->d_inode->i_sem);
952                 path_release(&nd);
953 @@ -1654,6 +1761,7 @@
954  {
955         int error;
956         char * to;
957 +       struct lookup_intent it = { IT_LINK, 0 };
958  
959         to = getname(newname);
960         error = PTR_ERR(to);
961 @@ -1670,10 +1778,12 @@
962                 error = -EXDEV;
963                 if (old_nd.mnt != nd.mnt)
964                         goto out_release;
965 -               new_dentry = lookup_create(&nd, 0);
966 +               new_dentry = lookup_create(&nd, 0, &it);
967                 error = PTR_ERR(new_dentry);
968                 if (!IS_ERR(new_dentry)) {
969 +                       new_dentry->d_it = &it;
970                         error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
971 +                       intent_release(new_dentry);
972                         dput(new_dentry);
973                 }
974                 up(&nd.dentry->d_inode->i_sem);
975 @@ -1714,7 +1824,8 @@
976   *        locking].
977   */
978  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
979 -              struct inode *new_dir, struct dentry *new_dentry)
980 +              struct inode *new_dir, struct dentry *new_dentry,
981 +              struct lookup_intent *it)
982  {
983         int error;
984         struct inode *target;
985 @@ -1768,10 +1879,12 @@
986         } else
987                 double_down(&old_dir->i_zombie,
988                             &new_dir->i_zombie);
989 +       new_dentry->d_it = it;
990         if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
991                 error = -EBUSY;
992         else 
993                 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
994 +       intent_release(new_dentry);
995         if (target) {
996                 if (!error)
997                         target->i_flags |= S_DEAD;
998 @@ -1793,7 +1906,8 @@
999  }
1000  
1001  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
1002 -              struct inode *new_dir, struct dentry *new_dentry)
1003 +              struct inode *new_dir, struct dentry *new_dentry,
1004 +              struct lookup_intent *it)
1005  {
1006         int error;
1007  
1008 @@ -1820,10 +1934,12 @@
1009         DQUOT_INIT(old_dir);
1010         DQUOT_INIT(new_dir);
1011         double_down(&old_dir->i_zombie, &new_dir->i_zombie);
1012 +       new_dentry->d_it = it;
1013         if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
1014                 error = -EBUSY;
1015         else
1016                 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
1017 +       intent_release(new_dentry);
1018         double_up(&old_dir->i_zombie, &new_dir->i_zombie);
1019         if (error)
1020                 return error;
1021 @@ -1835,13 +1951,14 @@
1022  }
1023  
1024  int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1025 -              struct inode *new_dir, struct dentry *new_dentry)
1026 +              struct inode *new_dir, struct dentry *new_dentry,
1027 +              struct lookup_intent *it)
1028  {
1029         int error;
1030         if (S_ISDIR(old_dentry->d_inode->i_mode))
1031 -               error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
1032 +               error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
1033         else
1034 -               error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
1035 +               error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
1036         if (!error) {
1037                 if (old_dir == new_dir)
1038                         inode_dir_notify(old_dir, DN_RENAME);
1039 @@ -1858,6 +1975,7 @@
1040         int error = 0;
1041         struct dentry * old_dir, * new_dir;
1042         struct dentry * old_dentry, *new_dentry;
1043 +       struct lookup_intent it = {IT_RENAME, 0};
1044         struct nameidata oldnd, newnd;
1045  
1046         error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
1047 @@ -1883,7 +2001,7 @@
1048  
1049         double_lock(new_dir, old_dir);
1050  
1051 -       old_dentry = lookup_hash(&oldnd.last, old_dir);
1052 +       old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
1053         error = PTR_ERR(old_dentry);
1054         if (IS_ERR(old_dentry))
1055                 goto exit3;
1056 @@ -1899,14 +2019,15 @@
1057                 if (newnd.last.name[newnd.last.len])
1058                         goto exit4;
1059         }
1060 -       new_dentry = lookup_hash(&newnd.last, new_dir);
1061 +       it.it_op = IT_RENAME2;
1062 +       new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
1063         error = PTR_ERR(new_dentry);
1064         if (IS_ERR(new_dentry))
1065                 goto exit4;
1066  
1067         lock_kernel();
1068         error = vfs_rename(old_dir->d_inode, old_dentry,
1069 -                                  new_dir->d_inode, new_dentry);
1070 +                                  new_dir->d_inode, new_dentry, &it);
1071         unlock_kernel();
1072  
1073         dput(new_dentry);
1074 --- linux-2.4.18-chaos5-pristine/fs/open.c      Sat Jun 29 23:07:56 2002
1075 +++ linux-2.4.18-chaos5/fs/open.c       Sat Jun 29 23:09:04 2002
1076 @@ -19,6 +19,8 @@
1077  #include <asm/uaccess.h>
1078  
1079  #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
1080 +extern int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it);
1081 +extern void intent_release(struct dentry *de);
1082  
1083  int vfs_statfs(struct super_block *sb, struct statfs *buf)
1084  {
1085 @@ -118,14 +120,19 @@
1086         struct nameidata nd;
1087         struct inode * inode;
1088         int error;
1089 +       struct lookup_intent it;
1090 +       
1091 +       it.it_op = IT_SETATTR;
1092 +
1093  
1094         error = -EINVAL;
1095         if (length < 0) /* sorry, but loff_t says... */
1096                 goto out;
1097  
1098 -       error = user_path_walk(path, &nd);
1099 +       error = user_path_walk_it(path, &nd, &it);
1100         if (error)
1101                 goto out;
1102 +       nd.dentry->d_it = &it;
1103         inode = nd.dentry->d_inode;
1104  
1105         /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
1106 @@ -168,6 +175,7 @@
1107         put_write_access(inode);
1108  
1109  dput_and_out:
1110 +       intent_release(nd.dentry);
1111         path_release(&nd);
1112  out:
1113         return error;
1114 @@ -259,10 +267,14 @@
1115         struct nameidata nd;
1116         struct inode * inode;
1117         struct iattr newattrs;
1118 +       struct lookup_intent it;
1119  
1120 -       error = user_path_walk(filename, &nd);
1121 +       it.it_op = IT_SETATTR;
1122 +
1123 +       error = user_path_walk_it(filename, &nd, &it);
1124         if (error)
1125                 goto out;
1126 +       nd.dentry->d_it = &it;
1127         inode = nd.dentry->d_inode;
1128  
1129         error = -EROFS;
1130 @@ -286,6 +298,7 @@
1131         }
1132         error = notify_change(nd.dentry, &newattrs);
1133  dput_and_out:
1134 +       intent_release(nd.dentry);
1135         path_release(&nd);
1136  out:
1137         return error;
1138 @@ -303,11 +316,15 @@
1139         struct nameidata nd;
1140         struct inode * inode;
1141         struct iattr newattrs;
1142 +       struct lookup_intent it;
1143 +       
1144 +       it.it_op = IT_SETATTR;
1145  
1146 -       error = user_path_walk(filename, &nd);
1147 +       error = user_path_walk_it(filename, &nd, &it);
1148  
1149         if (error)
1150                 goto out;
1151 +       nd.dentry->d_it = &it;
1152         inode = nd.dentry->d_inode;
1153  
1154         error = -EROFS;
1155 @@ -330,6 +347,7 @@
1156         }
1157         error = notify_change(nd.dentry, &newattrs);
1158  dput_and_out:
1159 +       intent_release(nd.dentry);
1160         path_release(&nd);
1161  out:
1162         return error;
1163 @@ -346,6 +364,9 @@
1164         int old_fsuid, old_fsgid;
1165         kernel_cap_t old_cap;
1166         int res;
1167 +       struct lookup_intent it;
1168 +       
1169 +       it.it_op = IT_GETATTR;
1170  
1171         if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
1172                 return -EINVAL;
1173 @@ -363,13 +384,14 @@
1174         else
1175                 current->cap_effective = current->cap_permitted;
1176  
1177 -       res = user_path_walk(filename, &nd);
1178 +       res = user_path_walk_it(filename, &nd, &it);
1179         if (!res) {
1180                 res = permission(nd.dentry->d_inode, mode);
1181                 /* SuS v2 requires we report a read only fs too */
1182                 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
1183                    && !special_file(nd.dentry->d_inode->i_mode))
1184                         res = -EROFS;
1185 +               intent_release(nd.dentry);
1186                 path_release(&nd);
1187         }
1188  
1189 @@ -384,11 +406,13 @@
1190  {
1191         int error;
1192         struct nameidata nd;
1193 -
1194 -       error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
1195 +       struct lookup_intent it = {IT_GETATTR};
1196 +       
1197 +       error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it);
1198         if (error)
1199                 goto out;
1200  
1201 +       nd.dentry->d_it = &it;
1202         error = permission(nd.dentry->d_inode,MAY_EXEC);
1203         if (error)
1204                 goto dput_and_out;
1205 @@ -396,6 +420,7 @@
1206         set_fs_pwd(current->fs, nd.mnt, nd.dentry);
1207  
1208  dput_and_out:
1209 +       intent_release(nd.dentry);
1210         path_release(&nd);
1211  out:
1212         return error;
1213 @@ -435,12 +460,14 @@
1214  {
1215         int error;
1216         struct nameidata nd;
1217 +       struct lookup_intent it = {IT_GETATTR};
1218  
1219 -       error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
1220 -                     LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
1221 +       error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
1222 +                     LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
1223         if (error)
1224                 goto out;
1225  
1226 +       nd.dentry->d_it = &it;
1227         error = permission(nd.dentry->d_inode,MAY_EXEC);
1228         if (error)
1229                 goto dput_and_out;
1230 @@ -453,6 +480,7 @@
1231         set_fs_altroot();
1232         error = 0;
1233  dput_and_out:
1234 +       intent_release(nd.dentry);
1235         path_release(&nd);
1236  out:
1237         return error;
1238 @@ -497,12 +525,15 @@
1239         struct inode * inode;
1240         int error;
1241         struct iattr newattrs;
1242 +       struct lookup_intent it;
1243  
1244 -       error = user_path_walk(filename, &nd);
1245 +       it.it_op = IT_SETATTR;
1246 +       error = user_path_walk_it(filename, &nd, &it);
1247         if (error)
1248                 goto out;
1249         inode = nd.dentry->d_inode;
1250  
1251 +       nd.dentry->d_it = &it;
1252         error = -EROFS;
1253         if (IS_RDONLY(inode))
1254                 goto dput_and_out;
1255 @@ -518,6 +549,7 @@
1256         error = notify_change(nd.dentry, &newattrs);
1257  
1258  dput_and_out:
1259 +       intent_release(nd.dentry);
1260         path_release(&nd);
1261  out:
1262         return error;
1263 @@ -587,10 +619,15 @@
1264  {
1265         struct nameidata nd;
1266         int error;
1267 +       struct lookup_intent it;
1268 +       
1269 +       it.it_op = IT_SETATTR;
1270  
1271 -       error = user_path_walk(filename, &nd);
1272 +       error = user_path_walk_it(filename, &nd, &it);
1273         if (!error) {
1274 +               nd.dentry->d_it = &it;
1275                 error = chown_common(nd.dentry, user, group);
1276 +               intent_release(nd.dentry);
1277                 path_release(&nd);
1278         }
1279         return error;
1280 @@ -600,10 +637,15 @@
1281  {
1282         struct nameidata nd;
1283         int error;
1284 +       struct lookup_intent it;
1285  
1286 -       error = user_path_walk_link(filename, &nd);
1287 +       it.it_op = IT_SETATTR;
1288 +
1289 +       error = user_path_walk_link_it(filename, &nd, &it);
1290         if (!error) {
1291 +               nd.dentry->d_it = &it;
1292                 error = chown_common(nd.dentry, user, group);
1293 +               intent_release(nd.dentry);
1294                 path_release(&nd);
1295         }
1296         return error;
1297 @@ -637,10 +679,15 @@
1298   * for the internal routines (ie open_namei()/follow_link() etc). 00 is
1299   * used by symlinks.
1300   */
1301 +extern int open_namei_it(const char *filename, int namei_flags, int mode, 
1302 +                        struct nameidata *nd, struct lookup_intent *it);
1303 +struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, int flags, struct lookup_intent *it);
1304 +
1305  struct file *filp_open(const char * filename, int flags, int mode)
1306  {
1307         int namei_flags, error;
1308         struct nameidata nd;
1309 +       struct lookup_intent it = {IT_OPEN, 0};
1310  
1311         namei_flags = flags;
1312         if ((namei_flags+1) & O_ACCMODE)
1313 @@ -648,14 +695,14 @@
1314         if (namei_flags & O_TRUNC)
1315                 namei_flags |= 2;
1316  
1317 -       error = open_namei(filename, namei_flags, mode, &nd);
1318 +       error = open_namei_it(filename, namei_flags, mode, &nd, &it);
1319         if (!error)
1320 -               return dentry_open(nd.dentry, nd.mnt, flags);
1321 +               return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
1322  
1323         return ERR_PTR(error);
1324  }
1325  
1326 -struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
1327 +struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, int flags, struct lookup_intent *it)
1328  {
1329         struct file * f;
1330         struct inode *inode;
1331 @@ -712,11 +759,19 @@
1332  cleanup_file:
1333         put_filp(f);
1334  cleanup_dentry:
1335 +       intent_release(dentry);
1336         dput(dentry);
1337         mntput(mnt);
1338         return ERR_PTR(error);
1339  }
1340  
1341 +struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
1342 +{
1343 +       return dentry_open_it(dentry, mnt, flags, NULL);
1344 +
1345 +}
1346 +
1347 +
1348  /*
1349   * Find an empty file descriptor entry, and mark it busy.
1350   */
1351 --- linux-2.4.18-chaos5-pristine/fs/stat.c      Sat Jun 29 23:07:56 2002
1352 +++ linux-2.4.18-chaos5/fs/stat.c       Mon Jul  1 08:54:45 2002
1353 @@ -13,6 +13,8 @@
1354  
1355  #include <asm/uaccess.h>
1356  
1357 +
1358 +extern void intent_release(struct dentry *de);
1359  /*
1360   * Revalidate the inode. This is required for proper NFS attribute caching.
1361   */
1362 @@ -104,10 +106,12 @@
1363  {
1364         struct nameidata nd;
1365         int error;
1366 +       struct lookup_intent it = { IT_GETATTR};
1367  
1368 -       error = user_path_walk(name, &nd);
1369 +       error = user_path_walk_it(name, &nd, &it);
1370         if (!error) {
1371                 error = do_getattr(nd.mnt, nd.dentry, stat);
1372 +               intent_release(nd.dentry);
1373                 path_release(&nd);
1374         }
1375         return error;
1376 @@ -117,10 +121,13 @@
1377  {
1378         struct nameidata nd;
1379         int error;
1380 +       struct lookup_intent it = { IT_GETATTR};
1381 +
1382  
1383 -       error = user_path_walk_link(name, &nd);
1384 +       error = user_path_walk_link_it(name, &nd, &it);
1385         if (!error) {
1386                 error = do_getattr(nd.mnt, nd.dentry, stat);
1387 +               intent_release(nd.dentry);
1388                 path_release(&nd);
1389         }
1390         return error;
1391 --- linux-2.4.18-chaos5-pristine/mm/slab.c      Sat Jun 29 23:07:57 2002
1392 +++ linux-2.4.18-chaos5/mm/slab.c       Sat Jun 29 23:09:04 2002
1393 @@ -1207,6 +1207,58 @@
1394   * Called with the cache-lock held.
1395   */
1396  
1397 +extern struct page *check_get_page(unsigned long kaddr);
1398 +struct page *page_mem_map(struct page *page);
1399 +static int kmem_check_cache_obj (kmem_cache_t * cachep,
1400 +                                slab_t *slabp, void * objp)
1401 +{
1402 +       int i;
1403 +       unsigned int objnr;
1404 +#if DEBUG
1405 +       if (cachep->flags & SLAB_RED_ZONE) {
1406 +               objp -= BYTES_PER_WORD;
1407 +               if ( *(unsigned long *)objp != RED_MAGIC2)
1408 +                       /* Either write before start, or a double free. */
1409 +                       return 0;
1410 +               if (*(unsigned long *)(objp+cachep->objsize -
1411 +                               BYTES_PER_WORD) != RED_MAGIC2)
1412 +                       /* Either write past end, or a double free. */
1413 +                       return 0;
1414 +       }
1415 +#endif
1416 +
1417 +       objnr = (objp-slabp->s_mem)/cachep->objsize;
1418 +       if (objnr >= cachep->num)
1419 +               return 0;
1420 +       if (objp != slabp->s_mem + objnr*cachep->objsize)
1421 +               return 0;
1422 +
1423 +       /* Check slab's freelist to see if this obj is there. */
1424 +       for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
1425 +               if (i == objnr)
1426 +                       return 0;
1427 +       }
1428 +       return 1;
1429 +}
1430 +
1431 +
1432 +int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
1433 +{
1434 +       struct page *page = check_get_page((unsigned long)objp); 
1435 +
1436 +       if (!VALID_PAGE(page))
1437 +               return 0;
1438 +
1439 +       if (!PageSlab(page))
1440 +               return 0;
1441 +
1442 +       /* XXX check for freed slab objects ? */ 
1443 +       if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp)) 
1444 +               return 0;
1445 +
1446 +       return (cachep == GET_PAGE_CACHE(page));
1447 +}
1448 +
1449  #if DEBUG
1450  static int kmem_extra_free_checks (kmem_cache_t * cachep,
1451                         slab_t *slabp, void * objp)
1452 --- linux-2.4.18-chaos5-pristine/arch/i386/mm/init.c    Sat Jun 29 23:07:34 2002
1453 +++ linux-2.4.18-chaos5/arch/i386/mm/init.c     Sat Jun 29 23:09:04 2002
1454 @@ -43,6 +43,14 @@
1455  static unsigned long totalram_pages;
1456  static unsigned long totalhigh_pages;
1457  
1458 +
1459 +struct page *check_get_page(unsigned long kaddr)
1460 +{
1461 +#warning FIXME: Lustre team, is this solid enough?
1462 +       return virt_to_page(kaddr);
1463 +}
1464 +
1465 +
1466  int do_check_pgt_cache(int low, int high)
1467  {
1468         int freed = 0;
1469 --- linux-2.4.18-chaos5-pristine/include/linux/slab.h   Sat Jun 29 23:07:57 2002
1470 +++ linux-2.4.18-chaos5/include/linux/slab.h    Mon Jul  1 08:51:12 2002
1471 @@ -57,6 +57,7 @@
1472  extern int kmem_cache_shrink(kmem_cache_t *);
1473  extern void *kmem_cache_alloc(kmem_cache_t *, int);
1474  extern void kmem_cache_free(kmem_cache_t *, void *);
1475 +extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
1476  
1477  extern void *kmalloc(size_t, int);
1478  extern void kfree(const void *);
1479 --- linux-2.4.18-chaos5-pristine/scripts/mkspec Sat Jun 29 23:07:58 2002
1480 +++ linux-2.4.18-chaos5/scripts/mkspec  Sat Jun 29 23:09:04 2002
1481 @@ -64,6 +64,7 @@
1482  fi
1483  # Back on track, again
1484  echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
1485 +echo 'cp vmlinux $RPM_BUILD_ROOT'"/boot/vmlinux-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
1486  echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
1487  echo ""
1488  echo "%clean"