diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index c80989fe14da161749caaccc4b3af2fadd2e0805..0eb3b7fd59c059c9fe4708e5930796d5d2a02371 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -19,8 +19,13 @@ tbd  Cluster File Systems, Inc. <info@clusterfs.com>
 	- mds_reint_create() should take same inode create lock (2926)
 	- correct journal credits calculated for CANCEL_UNLINK_LOG (2931)
 	- don't close files for self_export to avoid uninitialized obd (2936)
-        - let lustre could be mounted with the same name for node and mds (2939)
-	
+	- allow MDS with the same name as client node (2939)
+	- hold dentry reference for closed log files for unlink (2325)
+	- reserve space for all logs during transactions (2059)
+	- don't evict page beyond end of stripe extent (2925)
+	- don't oops on a deleted current working directory (2399)
+	- handle hard links to targets without a parent properly (2517)
+
 2004-03-04  Cluster File Systems, Inc. <info@clusterfs.com>
        * version 1.2.0
        * bug fixes
diff --git a/lustre/include/linux/lustre_fsfilt.h b/lustre/include/linux/lustre_fsfilt.h
index 3f3421a4c429ff071b83164249c17644ca7a076c..40e991415b52e4ab28b846a016a87825b50367a7 100644
--- a/lustre/include/linux/lustre_fsfilt.h
+++ b/lustre/include/linux/lustre_fsfilt.h
@@ -28,6 +28,7 @@
 #ifdef __KERNEL__
 
 #include <linux/obd.h>
+#include <linux/obd_class.h>
 
 typedef void (*fsfilt_cb_t)(struct obd_device *obd, __u64 last_rcvd,
                             void *data, int error);
@@ -41,10 +42,11 @@ struct fsfilt_operations {
         struct list_head fs_list;
         struct module *fs_owner;
         char   *fs_type;
-        void   *(* fs_start)(struct inode *inode, int op, void *desc_private);
+        void   *(* fs_start)(struct inode *inode, int op, void *desc_private,
+                             int logs);
         void   *(* fs_brw_start)(int objcount, struct fsfilt_objinfo *fso,
                                  int niocount, struct niobuf_local *nb,
-                                 void *desc_private);
+                                 void *desc_private, int logs);
         int     (* fs_commit)(struct inode *inode, void *handle,int force_sync);
         int     (* fs_commit_async)(struct inode *inode, void *handle,
                                         void **wait_handle);
@@ -72,6 +74,7 @@ struct fsfilt_operations {
                                     int force_sync);
         int     (* fs_read_record)(struct file *, void *, int size, loff_t *);
         int     (* fs_setup)(struct super_block *sb);
+        int     (* fs_get_op_len)(int, struct fsfilt_objinfo *, int);
 };
 
 extern int fsfilt_register_ops(struct fsfilt_operations *fs_ops);
@@ -88,24 +91,23 @@ extern void fsfilt_put_ops(struct fsfilt_operations *fs_ops);
 #define FSFILT_OP_MKNOD          7
 #define FSFILT_OP_SETATTR        8
 #define FSFILT_OP_LINK           9
-#define FSFILT_OP_CREATE_LOG    10
-#define FSFILT_OP_UNLINK_LOG    11
-#define FSFILT_OP_CANCEL_UNLINK_LOG    12
+#define FSFILT_OP_CANCEL_UNLINK 10
 
-static inline void *fsfilt_start(struct obd_device *obd, struct inode *inode,
-                                 int op, struct obd_trans_info *oti)
+static inline void *fsfilt_start_log(struct obd_device *obd,
+                                     struct inode *inode, int op,
+                                     struct obd_trans_info *oti, int logs)
 {
         unsigned long now = jiffies;
         void *parent_handle = oti ? oti->oti_handle : NULL;
-        void *handle = obd->obd_fsops->fs_start(inode, op, parent_handle);
-        CDEBUG(D_INFO, "started handle %p (%p)\n", handle, parent_handle);
+        void *handle = obd->obd_fsops->fs_start(inode, op, parent_handle, logs);
+        CDEBUG(D_HA, "started handle %p (%p)\n", handle, parent_handle);
 
         if (oti != NULL) {
                 if (parent_handle == NULL) {
                         oti->oti_handle = handle;
                 } else if (handle != parent_handle) {
                         CERROR("mismatch: parent %p, handle %p, oti %p\n",
-                               parent_handle, handle, oti->oti_handle);
+                               parent_handle, handle, oti);
                         LBUG();
                 }
         }
@@ -114,17 +116,22 @@ static inline void *fsfilt_start(struct obd_device *obd, struct inode *inode,
         return handle;
 }
 
-static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount,
-                                     struct fsfilt_objinfo *fso, int niocount,
-                                     struct niobuf_local *nb,
-                                     struct obd_trans_info *oti)
+static inline void *fsfilt_start(struct obd_device *obd, struct inode *inode,
+                                 int op, struct obd_trans_info *oti)
+{
+        return fsfilt_start_log(obd, inode, op, oti, 0);
+}
+
+static inline void *fsfilt_brw_start_log(struct obd_device *obd,
+                                         int objcount,
+                                         struct fsfilt_objinfo *fso,
+                                         int niocount, struct niobuf_local *nb,
+                                         struct obd_trans_info *oti, int logs)
 {
         unsigned long now = jiffies;
         void *parent_handle = oti ? oti->oti_handle : NULL;
-        void *handle;
-
-        handle = obd->obd_fsops->fs_brw_start(objcount, fso, niocount, nb,
-                                              parent_handle);
+        void *handle = obd->obd_fsops->fs_brw_start(objcount, fso, niocount, nb,
+                                                    parent_handle, logs);
         CDEBUG(D_HA, "started handle %p (%p)\n", handle, parent_handle);
 
         if (oti != NULL) {
@@ -132,41 +139,53 @@ static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount,
                         oti->oti_handle = handle;
                 } else if (handle != parent_handle) {
                         CERROR("mismatch: parent %p, handle %p, oti %p\n",
-                               parent_handle, handle, oti->oti_handle);
+                               parent_handle, handle, oti);
                         LBUG();
                 }
         }
         if (time_after(jiffies, now + 15 * HZ))
                 CERROR("long journal start time %lus\n", (jiffies - now) / HZ);
+
         return handle;
 }
 
+static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount,
+                                     struct fsfilt_objinfo *fso, int niocount,
+                                     struct niobuf_local *nb,
+                                     struct obd_trans_info *oti)
+{
+        return fsfilt_brw_start_log(obd, objcount, fso, niocount, nb, oti, 0);
+}
+
 static inline int fsfilt_commit(struct obd_device *obd, struct inode *inode,
                                 void *handle, int force_sync)
 {
         unsigned long now = jiffies;
         int rc = obd->obd_fsops->fs_commit(inode, handle, force_sync);
-        CDEBUG(D_INFO, "committing handle %p\n", handle);
+        CDEBUG(D_HA, "committing handle %p\n", handle);
+
         if (time_after(jiffies, now + 15 * HZ))
                 CERROR("long journal start time %lus\n", (jiffies - now) / HZ);
+
         return rc;
 }
 
 static inline int fsfilt_commit_async(struct obd_device *obd,
-                                         struct inode *inode,
-                                         void *handle,
-                                         void **wait_handle)
+                                      struct inode *inode, void *handle,
+                                      void **wait_handle)
 {
         unsigned long now = jiffies;
         int rc = obd->obd_fsops->fs_commit_async(inode, handle, wait_handle);
+
         CDEBUG(D_HA, "committing handle %p (async)\n", *wait_handle);
         if (time_after(jiffies, now + 15 * HZ))
                 CERROR("long journal start time %lus\n", (jiffies - now) / HZ);
+
         return rc;
 }
 
-static inline int fsfilt_commit_wait(struct obd_device *obd, struct inode *inode,
-                                        void *handle)
+static inline int fsfilt_commit_wait(struct obd_device *obd,
+                                     struct inode *inode, void *handle)
 {
         unsigned long now = jiffies;
         int rc = obd->obd_fsops->fs_commit_wait(inode, handle);
@@ -217,8 +236,8 @@ static inline int fsfilt_add_journal_cb(struct obd_device *obd, __u64 last_rcvd,
                                         void *handle, fsfilt_cb_t cb_func,
                                         void *cb_data)
 {
-        return obd->obd_fsops->fs_add_journal_cb(obd, last_rcvd, handle,
-                                                 cb_func, cb_data);
+        return obd->obd_fsops->fs_add_journal_cb(obd, last_rcvd,
+                                                 handle, cb_func, cb_data);
 }
 
 /* very similar to obd_statfs(), but caller already holds obd_osfs_lock */
diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h
index 9da934fedd6aabbaed3c75ebd202bf4b5703f420..fb2da73869ea831e0504293144fdbfdb30558f43 100644
--- a/lustre/include/linux/obd.h
+++ b/lustre/include/linux/obd.h
@@ -479,10 +479,10 @@ struct obd_device {
         __u64                  obd_last_committed;
         struct fsfilt_operations *obd_fsops;
         spinlock_t              obd_osfs_lock;
-        struct llog_ctxt        *obd_llog_ctxt[LLOG_MAX_CTXTS];
         struct obd_statfs       obd_osfs;
         unsigned long           obd_osfs_age;
         struct obd_run_ctxt     obd_ctxt;
+        struct llog_ctxt        *obd_llog_ctxt[LLOG_MAX_CTXTS];
         struct obd_device       *obd_observer;
         struct obd_export       *obd_self_export;
 
diff --git a/lustre/kernel_patches/patches/dcache_refcount_debug.patch b/lustre/kernel_patches/patches/dcache_refcount_debug.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0eddc23286dcd4741e9461045c15b12af1b9d4df
--- /dev/null
+++ b/lustre/kernel_patches/patches/dcache_refcount_debug.patch
@@ -0,0 +1,24 @@
+--- ./fs/dcache.c.orig	2004-01-30 14:54:45.000000000 -0700
++++ ./fs/dcache.c	2004-02-20 14:49:18.000000000 -0700
+@@ -348,8 +348,20 @@
+ 		dentry_stat.nr_unused--;
+ 
+ 		/* Unused dentry with a count? */
+-		if (atomic_read(&dentry->d_count))
++		if (atomic_read(&dentry->d_count)) {
++			struct inode *inode = dentry->d_inode;
++			printk(KERN_CRIT "dentry %*s %p->%lu/%u(%p/%s) ct %d\n",
++			       dentry->d_name.len, dentry->d_name.name, dentry,
++			       inode ? inode->i_ino : 0,
++			       inode ? inode->i_generation : 0, inode,
++			       inode ? inode->i_sb ?
++					inode->i_sb->s_type->name : "" : "",
++			       atomic_read(&dentry->d_count));
++			spin_unlock(&dcache_lock);
++			set_task_state(current, TASK_UNINTERRUPTIBLE);
++			schedule();
+ 			BUG();
++		}
+ 
+ 		prune_one_dentry(dentry);
+ 		if (!--count)
diff --git a/lustre/kernel_patches/patches/ext3-pdirops-2.4.20-chaos.patch b/lustre/kernel_patches/patches/ext3-pdirops-2.4.20-chaos.patch
new file mode 100644
index 0000000000000000000000000000000000000000..28badd64704f560caaf4d9874b1cc90bb1ec0abe
--- /dev/null
+++ b/lustre/kernel_patches/patches/ext3-pdirops-2.4.20-chaos.patch
@@ -0,0 +1,1248 @@
+ fs/ext3/ialloc.c          |    3 
+ fs/ext3/inode.c           |    3 
+ fs/ext3/namei.c           |  582 +++++++++++++++++++++++++++++++++++++---------
+ fs/ext3/super.c           |   14 +
+ include/linux/ext3_fs.h   |    1 
+ include/linux/ext3_fs_i.h |    6 
+ 6 files changed, 500 insertions(+), 109 deletions(-)
+
+Index: linux-2.4.20/fs/ext3/namei.c
+===================================================================
+--- linux-2.4.20.orig/fs/ext3/namei.c	Wed Mar 17 15:37:09 2004
++++ linux-2.4.20/fs/ext3/namei.c	Wed Mar 17 15:37:56 2004
+@@ -51,6 +51,9 @@
+ {
+ 	struct buffer_head *bh;
+ 
++	/* with parallel dir operations all appends
++	 * have to be serialized -bzzz */
++	down(&EXT3_I(inode)->i_append_sem);
+ 	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+ 
+ 	if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
+@@ -58,6 +61,8 @@
+ 		EXT3_I(inode)->i_disksize = inode->i_size;
+ 		ext3_journal_get_write_access(handle,bh);
+ 	}
++	up(&EXT3_I(inode)->i_append_sem);
++	
+ 	return bh;
+ }
+ 
+@@ -134,6 +139,8 @@
+ 	struct buffer_head *bh;
+ 	struct dx_entry *entries;
+ 	struct dx_entry *at;
++	unsigned long leaf;
++	unsigned int curidx;
+ };
+ 
+ struct dx_map_entry
+@@ -142,6 +149,30 @@
+ 	u32 offs;
+ };
+ 
++/* FIXME: this should be reworked using bb_spin_lock
++ * introduced in -mm tree
++ */
++#define BH_DXLock	25
++
++static inline void dx_lock_bh(struct buffer_head volatile *bh)
++{
++#ifdef CONFIG_SMP
++        while (test_and_set_bit(BH_DXLock, &bh->b_state)) {
++                while (test_bit(BH_DXLock, &bh->b_state))
++                        cpu_relax();
++        }
++#endif
++}
++
++static inline void dx_unlock_bh(struct buffer_head *bh)
++{
++#ifdef CONFIG_SMP
++        smp_mb__before_clear_bit();
++        clear_bit(BH_DXLock, &bh->b_state);
++#endif
++}
++
++
+ #ifdef CONFIG_EXT3_INDEX
+ static inline unsigned dx_get_block (struct dx_entry *entry);
+ static void dx_set_block (struct dx_entry *entry, unsigned value);
+@@ -153,7 +184,7 @@
+ static void dx_set_limit (struct dx_entry *entries, unsigned value);
+ static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
+ static unsigned dx_node_limit (struct inode *dir);
+-static struct dx_frame *dx_probe(struct dentry *dentry,
++static struct dx_frame *dx_probe(struct qstr *name,
+ 				 struct inode *dir,
+ 				 struct dx_hash_info *hinfo,
+ 				 struct dx_frame *frame,
+@@ -165,15 +196,18 @@
+ static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
+ 		struct dx_map_entry *offsets, int count);
+ static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
+-static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
++static void dx_insert_block (struct inode *, struct dx_frame *, u32, u32, u32);
+ static int ext3_htree_next_block(struct inode *dir, __u32 hash,
+ 				 struct dx_frame *frame,
+ 				 struct dx_frame *frames, int *err,
+ 				 __u32 *start_hash);
+ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
+-		       struct ext3_dir_entry_2 **res_dir, int *err);
++		       struct ext3_dir_entry_2 **res_dir, int *err,
++		       int rwlock, void **lock);
+ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			     struct inode *inode);
++static inline void *ext3_lock_htree(struct inode *, unsigned long, int);
++static inline void ext3_unlock_htree(struct inode *, void *);
+ 
+ /*
+  * Future: use high four bits of block for coalesce-on-delete flags
+@@ -306,6 +340,94 @@
+ #endif /* DX_DEBUG */
+ 
+ /*
++ * dx_find_position
++ *
++ * search position of specified hash in index
++ *
++ */
++
++struct dx_entry * dx_find_position(struct dx_entry * entries, u32 hash)
++{
++	struct dx_entry *p, *q, *m;
++	int count;
++
++	count = dx_get_count(entries);
++	p = entries + 1;
++	q = entries + count - 1;
++	while (p <= q)
++	{
++		m = p + (q - p)/2;
++		if (dx_get_hash(m) > hash)
++			q = m - 1;
++		else
++			p = m + 1;
++	}
++	return p - 1;
++}
++
++/*
++ * returns 1 if path is unchanged
++ */
++int dx_check_path(struct dx_frame *frame, u32 hash)
++{
++	struct dx_entry *p;
++	int ret = 1;
++
++	dx_lock_bh(frame->bh);
++	p = dx_find_position(frame->entries, hash);
++	if (frame->leaf != dx_get_block(p))
++		ret = 0;
++	dx_unlock_bh(frame->bh);
++	
++	return ret;
++}
++
++/*
++ * 0 - changed
++ * 1 - hasn't changed
++ */
++static int
++dx_check_full_path(struct dx_frame *frames, struct dx_hash_info *hinfo)
++{
++	struct dx_entry *p;
++	struct dx_frame *frame = frames;
++	u32 leaf;
++
++	/* check first level */
++	dx_lock_bh(frame->bh);
++	p = dx_find_position(frame->entries, hinfo->hash);
++	leaf = dx_get_block(p);
++	dx_unlock_bh(frame->bh);
++	
++	if (leaf != frame->leaf) 
++		return 0;
++	
++	/* is there 2nd level? */
++	frame++;
++	if (frame->bh == NULL)
++		return 1;
++
++	/* check second level */
++	dx_lock_bh(frame->bh);
++
++	/* probably 1st level got changed, check it */
++	if (!dx_check_path(frames, hinfo->hash)) {
++		/* path changed */
++		dx_unlock_bh(frame->bh);
++		return 0;
++	}
++
++	p = dx_find_position(frame->entries, hinfo->hash);
++	leaf = dx_get_block(p);
++	dx_unlock_bh(frame->bh);
++	
++	if (leaf != frame->leaf)
++		return 0;
++
++	return 1;
++}
++
++/*
+  * Probe for a directory leaf block to search.
+  *
+  * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
+@@ -315,19 +437,20 @@
+  * back to userspace.
+  */
+ static struct dx_frame *
+-dx_probe(struct dentry *dentry, struct inode *dir,
++dx_probe(struct qstr *name, struct inode *dir,
+ 	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
+ {
+-	unsigned count, indirect;
+-	struct dx_entry *at, *entries, *p, *q, *m;
++	unsigned indirect;
++	struct dx_entry *at, *entries;
+ 	struct dx_root *root;
+ 	struct buffer_head *bh;
+ 	struct dx_frame *frame = frame_in;
+ 	u32 hash;
++	unsigned int curidx;
+ 
+ 	frame->bh = NULL;
+-	if (dentry)
+-		dir = dentry->d_parent->d_inode;
++	frame[1].bh = NULL;
++
+ 	if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
+ 		goto fail;
+ 	root = (struct dx_root *) bh->b_data;
+@@ -343,8 +466,8 @@
+ 	}
+ 	hinfo->hash_version = root->info.hash_version;
+ 	hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed;
+-	if (dentry)
+-		ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
++	if (name)
++		ext3fs_dirhash(name->name, name->len, hinfo);
+ 	hash = hinfo->hash;
+ 
+ 	if (root->info.unused_flags & 1) {
+@@ -356,7 +479,19 @@
+ 		goto fail;
+ 	}
+ 
++repeat:
++	curidx = 0;
++	entries = (struct dx_entry *) (((char *)&root->info) +
++				       root->info.info_length);
++	assert(dx_get_limit(entries) == dx_root_limit(dir,
++						      root->info.info_length));
++	dxtrace (printk("Look up %x", hash));
++	dx_lock_bh(bh);
++	/* indirect must be initialized under bh lock because
++	 * 2nd level creation procedure may change it and dx_probe()
++	 * will suggest htree is still single-level -bzzz */
+ 	if ((indirect = root->info.indirect_levels) > 1) {
++		dx_unlock_bh(bh);
+ 		ext3_warning(dir->i_sb, __FUNCTION__,
+ 			     "Unimplemented inode hash depth: %#06x",
+ 			     root->info.indirect_levels);
+@@ -364,56 +499,46 @@
+ 		*err = ERR_BAD_DX_DIR;
+ 		goto fail;
+ 	}
+-
+-	entries = (struct dx_entry *) (((char *)&root->info) +
+-				       root->info.info_length);
+-	assert(dx_get_limit(entries) == dx_root_limit(dir,
+-						      root->info.info_length));
+-	dxtrace (printk("Look up %x", hash));
++	
+ 	while (1)
+ 	{
+-		count = dx_get_count(entries);
+-		assert (count && count <= dx_get_limit(entries));
+-		p = entries + 1;
+-		q = entries + count - 1;
+-		while (p <= q)
+-		{
+-			m = p + (q - p)/2;
+-			dxtrace(printk("."));
+-			if (dx_get_hash(m) > hash)
+-				q = m - 1;
+-			else
+-				p = m + 1;
+-		}
+-
+-		if (0) // linear search cross check
+-		{
+-			unsigned n = count - 1;
+-			at = entries;
+-			while (n--)
+-			{
+-				dxtrace(printk(","));
+-				if (dx_get_hash(++at) > hash)
+-				{
+-					at--;
+-					break;
+-				}
+-			}
+-			assert (at == p - 1);
+-		}
+-
+-		at = p - 1;
+-		dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
++		at = dx_find_position(entries, hinfo->hash);
++		dxtrace(printk(" %x->%u\n",
++				at == entries? 0: dx_get_hash(at),
++				dx_get_block(at)));
+ 		frame->bh = bh;
+ 		frame->entries = entries;
+ 		frame->at = at;
+-		if (!indirect--) return frame;
+-		if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
++		frame->curidx = curidx;
++		frame->leaf = dx_get_block(at);
++		if (!indirect--) {
++			dx_unlock_bh(bh);
++			return frame;
++		}
++		
++		/* step into next htree level */
++		curidx = dx_get_block(at);
++		dx_unlock_bh(bh);
++		if (!(bh = ext3_bread (NULL,dir, frame->leaf, 0, err)))
+ 			goto fail2;
++		
++		dx_lock_bh(bh);
++		/* splitting may change root index block and move
++		 * hash we're looking for into another index block
++		 * so, we have to check this situation and repeat
++		 * from begining if path got changed -bzzz */
++		if (!dx_check_path(frame, hash)) {
++			dx_unlock_bh(bh);
++			bh = frame->bh;
++			indirect++;
++			goto repeat;
++		}
++		
+ 		at = entries = ((struct dx_node *) bh->b_data)->entries;
+ 		assert (dx_get_limit(entries) == dx_node_limit (dir));
+ 		frame++;
+ 	}
++	dx_unlock_bh(bh);
+ fail2:
+ 	while (frame >= frame_in) {
+ 		brelse(frame->bh);
+@@ -427,8 +552,7 @@
+ {
+ 	if (frames[0].bh == NULL)
+ 		return;
+-
+-	if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
++	if (frames[1].bh != NULL)
+ 		brelse(frames[1].bh);
+ 	brelse(frames[0].bh);
+ }
+@@ -470,8 +594,10 @@
+ 	 * nodes need to be read.
+ 	 */
+ 	while (1) {
+-		if (++(p->at) < p->entries + dx_get_count(p->entries))
++		if (++(p->at) < p->entries + dx_get_count(p->entries)) {
++			p->leaf = dx_get_block(p->at);
+ 			break;
++		}
+ 		if (p == frames)
+ 			return 0;
+ 		num_frames++;
+@@ -497,13 +623,17 @@
+ 	 * block so no check is necessary
+ 	 */
+ 	while (num_frames--) {
+-		if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
+-				      0, err)))
++		u32 idx;
++		
++		idx = p->leaf = dx_get_block(p->at);
++		if (!(bh = ext3_bread(NULL, dir, idx, 0, err)))
+ 			return -1; /* Failure */
+ 		p++;
+ 		brelse (p->bh);
+ 		p->bh = bh;
+ 		p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
++		p->curidx = idx;
++		p->leaf = dx_get_block(p->at);
+ 	}
+ 	return 1;
+ }
+@@ -543,7 +673,7 @@
+ 	dir = dir_file->f_dentry->d_inode;
+ 	hinfo.hash = start_hash;
+ 	hinfo.minor_hash = 0;
+-	frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
++	frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
+ 	if (!frame)
+ 		return err;
+ 
+@@ -625,7 +755,8 @@
+ 			count++;
+ 		}
+ 		/* XXX: do we need to check rec_len == 0 case? -Chris */
+-		de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
++		de = (struct ext3_dir_entry_2 *)((char*)de +
++				le16_to_cpu(de->rec_len));
+ 	}
+ 	return count;
+ }
+@@ -658,7 +789,8 @@
+ 	} while(more);
+ }
+ 
+-static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
++static void dx_insert_block(struct inode *dir, struct dx_frame *frame,
++			u32 hash, u32 block, u32 idx)
+ {
+ 	struct dx_entry *entries = frame->entries;
+ 	struct dx_entry *old = frame->at, *new = old + 1;
+@@ -670,6 +802,7 @@
+ 	dx_set_hash(new, hash);
+ 	dx_set_block(new, block);
+ 	dx_set_count(entries, count + 1);
++	
+ }
+ #endif
+ 
+@@ -752,7 +885,8 @@
+ 
+ 	
+ static struct buffer_head * ext3_find_entry (struct dentry *dentry,
+-					struct ext3_dir_entry_2 ** res_dir)
++					struct ext3_dir_entry_2 ** res_dir,
++					int rwlock, void **lock)
+ {
+ 	struct super_block * sb;
+ 	struct buffer_head * bh_use[NAMEI_RA_SIZE];
+@@ -768,6 +902,7 @@
+ 	int namelen;
+ 	const u8 *name;
+ 	unsigned blocksize;
++	int do_not_use_dx = 0;
+ 
+ 	*res_dir = NULL;
+ 	sb = dir->i_sb;
+@@ -776,9 +911,10 @@
+ 	name = dentry->d_name.name;
+ 	if (namelen > EXT3_NAME_LEN)
+ 		return NULL;
++repeat:
+ #ifdef CONFIG_EXT3_INDEX
+ 	if (is_dx(dir)) {
+-		bh = ext3_dx_find_entry(dentry, res_dir, &err);
++		bh = ext3_dx_find_entry(dentry, res_dir, &err, rwlock, lock);
+ 		/*
+ 		 * On success, or if the error was file not found,
+ 		 * return.  Otherwise, fall back to doing a search the
+@@ -787,8 +923,14 @@
+ 		if (bh || (err != ERR_BAD_DX_DIR))
+ 			return bh;
+ 		dxtrace(printk("ext3_find_entry: dx failed, falling back\n"));
++		do_not_use_dx = 1;
+ 	}
+ #endif
++	*lock = ext3_lock_htree(dir, 0, rwlock);
++	if (is_dx(dir) && !do_not_use_dx) {
++		ext3_unlock_htree(dir, *lock);
++		goto repeat;
++	}
+ 	nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
+ 	start = EXT3_I(dir)->i_dir_start_lookup;
+ 	if (start >= nblocks)
+@@ -860,12 +1002,17 @@
+ 	/* Clean up the read-ahead blocks */
+ 	for (; ra_ptr < ra_max; ra_ptr++)
+ 		brelse (bh_use[ra_ptr]);
++	if (!ret) {
++		ext3_unlock_htree(dir, *lock);
++		*lock = NULL;
++	}
+ 	return ret;
+ }
+ 
+ #ifdef CONFIG_EXT3_INDEX
+ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
+-		       struct ext3_dir_entry_2 **res_dir, int *err)
++		       struct ext3_dir_entry_2 **res_dir, int *err,
++		       int rwlock, void **lock)
+ {
+ 	struct super_block * sb;
+ 	struct dx_hash_info	hinfo;
+@@ -880,11 +1027,22 @@
+ 	struct inode *dir = dentry->d_parent->d_inode;
+ 	
+ 	sb = dir->i_sb;
+-	if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err)))
++repeat:
++	if (!(frame = dx_probe (&dentry->d_name, dir, &hinfo, frames, err)))
+ 		return NULL;
++	
++	*lock = ext3_lock_htree(dir, frame->leaf, rwlock);
++	/* while locking leaf we just found may get splitted
++	 * so, we need another leaf. check this */
++	if (!dx_check_full_path(frames, &hinfo)) {
++		ext3_unlock_htree(dir, *lock);
++		dx_release(frames);
++		goto repeat;
++	}
++
+ 	hash = hinfo.hash;
+ 	do {
+-		block = dx_get_block(frame->at);
++		block = frame->leaf;
+ 		if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
+ 			goto errout;
+ 		de = (struct ext3_dir_entry_2 *) bh->b_data;
+@@ -918,6 +1076,8 @@
+ 	*err = -ENOENT;
+ errout:
+ 	dxtrace(printk("%s not found\n", name));
++	ext3_unlock_htree(dir, *lock);
++	*lock = NULL;
+ 	dx_release (frames);
+ 	return NULL;
+ }
+@@ -928,6 +1088,7 @@
+ 	struct inode * inode;
+ 	struct ext3_dir_entry_2 * de;
+ 	struct buffer_head * bh;
++    void *lock = NULL;
+ 
+ 	if (dentry->d_name.len > EXT3_NAME_LEN)
+ 		return ERR_PTR(-ENAMETOOLONG);
+@@ -935,10 +1096,11 @@
+ 	if (ext3_check_for_iopen(dir, dentry))
+ 		return NULL;
+ 
+-	bh = ext3_find_entry(dentry, &de);
++	bh = ext3_find_entry(dentry, &de, 0, &lock);
+ 	inode = NULL;
+ 	if (bh) {
+ 		unsigned long ino = le32_to_cpu(de->inode);
++		ext3_unlock_htree(dir, lock);
+ 		brelse (bh);
+ 		inode = iget(dir->i_sb, ino);
+ 
+@@ -975,7 +1137,8 @@
+ 	unsigned rec_len = 0;
+ 
+ 	while (count--) {
+-		struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs);
++		struct ext3_dir_entry_2 *de =
++			(struct ext3_dir_entry_2 *) (from + map->offs);
+ 		rec_len = EXT3_DIR_REC_LEN(de->name_len);
+ 		memcpy (to, de, rec_len);
+ 		((struct ext3_dir_entry_2 *) to)->rec_len = rec_len;
+@@ -988,7 +1151,8 @@
+ 
+ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
+ {
+-	struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
++	struct ext3_dir_entry_2 *next, *to, *prev;
++	struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) base;
+ 	unsigned rec_len = 0;
+ 
+ 	prev = to = de;
+@@ -1010,7 +1174,8 @@
+ 
+ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+ 			struct buffer_head **bh,struct dx_frame *frame,
+-			struct dx_hash_info *hinfo, int *error)
++			struct dx_hash_info *hinfo, void **target,
++			int *error)
+ {
+ 	unsigned blocksize = dir->i_sb->s_blocksize;
+ 	unsigned count, continued;
+@@ -1057,23 +1222,30 @@
+ 	hash2 = map[split].hash;
+ 	continued = hash2 == map[split - 1].hash;
+ 	dxtrace(printk("Split block %i at %x, %i/%i\n",
+-		dx_get_block(frame->at), hash2, split, count-split));
+-
++		frame->leaf, hash2, split, count-split));
++	
+ 	/* Fancy dance to stay within two buffers */
+ 	de2 = dx_move_dirents(data1, data2, map + split, count - split);
+ 	de = dx_pack_dirents(data1,blocksize);
+ 	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+ 	de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+-	dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
+-	dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
++	dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data1, blocksize, 1));
++	dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data2, blocksize, 1));
+ 
+ 	/* Which block gets the new entry? */
++	*target = NULL;
+ 	if (hinfo->hash >= hash2)
+ 	{
+ 		swap(*bh, bh2);
+ 		de = de2;
+-	}
+-	dx_insert_block (frame, hash2 + continued, newblock);
++
++		/* entry will be stored into new block
++		 * we have to lock it before add_dirent_to_buf */
++		*target = ext3_lock_htree(dir, newblock, 1);
++	}
++	dx_lock_bh(frame->bh);
++	dx_insert_block (dir, frame, hash2 + continued, newblock, frame->curidx);
++	dx_unlock_bh(frame->bh);
+ 	err = ext3_journal_dirty_metadata (handle, bh2);
+ 	if (err)
+ 		goto journal_error;
+@@ -1147,7 +1319,8 @@
+ 	nlen = EXT3_DIR_REC_LEN(de->name_len);
+ 	rlen = le16_to_cpu(de->rec_len);
+ 	if (de->inode) {
+-		struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen);
++		struct ext3_dir_entry_2 *de1 =
++			(struct ext3_dir_entry_2 *)((char *)de + nlen);
+ 		de1->rec_len = cpu_to_le16(rlen - nlen);
+ 		de->rec_len = cpu_to_le16(nlen);
+ 		de = de1;
+@@ -1205,7 +1378,8 @@
+ 	unsigned	blocksize;
+ 	struct dx_hash_info hinfo;
+ 	u32		block;
+-		
++	void		*lock, *new_lock;
++
+ 	blocksize =  dir->i_sb->s_blocksize;
+ 	dxtrace(printk("Creating index\n"));
+ 	retval = ext3_journal_get_write_access(handle, bh);
+@@ -1216,7 +1390,6 @@
+ 	}
+ 	root = (struct dx_root *) bh->b_data;
+ 		
+-	EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
+ 	bh2 = ext3_append (handle, dir, &block, &retval);
+ 	if (!(bh2)) {
+ 		brelse(bh);
+@@ -1224,6 +1397,8 @@
+ 	}
+ 	data1 = bh2->b_data;
+ 
++	lock = ext3_lock_htree(dir, block, 1);
++
+ 	/* The 0th block becomes the root, move the dirents out */
+ 	de = (struct ext3_dir_entry_2 *) &root->dotdot;
+ 	de = (struct ext3_dir_entry_2 *) ((char *)de + de->rec_len);
+@@ -1253,13 +1428,25 @@
+ 	frame->entries = entries;
+ 	frame->at = entries;
+ 	frame->bh = bh;
++	frame->curidx = 0;
++	frame->leaf = 0;
++	frame[1].bh = NULL;
+ 	bh = bh2;
+-	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
++	de = do_split(handle,dir, &bh, frame, &hinfo, &new_lock, &retval);
+ 	dx_release (frames);
+ 	if (!(de))
+-		return retval;
++		goto cleanup;
++
++	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
++cleanup:
++	if (new_lock)
++		ext3_unlock_htree(dir, new_lock);
++	/* we mark directory indexed in order to
++	 * avoid races while htree being created -bzzz */
++	EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
++	ext3_unlock_htree(dir, lock);
+ 
+-	return add_dirent_to_buf(handle, dentry, inode, de, bh);
++	return retval;
+ }
+ #endif
+ 
+@@ -1288,11 +1475,13 @@
+ 	unsigned blocksize;
+ 	unsigned nlen, rlen;
+ 	u32 block, blocks;
++	void *lock;
+ 
+ 	sb = dir->i_sb;
+ 	blocksize = sb->s_blocksize;
+ 	if (!dentry->d_name.len)
+ 		return -EINVAL;
++repeat:
+ #ifdef CONFIG_EXT3_INDEX
+ 	if (is_dx(dir)) {
+ 		retval = ext3_dx_add_entry(handle, dentry, inode);
+@@ -1303,36 +1492,53 @@
+ 		ext3_mark_inode_dirty(handle, dir);
+ 	}
+ #endif
++	lock = ext3_lock_htree(dir, 0, 1);
++	if (is_dx(dir)) {
++		/* we got lock for block 0
++		 * probably previous holder of the lock
++		 * created htree -bzzz */
++		ext3_unlock_htree(dir, lock);
++		goto repeat;
++	}
++	
+ 	blocks = dir->i_size >> sb->s_blocksize_bits;
+ 	for (block = 0, offset = 0; block < blocks; block++) {
+ 		bh = ext3_bread(handle, dir, block, 0, &retval);
+-		if(!bh)
++		if(!bh) {
++			ext3_unlock_htree(dir, lock);
+ 			return retval;
++		}
+ 		retval = add_dirent_to_buf(handle, dentry, inode, 0, bh);
+-		if (retval != -ENOSPC)
++		if (retval != -ENOSPC) {
++			ext3_unlock_htree(dir, lock);
+ 			return retval;
++		}
+ 
+ #ifdef CONFIG_EXT3_INDEX
+ 		if (blocks == 1 && !dx_fallback &&
+-		    EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
+-			return make_indexed_dir(handle, dentry, inode, bh);
++		    EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) {
++			retval = make_indexed_dir(handle, dentry, inode, bh);
++			ext3_unlock_htree(dir, lock);
++			return retval;
++		}
+ #endif
+ 		brelse(bh);
+ 	}
+ 	bh = ext3_append(handle, dir, &block, &retval);
+-	if (!bh)
++	if (!bh) {
++		ext3_unlock_htree(dir, lock);
+ 		return retval;
++	}
+ 	de = (struct ext3_dir_entry_2 *) bh->b_data;
+ 	de->inode = 0;
+ 	de->rec_len = cpu_to_le16(rlen = blocksize);
+ 	nlen = 0;
+-	return add_dirent_to_buf(handle, dentry, inode, de, bh);
++	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
++	ext3_unlock_htree(dir, lock);
++	return retval;
+ }
+ 
+ #ifdef CONFIG_EXT3_INDEX
+-/*
+- * Returns 0 for success, or a negative error value
+- */
+ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
+ 			     struct inode *inode)
+ {
+@@ -1344,15 +1550,28 @@
+ 	struct super_block * sb = dir->i_sb;
+ 	struct ext3_dir_entry_2 *de;
+ 	int err;
+-
+-	frame = dx_probe(dentry, 0, &hinfo, frames, &err);
++	int curidx;
++	void *idx_lock, *leaf_lock, *newleaf_lock;
++	
++repeat:
++	frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
+ 	if (!frame)
+ 		return err;
+-	entries = frame->entries;
+-	at = frame->at;
+ 
+-	if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
++	/* we're going to chage leaf, so lock it first */
++	leaf_lock = ext3_lock_htree(dir, frame->leaf, 1);
++
++	/* while locking leaf we just found may get splitted
++	 * so we need to check this */
++	if (!dx_check_full_path(frames, &hinfo)) {
++		ext3_unlock_htree(dir, leaf_lock);
++		dx_release(frames);
++		goto repeat;
++	}
++	if (!(bh = ext3_bread(handle,dir, frame->leaf, 0, &err))) {
++		printk("can't ext3_bread(%d) = %d\n", (int) frame->leaf, err);
+ 		goto cleanup;
++	}
+ 
+ 	BUFFER_TRACE(bh, "get_write_access");
+ 	err = ext3_journal_get_write_access(handle, bh);
+@@ -1365,6 +1584,35 @@
+ 		goto cleanup;
+ 	}
+ 
++	/* our leaf has no enough space. hence, we have to
++	 * split it. so lock index for this leaf first */
++	curidx = frame->curidx;
++	idx_lock = ext3_lock_htree(dir, curidx, 1);
++
++	/* now check did path get changed? */
++	dx_release(frames);
++
++	frame = dx_probe(&dentry->d_name, dentry->d_parent->d_inode,
++			&hinfo, frames, &err);
++	if (!frame) {
++		/* FIXME: error handling here */
++		brelse(bh);
++		ext3_unlock_htree(dir, idx_lock);
++		return err;
++	}
++	
++	if (frame->curidx != curidx) {
++		/* path has been changed. we have to drop old lock
++		 * and repeat */
++		brelse(bh);
++		ext3_unlock_htree(dir, idx_lock);
++		ext3_unlock_htree(dir, leaf_lock);
++		dx_release(frames);
++		goto repeat;
++	}
++	entries = frame->entries;
++	at = frame->at;
++
+ 	/* Block full, should compress but for now just split */
+ 	dxtrace(printk("using %u of %u node entries\n",
+ 		       dx_get_count(entries), dx_get_limit(entries)));
+@@ -1376,7 +1624,8 @@
+ 		struct dx_entry *entries2;
+ 		struct dx_node *node2;
+ 		struct buffer_head *bh2;
+-
++		void *nb_lock;
++		
+ 		if (levels && (dx_get_count(frames->entries) ==
+ 			       dx_get_limit(frames->entries))) {
+ 			ext3_warning(sb, __FUNCTION__,
+@@ -1387,6 +1636,7 @@
+ 		bh2 = ext3_append (handle, dir, &newblock, &err);
+ 		if (!(bh2))
+ 			goto cleanup;
++		nb_lock = ext3_lock_htree(dir, newblock, 1);
+ 		node2 = (struct dx_node *)(bh2->b_data);
+ 		entries2 = node2->entries;
+ 		node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+@@ -1398,27 +1648,73 @@
+ 		if (levels) {
+ 			unsigned icount1 = icount/2, icount2 = icount - icount1;
+ 			unsigned hash2 = dx_get_hash(entries + icount1);
++			void *ri_lock;
++
++			/* we have to protect root htree index against
++			 * another dx_add_entry() which would want to
++			 * split it too -bzzz */
++			ri_lock = ext3_lock_htree(dir, 0, 1);
++
++			/* as root index block blocked we must repeat
++			 * searching for current position of our 2nd index -bzzz */
++			dx_lock_bh(frame->bh);
++			frames->at = dx_find_position(frames->entries, hinfo.hash);
++			dx_unlock_bh(frame->bh);
++			
+ 			dxtrace(printk("Split index %i/%i\n", icount1, icount2));
+-				
+-			BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
++	
++			BUFFER_TRACE(frame->bh, "get_write_access");
+ 			err = ext3_journal_get_write_access(handle,
+ 							     frames[0].bh);
+ 			if (err)
+ 				goto journal_error;
+-				
++			
++			/* copy index into new one */
+ 			memcpy ((char *) entries2, (char *) (entries + icount1),
+ 				icount2 * sizeof(struct dx_entry));
+-			dx_set_count (entries, icount1);
+ 			dx_set_count (entries2, icount2);
+ 			dx_set_limit (entries2, dx_node_limit(dir));
+ 
+ 			/* Which index block gets the new entry? */
+ 			if (at - entries >= icount1) {
++				/* unlock index we won't use */
++				ext3_unlock_htree(dir, idx_lock);
++				idx_lock = nb_lock;
+ 				frame->at = at = at - entries - icount1 + entries2;
+-				frame->entries = entries = entries2;
++				frame->entries = entries2;
++				frame->curidx = curidx = newblock;
+ 				swap(frame->bh, bh2);
++			} else {
++				/* we'll use old index,so new one may be freed */
++				ext3_unlock_htree(dir, nb_lock);
+ 			}
+-			dx_insert_block (frames + 0, hash2, newblock);
++		
++			/* NOTE: very subtle piece of code
++			 * competing dx_probe() may find 2nd level index in root
++			 * index, then we insert new index here and set new count
++			 * in that 2nd level index. so, dx_probe() may see 2nd
++			 * level index w/o hash it looks for. the solution is
++			 * to check root index after we locked just founded 2nd
++			 * level index -bzzz */
++			dx_lock_bh(frames[0].bh);
++			dx_insert_block (dir, frames + 0, hash2, newblock, 0);
++			dx_unlock_bh(frames[0].bh);
++			
++			/* now old and new 2nd level index blocks contain
++			 * all pointers, so dx_probe() may find it in the both.
++			 * it's OK -bzzz */
++			
++			dx_lock_bh(frame->bh);
++			dx_set_count(entries, icount1);
++			dx_unlock_bh(frame->bh);
++
++			/* now old 2nd level index block points to first half
++			 * of leafs. it's importand that dx_probe() must
++			 * check root index block for changes under
++			 * dx_lock_bh(frame->bh) -bzzz */
++
++			ext3_unlock_htree(dir, ri_lock);
++		
+ 			dxtrace(dx_show_index ("node", frames[1].entries));
+ 			dxtrace(dx_show_index ("node",
+ 			       ((struct dx_node *) bh2->b_data)->entries));
+@@ -1427,38 +1723,61 @@
+ 				goto journal_error;
+ 			brelse (bh2);
+ 		} else {
++			unsigned long leaf = frame->leaf;
++
+ 			dxtrace(printk("Creating second level index...\n"));
+ 			memcpy((char *) entries2, (char *) entries,
+ 			       icount * sizeof(struct dx_entry));
+ 			dx_set_limit(entries2, dx_node_limit(dir));
+ 
+ 			/* Set up root */
++ 			dx_lock_bh(frames[0].bh);
+ 			dx_set_count(entries, 1);
+ 			dx_set_block(entries + 0, newblock);
+ 			((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
++			dx_unlock_bh(frames[0].bh);
+ 
+ 			/* Add new access path frame */
+ 			frame = frames + 1;
+ 			frame->at = at = at - entries + entries2;
+ 			frame->entries = entries = entries2;
+ 			frame->bh = bh2;
++			frame->curidx = newblock;
++			frame->leaf = leaf;
+ 			err = ext3_journal_get_write_access(handle,
+ 							     frame->bh);
+ 			if (err)
+ 				goto journal_error;
++
++			/* first level index was root. it's already initialized */
++			/* we my unlock it now */
++			ext3_unlock_htree(dir, idx_lock);
++
++			/* current index is just created 2nd level index */
++			curidx = newblock;
++			idx_lock = nb_lock;
+ 		}
+ 		ext3_journal_dirty_metadata(handle, frames[0].bh);
+ 	}
+-	de = do_split(handle, dir, &bh, frame, &hinfo, &err);
++	de = do_split(handle, dir, &bh, frame, &hinfo, &newleaf_lock, &err);
+ 	if (!de)
+ 		goto cleanup;
++
++	/* index splitted */
++	ext3_unlock_htree(dir, idx_lock);
++	
+ 	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
++
++	if (newleaf_lock)
++		ext3_unlock_htree(dir, newleaf_lock);
++	
+ 	bh = 0;
+ 	goto cleanup;
+ 	
+ journal_error:
+ 	ext3_std_error(dir->i_sb, err);
+ cleanup:
++	ext3_unlock_htree(dir, leaf_lock);
+ 	if (bh)
+ 		brelse(bh);
+ 	dx_release(frames);
+@@ -1902,6 +2221,7 @@
+ 	struct buffer_head * bh;
+ 	struct ext3_dir_entry_2 * de;
+ 	handle_t *handle;
++	void *lock;
+ 
+ 	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+ 	if (IS_ERR(handle)) {
+@@ -1909,7 +2229,7 @@
+ 	}
+ 
+ 	retval = -ENOENT;
+-	bh = ext3_find_entry (dentry, &de);
++	bh = ext3_find_entry (dentry, &de, 1, &lock);
+ 	if (!bh)
+ 		goto end_rmdir;
+ 
+@@ -1920,14 +2240,19 @@
+ 	DQUOT_INIT(inode);
+ 
+ 	retval = -EIO;
+-	if (le32_to_cpu(de->inode) != inode->i_ino)
++	if (le32_to_cpu(de->inode) != inode->i_ino) {
++		ext3_unlock_htree(dir, lock);
+ 		goto end_rmdir;
++	}
+ 
+ 	retval = -ENOTEMPTY;
+-	if (!empty_dir (inode))
++	if (!empty_dir (inode)) {
++		ext3_unlock_htree(dir, lock);
+ 		goto end_rmdir;
++	}
+ 
+ 	retval = ext3_delete_entry(handle, dir, de, bh);
++	ext3_unlock_htree(dir, lock);
+ 	if (retval)
+ 		goto end_rmdir;
+ 	if (inode->i_nlink != 2)
+@@ -1956,6 +2281,7 @@
+ 	struct buffer_head * bh;
+ 	struct ext3_dir_entry_2 * de;
+ 	handle_t *handle;
++	void *lock;
+ 
+ 	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+ 	if (IS_ERR(handle)) {
+@@ -1966,7 +2292,7 @@
+ 		handle->h_sync = 1;
+ 
+ 	retval = -ENOENT;
+-	bh = ext3_find_entry (dentry, &de);
++	bh = ext3_find_entry (dentry, &de, 1, &lock);
+ 	if (!bh)
+ 		goto end_unlink;
+ 
+@@ -1974,8 +2300,10 @@
+ 	DQUOT_INIT(inode);
+ 
+ 	retval = -EIO;
+-	if (le32_to_cpu(de->inode) != inode->i_ino)
++	if (le32_to_cpu(de->inode) != inode->i_ino) {
++		ext3_unlock_htree(dir, lock);
+ 		goto end_unlink;
++	}
+ 	
+ 	if (!inode->i_nlink) {
+ 		ext3_warning (inode->i_sb, "ext3_unlink",
+@@ -1984,6 +2312,7 @@
+ 		inode->i_nlink = 1;
+ 	}
+ 	retval = ext3_delete_entry(handle, dir, de, bh);
++	ext3_unlock_htree(dir, lock);
+ 	if (retval)
+ 		goto end_unlink;
+ 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+@@ -2121,6 +2450,7 @@
+ 	struct buffer_head * old_bh, * new_bh, * dir_bh;
+ 	struct ext3_dir_entry_2 * old_de, * new_de;
+ 	int retval;
++	void *lock1 = NULL, *lock2 = NULL, *lock3 = NULL;
+ 
+ 	old_bh = new_bh = dir_bh = NULL;
+ 
+@@ -2133,7 +2463,10 @@
+ 	if (IS_SYNC(old_dir) || IS_SYNC(new_dir))
+ 		handle->h_sync = 1;
+ 
+-	old_bh = ext3_find_entry (old_dentry, &old_de);
++	if (old_dentry->d_parent == new_dentry->d_parent)
++		down(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem);
++
++	old_bh = ext3_find_entry (old_dentry, &old_de, 1, &lock1 /* FIXME */);
+ 	/*
+ 	 *  Check for inode number is _not_ due to possible IO errors.
+ 	 *  We might rmdir the source, keep it as pwd of some process
+@@ -2146,7 +2479,7 @@
+ 		goto end_rename;
+ 
+ 	new_inode = new_dentry->d_inode;
+-	new_bh = ext3_find_entry (new_dentry, &new_de);
++	new_bh = ext3_find_entry (new_dentry, &new_de, 1, &lock2 /* FIXME */);
+ 	if (new_bh) {
+ 		if (!new_inode) {
+ 			brelse (new_bh);
+@@ -2209,7 +2542,7 @@
+ 		struct buffer_head *old_bh2;
+ 		struct ext3_dir_entry_2 *old_de2;
+ 		
+-		old_bh2 = ext3_find_entry(old_dentry, &old_de2);
++		old_bh2 = ext3_find_entry(old_dentry, &old_de2, 1, &lock3 /* FIXME */);
+ 		if (old_bh2) {
+ 			retval = ext3_delete_entry(handle, old_dir,
+ 						   old_de2, old_bh2);
+@@ -2252,6 +2585,14 @@
+ 	retval = 0;
+ 
+ end_rename:
++	if (lock1)
++		ext3_unlock_htree(old_dentry->d_parent->d_inode, lock1);
++	if (lock2)
++		ext3_unlock_htree(new_dentry->d_parent->d_inode, lock2);
++	if (lock3)
++		ext3_unlock_htree(old_dentry->d_parent->d_inode, lock3);
++	if (old_dentry->d_parent == new_dentry->d_parent)
++		up(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem);
+ 	brelse (dir_bh);
+ 	brelse (old_bh);
+ 	brelse (new_bh);
+@@ -2260,6 +2601,29 @@
+ }
+ 
+ /*
++ * this locking primitives are used to protect parts
++ * of dir's htree. protection unit is block: leaf or index
++ */
++static inline void *ext3_lock_htree(struct inode *dir,
++					unsigned long value, int rwlock)
++{
++	void *lock;
++	
++	if (!test_opt(dir->i_sb, PDIROPS))
++		return NULL;
++	lock = dynlock_lock(&EXT3_I(dir)->i_htree_lock, value, 1, GFP_KERNEL);
++	return lock;
++}
++
++static inline void ext3_unlock_htree(struct inode *dir,
++					void *lock)
++{
++	if (!test_opt(dir->i_sb, PDIROPS) || !lock)
++		return;
++	dynlock_unlock(&EXT3_I(dir)->i_htree_lock, lock);
++}
++
++/*
+  * directories can handle most operations...
+  */
+ struct inode_operations ext3_dir_inode_operations = {
+Index: linux-2.4.20/fs/ext3/super.c
+===================================================================
+--- linux-2.4.20.orig/fs/ext3/super.c	Wed Mar 17 15:37:09 2004
++++ linux-2.4.20/fs/ext3/super.c	Wed Mar 17 15:37:10 2004
+@@ -796,6 +796,8 @@
+ 				return 0;
+ 			}
+ 		}
++		else if (!strcmp (this_char, "pdirops"))
++			set_opt (sbi->s_mount_opt, PDIROPS);
+ 		else if (!strcmp (this_char, "grpid") ||
+ 			 !strcmp (this_char, "bsdgroups"))
+ 			set_opt (*mount_options, GRPID);
+@@ -822,6 +824,9 @@
+ 			if (want_numeric(value, "sb", sb_block))
+ 				return 0;
+ 		}
++		else if (!strcmp (this_char, "pdirops")) {
++			set_opt (sbi->s_mount_opt, PDIROPS);
++		}
+ #ifdef CONFIG_JBD_DEBUG
+ 		else if (!strcmp (this_char, "ro-after")) {
+ 			unsigned long v;
+@@ -985,6 +990,10 @@
+ 		ext3_check_inodes_bitmap (sb);
+ 	}
+ #endif
++#ifdef S_PDIROPS
++	if (test_opt (sb, PDIROPS))
++		sb->s_flags |= S_PDIROPS;
++#endif
+ 	setup_ro_after(sb);
+ 	return res;
+ }
+@@ -1484,6 +1493,11 @@
+ 		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
+ 		"writeback");
+ 
++	if (test_opt(sb, PDIROPS)) {
++		printk (KERN_INFO "EXT3-fs: mounted filesystem with parallel dirops\n");
++		sb->s_flags |= S_PDIROPS;
++	}
++		
+ 	return sb;
+ 
+ failed_mount3:
+Index: linux-2.4.20/fs/ext3/inode.c
+===================================================================
+--- linux-2.4.20.orig/fs/ext3/inode.c	Wed Mar 17 15:37:09 2004
++++ linux-2.4.20/fs/ext3/inode.c	Wed Mar 17 15:37:10 2004
+@@ -2435,6 +2435,9 @@
+ 	} else if (S_ISDIR(inode->i_mode)) {
+ 		inode->i_op = &ext3_dir_inode_operations;
+ 		inode->i_fop = &ext3_dir_operations;
++		dynlock_init(&EXT3_I(inode)->i_htree_lock);
++		sema_init(&EXT3_I(inode)->i_rename_sem, 1);
++		sema_init(&EXT3_I(inode)->i_append_sem, 1);
+ 	} else if (S_ISLNK(inode->i_mode)) {
+ 		if (ext3_inode_is_fast_symlink(inode))
+ 			inode->i_op = &ext3_fast_symlink_inode_operations;
+Index: linux-2.4.20/fs/ext3/ialloc.c
+===================================================================
+--- linux-2.4.20.orig/fs/ext3/ialloc.c	Wed Mar 17 15:37:09 2004
++++ linux-2.4.20/fs/ext3/ialloc.c	Wed Mar 17 15:37:10 2004
+@@ -601,6 +601,9 @@
+ 		return ERR_PTR(-EDQUOT);
+ 	}
+ 	ext3_debug ("allocating inode %lu\n", inode->i_ino);
++	dynlock_init(&EXT3_I(inode)->i_htree_lock);
++	sema_init(&EXT3_I(inode)->i_rename_sem, 1);
++	sema_init(&EXT3_I(inode)->i_append_sem, 1);
+ 	return inode;
+ 
+ fail:
+Index: linux-2.4.20/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.4.20.orig/include/linux/ext3_fs.h	Wed Mar 17 15:37:09 2004
++++ linux-2.4.20/include/linux/ext3_fs.h	Wed Mar 17 15:37:10 2004
+@@ -306,6 +306,7 @@
+ /*
+  * Mount flags
+  */
++#define EXT3_MOUNT_PDIROPS		0x800000/* Parallel dir operations */
+ #define EXT3_MOUNT_CHECK		0x0001	/* Do mount-time checks */
+ #define EXT3_MOUNT_GRPID		0x0004	/* Create files with directory's group */
+ #define EXT3_MOUNT_DEBUG		0x0008	/* Some debugging messages */
+Index: linux-2.4.20/include/linux/ext3_fs_i.h
+===================================================================
+--- linux-2.4.20.orig/include/linux/ext3_fs_i.h	Thu Nov 22 11:46:19 2001
++++ linux-2.4.20/include/linux/ext3_fs_i.h	Wed Mar 17 15:37:10 2004
+@@ -17,6 +17,7 @@
+ #define _LINUX_EXT3_FS_I
+ 
+ #include <linux/rwsem.h>
++#include <linux/dynlocks.h>
+ 
+ /*
+  * second extended file system inode data in memory
+@@ -73,6 +74,11 @@
+ 	 * by other means, so we have truncate_sem.
+ 	 */
+ 	struct rw_semaphore truncate_sem;
++
++	/* following fields for parallel directory operations -bzzz */
++	struct dynlock i_htree_lock;
++	struct semaphore i_append_sem;
++	struct semaphore i_rename_sem;
+ };
+ 
+ #endif	/* _LINUX_EXT3_FS_I */
diff --git a/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch b/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch
new file mode 100644
index 0000000000000000000000000000000000000000..9203859a2a13d963421dd51e90e776f3226630bd
--- /dev/null
+++ b/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch
@@ -0,0 +1,22 @@
+--- linux-2.4.24-l32/mm/filemap.c.inode_ramax	2004-03-14 13:16:21.000000000 -0800
++++ linux-2.4.24-l32/mm/filemap.c	2004-03-16 10:57:14.000000000 -0800
+@@ -1226,6 +1226,8 @@
+ 
+ static inline int get_max_readahead(struct inode * inode)
+ {
++	if (inode->i_mapping->a_ops->max_readahead)
++		return inode->i_mapping->a_ops->max_readahead(inode);
+ 	if (!inode->i_dev || !max_readahead[MAJOR(inode->i_dev)])
+ 		return vm_max_readahead;
+ 	return max_readahead[MAJOR(inode->i_dev)][MINOR(inode->i_dev)];
+--- linux-2.4.24-l32/include/linux/fs.h.inode_ramax	2004-03-14 13:15:49.000000000 -0800
++++ linux-2.4.24-l32/include/linux/fs.h	2004-03-15 11:56:56.000000000 -0800
+@@ -410,6 +410,8 @@
+ #define KERNEL_HAS_DIRECT_FILEIO /* Unfortunate kludge due to lack of foresight */
+ 	int (*direct_fileIO)(int, struct file *, struct kiobuf *, unsigned long, int);
+ 	void (*removepage)(struct page *); /* called when page gets removed from the inode */
++#define KERNEL_HAS_AS_MAX_READAHEAD
++	int (*max_readahead)(struct inode *);
+ };
+ 
+ struct address_space {
diff --git a/lustre/kernel_patches/patches/iopen-2.4.20.patch b/lustre/kernel_patches/patches/iopen-2.4.20.patch
index 8800e1fb2e3b8237f8509426a44d560dc6aa07c9..f40953365a8cb8b2cc4673e1e35b8a64f798bcac 100644
--- a/lustre/kernel_patches/patches/iopen-2.4.20.patch
+++ b/lustre/kernel_patches/patches/iopen-2.4.20.patch
@@ -8,10 +8,10 @@
  include/linux/ext3_fs.h            |    2 
  8 files changed, 318 insertions(+), 2 deletions(-)
 
-Index: linux-2.4.22-uml/Documentation/filesystems/ext2.txt
+Index: lum/Documentation/filesystems/ext2.txt
 ===================================================================
---- linux-2.4.22-uml.orig/Documentation/filesystems/ext2.txt	2001-07-11 16:44:45.000000000 -0600
-+++ linux-2.4.22-uml/Documentation/filesystems/ext2.txt	2004-01-30 14:18:10.000000000 -0700
+--- lum.orig/Documentation/filesystems/ext2.txt	2001-07-11 16:44:45.000000000 -0600
++++ lum/Documentation/filesystems/ext2.txt	2004-03-09 16:46:38.000000000 -0700
 @@ -35,6 +35,22 @@
  
  sb=n				Use alternate superblock at this location.
@@ -35,10 +35,10 @@ Index: linux-2.4.22-uml/Documentation/filesystems/ext2.txt
  grpquota,noquota,quota,usrquota	Quota options are silently ignored by ext2.
  
  
-Index: linux-2.4.22-uml/fs/ext3/Makefile
+Index: lum/fs/ext3/Makefile
 ===================================================================
---- linux-2.4.22-uml.orig/fs/ext3/Makefile	2004-01-30 14:17:58.000000000 -0700
-+++ linux-2.4.22-uml/fs/ext3/Makefile	2004-01-30 14:18:10.000000000 -0700
+--- lum.orig/fs/ext3/Makefile	2004-01-30 14:54:50.000000000 -0700
++++ lum/fs/ext3/Makefile	2004-03-09 16:46:39.000000000 -0700
 @@ -11,7 +11,7 @@
  
  export-objs := ext3-exports.o
@@ -48,10 +48,10 @@ Index: linux-2.4.22-uml/fs/ext3/Makefile
  		ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
  obj-m    := $(O_TARGET)
  
-Index: linux-2.4.22-uml/fs/ext3/inode.c
+Index: lum/fs/ext3/inode.c
 ===================================================================
---- linux-2.4.22-uml.orig/fs/ext3/inode.c	2004-01-30 14:17:59.000000000 -0700
-+++ linux-2.4.22-uml/fs/ext3/inode.c	2004-01-30 14:18:10.000000000 -0700
+--- lum.orig/fs/ext3/inode.c	2004-01-30 14:54:55.000000000 -0700
++++ lum/fs/ext3/inode.c	2004-03-09 16:46:41.000000000 -0700
 @@ -31,6 +31,7 @@
  #include <linux/highuid.h>
  #include <linux/quotaops.h>
@@ -70,11 +70,11 @@ Index: linux-2.4.22-uml/fs/ext3/inode.c
  	if(ext3_get_inode_loc(inode, &iloc))
  		goto bad_inode;
  	bh = iloc.bh;
-Index: linux-2.4.22-uml/fs/ext3/iopen.c
+Index: lum/fs/ext3/iopen.c
 ===================================================================
---- linux-2.4.22-uml.orig/fs/ext3/iopen.c	2004-01-30 14:18:10.000000000 -0700
-+++ linux-2.4.22-uml/fs/ext3/iopen.c	2004-01-30 14:18:10.000000000 -0700
-@@ -0,0 +1,258 @@
+--- lum.orig/fs/ext3/iopen.c	2004-03-09 16:46:37.000000000 -0700
++++ lum/fs/ext3/iopen.c	2004-03-09 16:48:03.000000000 -0700
+@@ -0,0 +1,282 @@
 +/*
 + * linux/fs/ext3/iopen.c
 + *
@@ -211,13 +211,24 @@ Index: linux-2.4.22-uml/fs/ext3/iopen.c
 +
 +/* This function is spliced into ext3_lookup and does the move of a
 + * disconnected dentry (if it exists) to a connected dentry.
-+ * Caller must hold dcache_lock.
 + */
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
++				    int rehash)
 +{
 +	struct dentry *tmp, *goal = NULL;
 +	struct list_head *lp;
 +
++	/* verify this dentry is really new */
++	assert(dentry->d_inode == NULL);
++	assert(list_empty(&dentry->d_alias));		/* d_instantiate */
++	if (rehash)
++		assert(list_empty(&dentry->d_hash));	/* d_rehash */
++	assert(list_empty(&dentry->d_subdirs));
++
++	spin_lock(&dcache_lock);
++	if (!inode)
++		goto do_rehash;
++
 +	/* preferrably return a connected dentry */
 +	list_for_each(lp, &inode->i_dentry) {
 +		tmp = list_entry(lp, struct dentry, d_alias);
@@ -231,27 +242,40 @@ Index: linux-2.4.22-uml/fs/ext3/iopen.c
 +	}
 +
 +	if (!goal)
-+		return NULL;
++		goto do_instantiate;
 +
 +	/* Move the goal to the de hash queue - like d_move() */
 +	goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
 +	list_del_init(&goal->d_hash);
 +
 +	list_del(&goal->d_child);
-+	list_del(&de->d_child);
++	list_del(&dentry->d_child);
 +
 +	/* Switch the parents and the names.. */
-+	switch_names(goal, de);
-+	do_switch(goal->d_parent, de->d_parent);
-+	do_switch(goal->d_name.len, de->d_name.len);
-+	do_switch(goal->d_name.hash, de->d_name.hash);
++	switch_names(goal, dentry);
++	do_switch(goal->d_parent, dentry->d_parent);
++	do_switch(goal->d_name.len, dentry->d_name.len);
++	do_switch(goal->d_name.hash, dentry->d_name.hash);
 +
 +	/* And add them back to the (new) parent lists */
 +	list_add(&goal->d_child, &goal->d_parent->d_subdirs);
-+	list_add(&de->d_child, &de->d_parent->d_subdirs);
++	list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
 +	__d_rehash(goal, 0);
++	spin_unlock(&dcache_lock);
++	iput(inode);
 +
 +	return goal;
++
++	/* d_add(), but don't drop dcache_lock before adding dentry to inode */
++do_instantiate:
++	list_add(&dentry->d_alias, &inode->i_dentry);	/* d_instantiate */
++	dentry->d_inode = inode;
++do_rehash:
++	if (rehash)
++		__d_rehash(dentry, 0);			/* d_rehash */
++	spin_unlock(&dcache_lock);
++
++	return NULL;
 +}
 +
 +/*
@@ -333,10 +357,10 @@ Index: linux-2.4.22-uml/fs/ext3/iopen.c
 +
 +	return 1;
 +}
-Index: linux-2.4.22-uml/fs/ext3/iopen.h
+Index: lum/fs/ext3/iopen.h
 ===================================================================
---- linux-2.4.22-uml.orig/fs/ext3/iopen.h	2004-01-30 14:18:10.000000000 -0700
-+++ linux-2.4.22-uml/fs/ext3/iopen.h	2004-01-30 14:18:10.000000000 -0700
+--- lum.orig/fs/ext3/iopen.h	2004-03-09 16:46:37.000000000 -0700
++++ lum/fs/ext3/iopen.h	2004-03-09 16:48:03.000000000 -0700
 @@ -0,0 +1,15 @@
 +/*
 + * iopen.h
@@ -351,12 +375,12 @@ Index: linux-2.4.22-uml/fs/ext3/iopen.h
 +
 +extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
 +extern int ext3_iopen_get_inode(struct inode *inode);
-+extern struct dentry *iopen_connect_dentry(struct dentry *de,
-+					   struct inode *inode);
-Index: linux-2.4.22-uml/fs/ext3/namei.c
++extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
++					   struct inode *inode, int rehash);
+Index: lum/fs/ext3/namei.c
 ===================================================================
---- linux-2.4.22-uml.orig/fs/ext3/namei.c	2004-01-30 14:17:59.000000000 -0700
-+++ linux-2.4.22-uml/fs/ext3/namei.c	2004-01-30 14:19:44.000000000 -0700
+--- lum.orig/fs/ext3/namei.c	2004-01-30 14:54:53.000000000 -0700
++++ lum/fs/ext3/namei.c	2004-03-09 16:49:25.000000000 -0700
 @@ -35,7 +35,7 @@
  #include <linux/string.h>
  #include <linux/locks.h>
@@ -366,12 +390,7 @@ Index: linux-2.4.22-uml/fs/ext3/namei.c
  
  /*
   * define how far ahead to read directories while searching them.
-@@ -927,10 +927,14 @@
- 	struct inode * inode;
- 	struct ext3_dir_entry_2 * de;
- 	struct buffer_head * bh;
-+	struct dentry *alternate = NULL;
- 
+@@ -931,6 +931,9 @@
  	if (dentry->d_name.len > EXT3_NAME_LEN)
  		return ERR_PTR(-ENAMETOOLONG);
  
@@ -381,41 +400,67 @@ Index: linux-2.4.22-uml/fs/ext3/namei.c
  	bh = ext3_find_entry(dentry, &de);
  	inode = NULL;
  	if (bh) {
-@@ -942,7 +946,28 @@
+@@ -942,8 +945,8 @@
  			return ERR_PTR(-EACCES);
  		}
  	}
 -	d_add(dentry, inode);
+-	return NULL;
 +
-+	/* verify this dentry is really new */
-+	assert(!dentry->d_inode);
-+	assert(list_empty(&dentry->d_alias));		/* d_instantiate */
-+	assert(list_empty(&dentry->d_hash));		/* d_rehash */
-+	assert(list_empty(&dentry->d_subdirs));
-+
-+	spin_lock(&dcache_lock);
-+	if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
-+		spin_unlock(&dcache_lock);
-+		iput(inode);
-+		return alternate;
++	return iopen_connect_dentry(dentry, inode, 1);
+ }
+ 
+ #define S_SHIFT 12
+@@ -1932,10 +1935,6 @@
+ 			      inode->i_nlink);
+ 	inode->i_version = ++event;
+ 	inode->i_nlink = 0;
+-	/* There's no need to set i_disksize: the fact that i_nlink is
+-	 * zero will ensure that the right thing happens during any
+-	 * recovery. */
+-	inode->i_size = 0;
+ 	ext3_orphan_add(handle, inode);
+ 	dir->i_nlink--;
+ 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+@@ -2086,6 +2085,23 @@
+ 	return err;
+ }
+ 
++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
++static int ext3_add_link(handle_t *handle, struct dentry *dentry,
++			 struct inode *inode)
++{
++	int err = ext3_add_entry(handle, dentry, inode);
++	if (!err) {
++		err = ext3_mark_inode_dirty(handle, inode);
++		if (err == 0) {
++			(void)iopen_connect_dentry(dentry, inode, 0);
++			return 0;
++		}
 +	}
++	ext3_dec_count(handle, inode);
++	iput(inode);
++	return err;
++}
 +
-+	/* d_add(), but don't drop dcache_lock before adding dentry to inode */
-+	if (inode)					/* d_instantiate */
-+		list_add(&dentry->d_alias, &inode->i_dentry);
-+	dentry->d_inode = inode;
-+
-+	__d_rehash(dentry, 0);				/* d_rehash */
-+	spin_unlock(&dcache_lock);
-+
- 	return NULL;
- }
+ static int ext3_link (struct dentry * old_dentry,
+ 		struct inode * dir, struct dentry *dentry)
+ {
+@@ -2113,7 +2129,8 @@
+ 	ext3_inc_count(handle, inode);
+ 	atomic_inc(&inode->i_count);
  
-Index: linux-2.4.22-uml/fs/ext3/super.c
+-	err = ext3_add_nondir(handle, dentry, inode);
++	err = ext3_add_link(handle, dentry, inode);
++	ext3_orphan_del(handle, inode);
+ 	ext3_journal_stop(handle, dir);
+ 	return err;
+ }
+Index: lum/fs/ext3/super.c
 ===================================================================
---- linux-2.4.22-uml.orig/fs/ext3/super.c	Sun Nov 16 01:19:22 2003
-+++ linux-2.4.22-uml/fs/ext3/super.c	Sun Nov 16 01:27:31 2003
-@@ -839,6 +839,18 @@
+--- lum.orig/fs/ext3/super.c	2004-01-30 14:54:53.000000000 -0700
++++ lum/fs/ext3/super.c	2004-03-09 16:46:45.000000000 -0700
+@@ -742,6 +742,18 @@
  		         || !strcmp (this_char, "quota")
  		         || !strcmp (this_char, "usrquota"))
  			/* Don't do anything ;-) */ ;
@@ -434,10 +479,10 @@ Index: linux-2.4.22-uml/fs/ext3/super.c
  		else if (!strcmp (this_char, "journal")) {
  			/* @@@ FIXME */
  			/* Eventually we will want to be able to create
-Index: linux-2.4.22-uml/include/linux/ext3_fs.h
+Index: lum/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.4.22-uml.orig/include/linux/ext3_fs.h	2004-01-30 14:17:59.000000000 -0700
-+++ linux-2.4.22-uml/include/linux/ext3_fs.h	2004-01-30 14:18:10.000000000 -0700
+--- lum.orig/include/linux/ext3_fs.h	2004-01-30 14:54:53.000000000 -0700
++++ lum/include/linux/ext3_fs.h	2004-03-09 16:46:46.000000000 -0700
 @@ -322,6 +322,8 @@
  #define EXT3_MOUNT_UPDATE_JOURNAL	0x1000	/* Update the journal format */
  #define EXT3_MOUNT_NO_UID32		0x2000  /* Disable 32-bit UIDs */
diff --git a/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch b/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch
index 16bde95593078d513ba8018f274744876d232ad4..62bd8e1618fafcd5a57d12fd07fdd38ad7e7cb58 100644
--- a/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch
+++ b/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch
@@ -8,11 +8,11 @@
  include/linux/ext3_fs.h            |    2 
  8 files changed, 318 insertions(+), 2 deletions(-)
 
-Index: linux-2.4.21-chaos/Documentation/filesystems/ext2.txt
+Index: linux-ia64/Documentation/filesystems/ext2.txt
 ===================================================================
---- linux-2.4.21-chaos.orig/Documentation/filesystems/ext2.txt	2002-05-08 01:53:59.000000000 +0400
-+++ linux-2.4.21-chaos/Documentation/filesystems/ext2.txt	2003-12-12 16:19:04.000000000 +0300
-@@ -35,6 +35,22 @@
+--- linux-ia64.orig/Documentation/filesystems/ext2.txt	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/Documentation/filesystems/ext2.txt	2004-03-17 18:03:15.000000000 -0800
+@@ -35,6 +35,22 @@ resgid=n			The group ID which may use th
  
  sb=n				Use alternate superblock at this location.
  
@@ -35,11 +35,11 @@ Index: linux-2.4.21-chaos/Documentation/filesystems/ext2.txt
  grpquota,noquota,quota,usrquota	Quota options are silently ignored by ext2.
  
  
-Index: linux-2.4.21-chaos/fs/ext3/Makefile
+Index: linux-ia64/fs/ext3/Makefile
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/ext3/Makefile	2003-12-12 16:18:36.000000000 +0300
-+++ linux-2.4.21-chaos/fs/ext3/Makefile	2003-12-12 16:19:04.000000000 +0300
-@@ -11,7 +11,7 @@
+--- linux-ia64.orig/fs/ext3/Makefile	2004-03-17 18:03:14.000000000 -0800
++++ linux-ia64/fs/ext3/Makefile	2004-03-17 18:03:15.000000000 -0800
+@@ -11,7 +11,7 @@ O_TARGET := ext3.o
  
  export-objs := ext3-exports.o
  
@@ -48,10 +48,10 @@ Index: linux-2.4.21-chaos/fs/ext3/Makefile
  		ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
  obj-m    := $(O_TARGET)
  
-Index: linux-2.4.21-chaos/fs/ext3/inode.c
+Index: linux-ia64/fs/ext3/inode.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/ext3/inode.c	2003-12-12 16:19:02.000000000 +0300
-+++ linux-2.4.21-chaos/fs/ext3/inode.c	2003-12-12 16:19:05.000000000 +0300
+--- linux-ia64.orig/fs/ext3/inode.c	2004-03-17 18:03:15.000000000 -0800
++++ linux-ia64/fs/ext3/inode.c	2004-03-17 18:10:36.000000000 -0800
 @@ -34,6 +34,7 @@
  #include <linux/highuid.h>
  #include <linux/quotaops.h>
@@ -60,7 +60,7 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c
  
  /*
   * SEARCH_FROM_ZERO forces each block allocation to search from the start
-@@ -2430,6 +2431,9 @@
+@@ -2430,6 +2431,9 @@ void ext3_read_inode(struct inode * inod
  	struct buffer_head *bh;
  	int block;
  	
@@ -70,21 +70,14 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c
  	if(ext3_get_inode_loc(inode, &iloc))
  		goto bad_inode;
  	bh = iloc.bh;
-Index: linux-2.4.21-chaos/fs/ext3/iopen.c
+Index: linux-ia64/fs/ext3/iopen.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/ext3/iopen.c	2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.21-chaos/fs/ext3/iopen.c	2003-12-12 16:19:05.000000000 +0300
-@@ -0,0 +1,258 @@
-+/*
-+ * linux/fs/ext3/iopen.c
-+ *
-+ * Special support for open by inode number
-+ *
-+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
-+ * This file may be redistributed under the terms of the GNU General
-+ * Public License.
-+ *
+--- linux-ia64.orig/fs/ext3/iopen.c	2004-03-17 18:02:08.000000000 -0800
++++ linux-ia64/fs/ext3/iopen.c	2004-03-17 18:10:58.000000000 -0800
+@@ -8,3 +8,275 @@
+  * This file may be redistributed under the terms of the GNU General
+  * Public License.
+  *
 + *
 + * Invariants:
 + *   - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
@@ -211,13 +204,24 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +
 +/* This function is spliced into ext3_lookup and does the move of a
 + * disconnected dentry (if it exists) to a connected dentry.
-+ * Caller must hold dcache_lock.
 + */
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
++				    int rehash)
 +{
 +	struct dentry *tmp, *goal = NULL;
 +	struct list_head *lp;
 +
++	/* verify this dentry is really new */
++	assert(dentry->d_inode == NULL);
++	assert(list_empty(&dentry->d_alias));		/* d_instantiate */
++	if (rehash)
++		assert(list_empty(&dentry->d_hash));	/* d_rehash */
++	assert(list_empty(&dentry->d_subdirs));
++
++	spin_lock(&dcache_lock);
++	if (!inode)
++		goto do_rehash;
++
 +	/* preferrably return a connected dentry */
 +	list_for_each(lp, &inode->i_dentry) {
 +		tmp = list_entry(lp, struct dentry, d_alias);
@@ -231,27 +235,40 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +	}
 +
 +	if (!goal)
-+		return NULL;
++		goto do_instantiate;
 +
 +	/* Move the goal to the de hash queue - like d_move() */
 +	goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
 +	list_del_init(&goal->d_hash);
 +
 +	list_del(&goal->d_child);
-+	list_del(&de->d_child);
++	list_del(&dentry->d_child);
 +
 +	/* Switch the parents and the names.. */
-+	switch_names(goal, de);
-+	do_switch(goal->d_parent, de->d_parent);
-+	do_switch(goal->d_name.len, de->d_name.len);
-+	do_switch(goal->d_name.hash, de->d_name.hash);
++	switch_names(goal, dentry);
++	do_switch(goal->d_parent, dentry->d_parent);
++	do_switch(goal->d_name.len, dentry->d_name.len);
++	do_switch(goal->d_name.hash, dentry->d_name.hash);
 +
 +	/* And add them back to the (new) parent lists */
 +	list_add(&goal->d_child, &goal->d_parent->d_subdirs);
-+	list_add(&de->d_child, &de->d_parent->d_subdirs);
++	list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
 +	__d_rehash(goal, 0);
++	spin_unlock(&dcache_lock);
++	iput(inode);
 +
 +	return goal;
++
++	/* d_add(), but don't drop dcache_lock before adding dentry to inode */
++do_instantiate:
++	list_add(&dentry->d_alias, &inode->i_dentry);	/* d_instantiate */
++	dentry->d_inode = inode;
++do_rehash:
++	if (rehash)
++		__d_rehash(dentry, 0);			/* d_rehash */
++	spin_unlock(&dcache_lock);
++
++	return NULL;
 +}
 +
 +/*
@@ -333,10 +350,10 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +
 +	return 1;
 +}
-Index: linux-2.4.21-chaos/fs/ext3/iopen.h
+Index: linux-ia64/fs/ext3/iopen.h
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/ext3/iopen.h	2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.21-chaos/fs/ext3/iopen.h	2003-12-12 16:19:05.000000000 +0300
+--- linux-ia64.orig/fs/ext3/iopen.h	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/fs/ext3/iopen.h	2004-03-17 18:03:15.000000000 -0800
 @@ -0,0 +1,15 @@
 +/*
 + * iopen.h
@@ -351,12 +368,12 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.h
 +
 +extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
 +extern int ext3_iopen_get_inode(struct inode *inode);
-+extern struct dentry *iopen_connect_dentry(struct dentry *de,
-+					   struct inode *inode);
-Index: linux-2.4.21-chaos/fs/ext3/namei.c
++extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
++					   struct inode *inode, int rehash);
+Index: linux-ia64/fs/ext3/namei.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/ext3/namei.c	2003-12-12 16:18:59.000000000 +0300
-+++ linux-2.4.21-chaos/fs/ext3/namei.c	2003-12-12 16:19:05.000000000 +0300
+--- linux-ia64.orig/fs/ext3/namei.c	2004-03-17 18:03:15.000000000 -0800
++++ linux-ia64/fs/ext3/namei.c	2004-03-17 18:10:35.000000000 -0800
 @@ -36,7 +36,7 @@
  #include <linux/string.h>
  #include <linux/locks.h>
@@ -366,12 +383,7 @@ Index: linux-2.4.21-chaos/fs/ext3/namei.c
  
  /*
   * define how far ahead to read directories while searching them.
-@@ -922,10 +922,14 @@
- 	struct inode * inode;
- 	struct ext3_dir_entry_2 * de;
- 	struct buffer_head * bh;
-+	struct dentry *alternate = NULL;
- 
+@@ -932,6 +932,9 @@ static struct dentry *ext3_lookup(struct
  	if (dentry->d_name.len > EXT3_NAME_LEN)
  		return ERR_PTR(-ENAMETOOLONG);
  
@@ -381,41 +393,67 @@ Index: linux-2.4.21-chaos/fs/ext3/namei.c
  	bh = ext3_find_entry(dentry, &de);
  	inode = NULL;
  	if (bh) {
-@@ -943,7 +948,28 @@
+@@ -943,8 +946,8 @@ static struct dentry *ext3_lookup(struct
  			return ERR_PTR(-EACCES);
  		}
  	}
 -	d_add(dentry, inode);
+-	return NULL;
 +
-+	/* verify this dentry is really new */
-+	assert(!dentry->d_inode);
-+	assert(list_empty(&dentry->d_alias));		/* d_instantiate */
-+	assert(list_empty(&dentry->d_hash));		/* d_rehash */
-+	assert(list_empty(&dentry->d_subdirs));
-+
-+	spin_lock(&dcache_lock);
-+	if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
-+		spin_unlock(&dcache_lock);
-+		iput(inode);
-+		return alternate;
++	return iopen_connect_dentry(dentry, inode, 1);
+ }
+ 
+ #define S_SHIFT 12
+@@ -1935,10 +1938,6 @@ static int ext3_rmdir (struct inode * di
+ 			      inode->i_nlink);
+ 	inode->i_version = ++event;
+ 	inode->i_nlink = 0;
+-	/* There's no need to set i_disksize: the fact that i_nlink is
+-	 * zero will ensure that the right thing happens during any
+-	 * recovery. */
+-	inode->i_size = 0;
+ 	ext3_orphan_add(handle, inode);
+ 	dir->i_nlink--;
+ 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+@@ -2057,6 +2056,23 @@ out_stop:
+ 	return err;
+ }
+ 
++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
++static int ext3_add_link(handle_t *handle, struct dentry *dentry,
++			 struct inode *inode)
++{
++	int err = ext3_add_entry(handle, dentry, inode);
++	if (!err) {
++		err = ext3_mark_inode_dirty(handle, inode);
++		if (err == 0) {
++			(void)iopen_connect_dentry(dentry, inode, 0);
++			return 0;
++		}
 +	}
++	ext3_dec_count(handle, inode);
++	iput(inode);
++	return err;
++}
 +
-+	/* d_add(), but don't drop dcache_lock before adding dentry to inode */
-+	if (inode)					/* d_instantiate */
-+		list_add(&dentry->d_alias, &inode->i_dentry);
-+	dentry->d_inode = inode;
-+
-+	__d_rehash(dentry, 0);				/* d_rehash */
-+	spin_unlock(&dcache_lock);
-+
- 	return NULL;
- }
+ static int ext3_link (struct dentry * old_dentry,
+ 		struct inode * dir, struct dentry *dentry)
+ {
+@@ -2084,7 +2100,8 @@ static int ext3_link (struct dentry * ol
+ 	ext3_inc_count(handle, inode);
+ 	atomic_inc(&inode->i_count);
  
-Index: linux-2.4.21-chaos/fs/ext3/super.c
+-	err = ext3_add_nondir(handle, dentry, inode);
++	err = ext3_add_link(handle, dentry, inode);
++	ext3_orphan_del(handle, inode);
+ 	ext3_journal_stop(handle, dir);
+ 	return err;
+ }
+Index: linux-ia64/fs/ext3/super.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/ext3/super.c	2003-12-12 16:18:51.000000000 +0300
-+++ linux-2.4.21-chaos/fs/ext3/super.c	2003-12-12 16:19:05.000000000 +0300
-@@ -890,6 +890,18 @@
+--- linux-ia64.orig/fs/ext3/super.c	2004-03-17 18:03:14.000000000 -0800
++++ linux-ia64/fs/ext3/super.c	2004-03-17 18:10:35.000000000 -0800
+@@ -891,6 +891,18 @@ static int parse_options (char * options
  		         || !strcmp (this_char, "quota")
  		         || !strcmp (this_char, "usrquota"))
  			/* Don't do anything ;-) */ ;
@@ -434,11 +472,11 @@ Index: linux-2.4.21-chaos/fs/ext3/super.c
  		else if (!strcmp (this_char, "journal")) {
  			/* @@@ FIXME */
  			/* Eventually we will want to be able to create
-Index: linux-2.4.21-chaos/include/linux/ext3_fs.h
+Index: linux-ia64/include/linux/ext3_fs.h
 ===================================================================
---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h	2003-12-12 16:19:01.000000000 +0300
-+++ linux-2.4.21-chaos/include/linux/ext3_fs.h	2003-12-12 16:19:05.000000000 +0300
-@@ -328,6 +328,8 @@
+--- linux-ia64.orig/include/linux/ext3_fs.h	2004-03-17 18:03:15.000000000 -0800
++++ linux-ia64/include/linux/ext3_fs.h	2004-03-17 18:03:15.000000000 -0800
+@@ -328,6 +328,8 @@ struct ext3_inode {
  #define EXT3_MOUNT_XATTR_USER		0x4000	/* Extended user attributes */
  #define EXT3_MOUNT_POSIX_ACL		0x8000	/* POSIX Access Control Lists */
  #define EXT3_MOUNT_ASYNCDEL		0x20000 /* Delayed deletion */
diff --git a/lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch b/lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch
index 79b1f177a52f2f85888287834fb5e4663d5e3aee..550032079343446defb714908be4b846612fc8f8 100644
--- a/lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch
+++ b/lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch
@@ -15,7 +15,7 @@ Index: linux-2.6.3-mm4/Documentation/filesystems/ext2.txt
  
  sb=n				Use alternate superblock at this location.
  
-+iopen				Makes an invisible pseudo-directory called 
++iopen				Makes an invisible pseudo-directory called
 +				__iopen__ available in the root directory
 +				of the filesystem.  Allows open-by-inode-
 +				number.  i.e., inode 3145 can be accessed
@@ -59,16 +59,14 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c
 ===================================================================
 --- linux-2.6.3-mm4.orig/fs/ext3/iopen.c	2004-03-08 14:58:44.413198848 +0800
 +++ linux-2.6.3-mm4/fs/ext3/iopen.c	2004-03-08 14:58:44.576174072 +0800
-@@ -0,0 +1,223 @@
-+
-+
+@@ -0,0 +1,218 @@
 +/*
 + * linux/fs/ext3/iopen.c
 + *
 + * Special support for open by inode number
 + *
 + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ * 
++ *
 + * This file may be redistributed under the terms of the GNU General
 + * Public License.
 + */
@@ -90,12 +88,13 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c
 +/*
 + * This implements looking up an inode by number.
 + */
-+static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
++static struct dentry *iopen_lookup(struct inode *dir, struct dentry *dentry,
++				   struct nameidata *nd)
 +{
 +	struct inode * inode;
 +	unsigned long ino;
-+        struct list_head *lp;
-+        struct dentry *alternate;
++	struct list_head *lp;
++	struct dentry *alternate;
 +	char buf[IOPEN_NAME_LEN];
 +	
 +	if (dentry->d_name.len >= IOPEN_NAME_LEN)
@@ -111,10 +110,7 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c
 +	else
 +		ino = simple_strtoul(buf, 0, 0);
 +
-+	if ((ino != EXT3_ROOT_INO &&
-+	     //ino != EXT3_ACL_IDX_INO &&
-+	     //ino != EXT3_ACL_DATA_INO &&
-+	     ino < EXT3_FIRST_INO(dir->i_sb)) ||
++	if ((ino != EXT3_ROOT_INO && ino < EXT3_FIRST_INO(dir->i_sb)) ||
 +	    ino > le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
 +		return ERR_PTR(-ENOENT);
 +
@@ -126,24 +122,24 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c
 +		return ERR_PTR(-ENOENT);
 +	}
 +
-+        /* preferrably return a connected dentry */
-+        spin_lock(&dcache_lock);
-+        list_for_each(lp, &inode->i_dentry) {
-+                alternate = list_entry(lp, struct dentry, d_alias);
-+                assert(!(alternate->d_flags & DCACHE_DISCONNECTED));
-+        }
-+
-+        if (!list_empty(&inode->i_dentry)) {
-+                alternate = list_entry(inode->i_dentry.next, 
-+                                       struct dentry, d_alias);
-+                dget_locked(alternate);
-+                alternate->d_vfs_flags |= DCACHE_REFERENCED;
-+                iput(inode);
-+                spin_unlock(&dcache_lock);
-+                return alternate;
-+        }
-+        dentry->d_flags |= DCACHE_DISCONNECTED;
-+        spin_unlock(&dcache_lock);
++	/* preferrably return a connected dentry */
++	spin_lock(&dcache_lock);
++	list_for_each(lp, &inode->i_dentry) {
++		alternate = list_entry(lp, struct dentry, d_alias);
++		assert(!(alternate->d_flags & DCACHE_DISCONNECTED));
++	}
++
++	if (!list_empty(&inode->i_dentry)) {
++		alternate = list_entry(inode->i_dentry.next,
++				       struct dentry, d_alias);
++		dget_locked(alternate);
++		alternate->d_vfs_flags |= DCACHE_REFERENCED;
++		iput(inode);
++		spin_unlock(&dcache_lock);
++		return alternate;
++	}
++	dentry->d_flags |= DCACHE_DISCONNECTED;
++	spin_unlock(&dcache_lock);
 +
 +	d_add(dentry, inode);
 +	return NULL;
@@ -157,7 +153,7 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c
 +{
 +	const unsigned char *old_name, *new_name;
 +
-+	memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); 
++	memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
 +	old_name = target->d_name.name;
 +	new_name = dentry->d_name.name;
 +	if (old_name == target->d_iname)
@@ -171,37 +167,36 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c
 +
 +struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
 +{
-+        struct dentry *tmp, *goal = NULL;
-+        struct list_head *lp;
-+
-+        /* preferrably return a connected dentry */
-+        spin_lock(&dcache_lock);
-+        /* verify this dentry is really new */
-+        assert(!de->d_inode);
-+        assert(list_empty(&de->d_subdirs));
-+        assert(list_empty(&de->d_alias));
-+
-+
-+        list_for_each(lp, &inode->i_dentry) {
-+                tmp = list_entry(lp, struct dentry, d_alias);
-+                if (tmp->d_flags & DCACHE_DISCONNECTED) {
-+                        assert(tmp->d_alias.next == &inode->i_dentry);
-+                        assert(tmp->d_alias.prev == &inode->i_dentry);
-+                        goal = tmp;
-+                        dget_locked(goal);
-+                        break;
-+                }
-+        }
-+        spin_unlock(&dcache_lock);
-+
-+        if (!goal)
-+                return NULL; 
-+
-+        goal->d_flags &= ~DCACHE_DISCONNECTED;
++	struct dentry *tmp, *goal = NULL;
++	struct list_head *lp;
++
++	/* preferrably return a connected dentry */
++	spin_lock(&dcache_lock);
++	/* verify this dentry is really new */
++	assert(!de->d_inode);
++	assert(list_empty(&de->d_subdirs));
++	assert(list_empty(&de->d_alias));
++
++	list_for_each(lp, &inode->i_dentry) {
++		tmp = list_entry(lp, struct dentry, d_alias);
++		if (tmp->d_flags & DCACHE_DISCONNECTED) {
++			assert(tmp->d_alias.next == &inode->i_dentry);
++			assert(tmp->d_alias.prev == &inode->i_dentry);
++			goal = tmp;
++			dget_locked(goal);
++			break;
++		}
++	}
++	spin_unlock(&dcache_lock);
++
++	if (!goal)
++		return NULL;
++
++	goal->d_flags &= ~DCACHE_DISCONNECTED;
 +	d_rehash(de);
 +	d_move(goal, de);
 +
-+        return goal;
++	return goal;
 +}
 +
 +/*
@@ -243,7 +238,7 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c
 +
 +	inode = iget(dir->i_sb, EXT3_BAD_INO);
 +
-+	if (!inode) 
++	if (!inode)
 +		return 0;
 +	d_add(dentry, inode);
 +	return 1;
@@ -272,7 +267,7 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c
 +	EXT3_I(inode)->i_dtime = 0;
 +	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size
 +					 * (for stat), not the fs block
-+					 * size */  
++					 * size */
 +	inode->i_blocks = 0;
 +	inode->i_version = 1;
 +	inode->i_generation = 0;
@@ -292,9 +287,9 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.h
 + * iopen.h
 + *
 + * Special support for opening files by inode number.
-+ * 
++ *
 + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ * 
++ *
 + * This file may be redistributed under the terms of the GNU General
 + * Public License.
 + */
@@ -320,13 +315,13 @@ Index: linux-2.6.3-mm4/fs/ext3/namei.c
  #endif
  
 +struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-+ 
++
  static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
  {
  	struct inode * inode;
  	struct ext3_dir_entry_2 * de;
  	struct buffer_head * bh;
-+  	struct dentry *alternate = NULL;
++	struct dentry *alternate = NULL;
  
  	if (dentry->d_name.len > EXT3_NAME_LEN)
  		return ERR_PTR(-ENAMETOOLONG);
diff --git a/lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch b/lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch
index 16e191b4eaec1ebdfafa4efdfdae8dd8de23e416..726957c6615e2380f3b926cc6783d8b4a8a04a5c 100644
--- a/lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch
+++ b/lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch
@@ -5336,7 +5336,7 @@ diff -puN /dev/null include/linux/sunrpc/svcauth_gss.h
 + * Bruce Fields <bfields@umich.edu>
 + * Copyright (c) 2002 The Regents of the Unviersity of Michigan
 + *
-+ * $Id: linux-2.6.3-CITI_NFS4_ALL.patch,v 1.2 2004/03/17 01:04:13 nic Exp $
++ * Id: linux-2.6.3-CITI_NFS4_ALL.patch,v 1.2.4.1 2004/03/17 23:55:23 adilger Exp $
 + *
 + */
 +
diff --git a/lustre/kernel_patches/patches/lustre_version.patch b/lustre/kernel_patches/patches/lustre_version.patch
index 86f514bb8b10f0fb6a145ed2a9debfd14dc5bf69..7ebb838ab51012d718b591e6be54d5c5729993a0 100644
--- a/lustre/kernel_patches/patches/lustre_version.patch
+++ b/lustre/kernel_patches/patches/lustre_version.patch
@@ -7,6 +7,6 @@
 --- /dev/null	Fri Aug 30 17:31:37 2002
 +++ linux-2.4.18-18.8.0-l12-braam/include/linux/lustre_version.h	Thu Feb 13 07:58:33 2003
 @@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 32
++#define LUSTRE_KERNEL_VERSION 34
 
 _
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch
index e29ae29135a234b99e457abe022025e6c95655e9..41c2772442c99e8e9a9fef07cd2f89dfd4b11e30 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch
@@ -467,7 +467,7 @@
 +						  &dentry->d_name, 0, NULL);
 +				d_invalidate(dentry);
 +				dput(dentry);
-+				if (IS_ERR(new)) { 
++				if (IS_ERR(new)) {
 +					err = PTR_ERR(new);
 +					break;
 +				}
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch
index 5fbd0fccef223162d8fbef73a9cc7c60da891a69..7c4ea56ff6be49db994bc594570daa0458e9de13 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch
@@ -453,7 +453,7 @@ Index: linux-2.4.19-pre1/fs/namei.c
 +						  &dentry->d_name, 0, NULL);
 +				d_invalidate(dentry);
 +				dput(dentry);
-+				if (IS_ERR(new)) { 
++				if (IS_ERR(new)) {
 +					err = PTR_ERR(new);
 +					break;
 +				}
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch
index 6b6027a4c6a646841c37d5bfe02bdaf4a8a93985..7741be489ebe9f35c5666b2feb4e17eb12e10151 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch
@@ -436,7 +436,7 @@ Index: linux-2.4.19.SuSE/fs/namei.c
 +						  &dentry->d_name, 0, NULL);
 +				d_invalidate(dentry);
 +				dput(dentry);
-+				if (IS_ERR(new)) { 
++				if (IS_ERR(new)) {
 +					err = PTR_ERR(new);
 +					break;
 +				}
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch
index 082b8b713540657bd30cd97f5e92bd4f50ac6e3f..85857015ca9802a3c072ee057d154ce0c42a5281 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch
@@ -13,9 +13,11 @@
  kernel/ksyms.c            |    1 
  13 files changed, 591 insertions(+), 133 deletions(-)
 
---- linux-2.4.20-hp4-pnnl13/fs/exec.c~vfs_intent-2.4.20-hp	2003-09-13 15:19:27.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/fs/exec.c	2003-09-14 17:33:51.000000000 +0400
-@@ -116,8 +116,10 @@ asmlinkage long sys_uselib(const char * 
+Index: linux/fs/exec.c
+===================================================================
+--- linux.orig/fs/exec.c	Wed Mar 17 13:00:38 2004
++++ linux/fs/exec.c	Wed Mar 17 13:11:25 2004
+@@ -115,8 +115,10 @@
  	struct file * file;
  	struct nameidata nd;
  	int error;
@@ -27,7 +29,7 @@
  	if (error)
  		goto out;
  
-@@ -129,7 +131,8 @@ asmlinkage long sys_uselib(const char * 
+@@ -128,7 +130,8 @@
  	if (error)
  		goto exit;
  
@@ -37,7 +39,7 @@
  	error = PTR_ERR(file);
  	if (IS_ERR(file))
  		goto out;
-@@ -372,8 +375,10 @@ struct file *open_exec(const char *name)
+@@ -371,8 +374,10 @@
  	struct inode *inode;
  	struct file *file;
  	int err = 0;
@@ -49,7 +51,7 @@
  	file = ERR_PTR(err);
  	if (!err) {
  		inode = nd.dentry->d_inode;
-@@ -385,7 +390,8 @@ struct file *open_exec(const char *name)
+@@ -384,7 +389,8 @@
  				err = -EACCES;
  			file = ERR_PTR(err);
  			if (!err) {
@@ -59,7 +61,7 @@
  				if (!IS_ERR(file)) {
  					err = deny_write_access(file);
  					if (err) {
-@@ -397,6 +403,7 @@ out:
+@@ -396,6 +402,7 @@
  				return file;
  			}
  		}
@@ -67,7 +69,7 @@
  		path_release(&nd);
  	}
  	goto out;
-@@ -1128,7 +1135,7 @@ int do_coredump(long signr, struct pt_re
+@@ -1120,7 +1127,7 @@
  		goto close_fail;
  	if (!file->f_op->write)
  		goto close_fail;
@@ -76,9 +78,11 @@
  		goto close_fail;
  
  	retval = binfmt->core_dump(signr, regs, file);
---- linux-2.4.20-hp4-pnnl13/fs/dcache.c~vfs_intent-2.4.20-hp	2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.20-hp4-pnnl13-alexey/fs/dcache.c	2003-09-14 17:33:51.000000000 +0400
-@@ -181,6 +181,13 @@ int d_invalidate(struct dentry * dentry)
+Index: linux/fs/dcache.c
+===================================================================
+--- linux.orig/fs/dcache.c	Thu Nov 28 18:53:15 2002
++++ linux/fs/dcache.c	Wed Mar 17 13:11:25 2004
+@@ -181,6 +181,13 @@
  		spin_unlock(&dcache_lock);
  		return 0;
  	}
@@ -92,7 +96,7 @@
  	/*
  	 * Check whether to do a partial shrink_dcache
  	 * to get rid of unused child entries.
-@@ -830,13 +837,19 @@ void d_delete(struct dentry * dentry)
+@@ -830,13 +837,19 @@
   * Adds a dentry to the hash according to its name.
   */
   
@@ -115,9 +119,11 @@
  }
  
  #define do_switch(x,y) do { \
---- linux-2.4.20-hp4-pnnl13/fs/namespace.c~vfs_intent-2.4.20-hp	2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.20-hp4-pnnl13-alexey/fs/namespace.c	2003-09-14 17:33:51.000000000 +0400
-@@ -99,6 +99,7 @@ static void detach_mnt(struct vfsmount *
+Index: linux/fs/namespace.c
+===================================================================
+--- linux.orig/fs/namespace.c	Thu Nov 28 18:53:15 2002
++++ linux/fs/namespace.c	Wed Mar 17 13:11:25 2004
+@@ -99,6 +99,7 @@
  {
  	old_nd->dentry = mnt->mnt_mountpoint;
  	old_nd->mnt = mnt->mnt_parent;
@@ -125,7 +131,7 @@
  	mnt->mnt_parent = mnt;
  	mnt->mnt_mountpoint = mnt->mnt_root;
  	list_del_init(&mnt->mnt_child);
-@@ -110,6 +111,7 @@ static void attach_mnt(struct vfsmount *
+@@ -110,6 +111,7 @@
  {
  	mnt->mnt_parent = mntget(nd->mnt);
  	mnt->mnt_mountpoint = dget(nd->dentry);
@@ -133,7 +139,7 @@
  	list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
  	list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
  	nd->dentry->d_mounted++;
-@@ -485,14 +487,17 @@ static int do_loopback(struct nameidata 
+@@ -485,14 +487,17 @@
  {
  	struct nameidata old_nd;
  	struct vfsmount *mnt = NULL;
@@ -153,7 +159,7 @@
  
  	down_write(&current->namespace->sem);
  	err = -EINVAL;
-@@ -515,6 +520,7 @@ static int do_loopback(struct nameidata 
+@@ -515,6 +520,7 @@
  	}
  
  	up_write(&current->namespace->sem);
@@ -161,7 +167,7 @@
  	path_release(&old_nd);
  	return err;
  }
-@@ -698,6 +704,7 @@ long do_mount(char * dev_name, char * di
+@@ -698,6 +704,7 @@
  		  unsigned long flags, void *data_page)
  {
  	struct nameidata nd;
@@ -169,7 +175,7 @@
  	int retval = 0;
  	int mnt_flags = 0;
  
-@@ -722,10 +729,11 @@ long do_mount(char * dev_name, char * di
+@@ -722,10 +729,11 @@
  	flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
  
  	/* ... and get the mountpoint */
@@ -184,7 +190,7 @@
  	if (flags & MS_REMOUNT)
  		retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
  				    data_page);
-@@ -736,6 +744,8 @@ long do_mount(char * dev_name, char * di
+@@ -736,6 +744,8 @@
  	else
  		retval = do_add_mount(&nd, type_page, flags, mnt_flags,
  				      dev_name, data_page);
@@ -193,7 +199,7 @@
  	path_release(&nd);
  	return retval;
  }
-@@ -901,6 +911,8 @@ asmlinkage long sys_pivot_root(const cha
+@@ -901,6 +911,8 @@
  {
  	struct vfsmount *tmp;
  	struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
@@ -202,7 +208,7 @@
  	int error;
  
  	if (!capable(CAP_SYS_ADMIN))
-@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha
+@@ -908,14 +920,14 @@
  
  	lock_kernel();
  
@@ -219,7 +225,7 @@
  	if (error)
  		goto out1;
  
-@@ -970,8 +982,10 @@ out2:
+@@ -970,8 +982,10 @@
  	up(&old_nd.dentry->d_inode->i_zombie);
  	up_write(&current->namespace->sem);
  	path_release(&user_nd);
@@ -230,8 +236,10 @@
  	path_release(&new_nd);
  out0:
  	unlock_kernel();
---- linux-2.4.20-hp4-pnnl13/fs/namei.c~vfs_intent-2.4.20-hp	2003-09-13 15:19:23.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/fs/namei.c	2003-09-14 17:33:51.000000000 +0400
+Index: linux/fs/namei.c
+===================================================================
+--- linux.orig/fs/namei.c	Wed Mar 17 13:00:37 2004
++++ linux/fs/namei.c	Wed Mar 17 13:12:31 2004
 @@ -94,6 +94,13 @@
   * XEmacs seems to be relying on it...
   */
@@ -246,7 +254,7 @@
  /* In order to reduce some races, while at the same time doing additional
   * checking and hopefully speeding things up, we copy filenames to the
   * kernel data space before using them..
-@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd)
+@@ -260,10 +267,19 @@
   * Internal lookup() using the new generic dcache.
   * SMP-safe
   */
@@ -267,7 +275,7 @@
  	if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
  		if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
  			dput(dentry);
-@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str
+@@ -281,11 +297,15 @@
   * make sure that nobody added the entry to the dcache in the meantime..
   * SMP-safe
   */
@@ -284,7 +292,7 @@
  	down(&dir->i_sem);
  	/*
  	 * First re-do the cached lookup just in case it was created
-@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc
+@@ -300,6 +320,9 @@
  		result = ERR_PTR(-ENOMEM);
  		if (dentry) {
  			lock_kernel();
@@ -294,7 +302,7 @@
  			result = dir->i_op->lookup(dir, dentry);
  			unlock_kernel();
  			if (result)
-@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc
+@@ -321,6 +344,15 @@
  			dput(result);
  			result = ERR_PTR(-ENOENT);
  		}
@@ -310,7 +318,7 @@
  	}
  	return result;
  }
-@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc
+@@ -332,7 +364,8 @@
   * Without that kind of total limit, nasty chains of consecutive
   * symlinks can cause almost arbitrarily long lookups. 
   */
@@ -320,7 +328,7 @@
  {
  	int err;
  	if (current->link_count >= 5)
-@@ -346,10 +379,18 @@ static inline int do_follow_link(struct 
+@@ -346,10 +379,18 @@
  	current->link_count++;
  	current->total_link_count++;
  	UPDATE_ATIME(dentry->d_inode);
@@ -339,7 +347,7 @@
  	path_release(nd);
  	return -ELOOP;
  }
-@@ -379,15 +420,26 @@ int follow_up(struct vfsmount **mnt, str
+@@ -379,15 +420,26 @@
  	return __follow_up(mnt, dentry);
  }
  
@@ -367,7 +375,7 @@
  		dput(*dentry);
  		mntput(mounted->mnt_parent);
  		*dentry = dget(mounted->mnt_root);
-@@ -399,7 +451,7 @@ static inline int __follow_down(struct v
+@@ -399,7 +451,7 @@
  
  int follow_down(struct vfsmount **mnt, struct dentry **dentry)
  {
@@ -376,7 +384,7 @@
  }
   
  static inline void follow_dotdot(struct nameidata *nd)
-@@ -435,7 +487,7 @@ static inline void follow_dotdot(struct 
+@@ -435,7 +487,7 @@
  		mntput(nd->mnt);
  		nd->mnt = parent;
  	}
@@ -385,7 +393,7 @@
  		;
  }
  
-@@ -447,7 +499,8 @@ static inline void follow_dotdot(struct 
+@@ -447,7 +499,8 @@
   *
   * We expect 'base' to be positive and a directory.
   */
@@ -395,7 +403,7 @@
  {
  	struct dentry *dentry;
  	struct inode *inode;
-@@ -520,15 +573,15 @@ int link_path_walk(const char * name, st
+@@ -520,15 +573,15 @@
  				break;
  		}
  		/* This does the actual lookups.. */
@@ -414,7 +422,7 @@
  			;
  
  		err = -ENOENT;
-@@ -540,7 +593,7 @@ int link_path_walk(const char * name, st
+@@ -540,7 +593,7 @@
  			goto out_dput;
  
  		if (inode->i_op->follow_link) {
@@ -423,7 +431,7 @@
  			dput(dentry);
  			if (err)
  				goto return_err;
-@@ -556,7 +609,7 @@ int link_path_walk(const char * name, st
+@@ -556,7 +609,7 @@
  			nd->dentry = dentry;
  		}
  		err = -ENOTDIR; 
@@ -432,7 +440,7 @@
  			break;
  		continue;
  		/* here ends the main loop */
-@@ -583,19 +636,19 @@ last_component:
+@@ -583,19 +636,19 @@
  			if (err < 0)
  				break;
  		}
@@ -456,7 +464,7 @@
  			dput(dentry);
  			if (err)
  				goto return_err;
-@@ -609,7 +662,8 @@ last_component:
+@@ -609,7 +662,8 @@
  			goto no_inode;
  		if (lookup_flags & LOOKUP_DIRECTORY) {
  			err = -ENOTDIR; 
@@ -466,7 +474,7 @@
  				break;
  		}
  		goto return_base;
-@@ -633,6 +687,25 @@ return_reval:
+@@ -633,6 +687,27 @@
  		 * Check the cached dentry for staleness.
  		 */
  		dentry = nd->dentry;
@@ -482,17 +490,19 @@
 +						  &dentry->d_name, 0, NULL);
 +				d_invalidate(dentry);
 +				dput(dentry);
-+				if (IS_ERR(new)) { 
++				if (IS_ERR(new)) {
 +					err = PTR_ERR(new);
 +					break;
 +				}
 +				nd->dentry = new;
 +			}
++			if (!nd->dentry->d_inode)
++				goto no_inode;
 +		} else
  		if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
  			err = -ESTALE;
  			if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -646,15 +719,28 @@ out_dput:
+@@ -646,15 +721,28 @@
  		dput(dentry);
  		break;
  	}
@@ -522,7 +532,7 @@
  }
  
  /* SMP-safe */
-@@ -739,6 +825,17 @@ walk_init_root(const char *name, struct 
+@@ -739,6 +827,17 @@
  }
  
  /* SMP-safe */
@@ -540,7 +550,7 @@
  int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
  {
  	int error = 0;
-@@ -753,6 +850,7 @@ int path_init(const char *name, unsigned
+@@ -753,6 +852,7 @@
  {
  	nd->last_type = LAST_ROOT; /* if there are only slashes... */
  	nd->flags = flags;
@@ -548,7 +558,7 @@
  	if (*name=='/')
  		return walk_init_root(name,nd);
  	read_lock(&current->fs->lock);
-@@ -767,7 +865,8 @@ int path_init(const char *name, unsigned
+@@ -767,7 +867,8 @@
   * needs parent already locked. Doesn't follow mounts.
   * SMP-safe.
   */
@@ -558,7 +568,7 @@
  {
  	struct dentry * dentry;
  	struct inode *inode;
-@@ -790,13 +889,16 @@ struct dentry * lookup_hash(struct qstr 
+@@ -790,13 +891,16 @@
  			goto out;
  	}
  
@@ -576,7 +586,7 @@
  		dentry = inode->i_op->lookup(inode, new);
  		unlock_kernel();
  		if (!dentry)
-@@ -808,6 +910,12 @@ out:
+@@ -808,6 +912,12 @@
  	return dentry;
  }
  
@@ -589,7 +599,7 @@
  /* SMP-safe */
  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
  {
-@@ -829,7 +937,7 @@ struct dentry * lookup_one_len(const cha
+@@ -829,7 +939,7 @@
  	}
  	this.hash = end_name_hash(hash);
  
@@ -598,7 +608,7 @@
  access:
  	return ERR_PTR(-EACCES);
  }
-@@ -860,6 +968,23 @@ int __user_walk(const char *name, unsign
+@@ -860,6 +970,23 @@
  	return err;
  }
  
@@ -622,7 +632,7 @@
  /*
   * It's inline, so penalty for filesystems that don't use sticky bit is
   * minimal.
-@@ -955,7 +1080,8 @@ static inline int lookup_flags(unsigned 
+@@ -955,7 +1082,8 @@
  	return retval;
  }
  
@@ -632,7 +642,7 @@
  {
  	int error;
  
-@@ -968,12 +1094,15 @@ int vfs_create(struct inode *dir, struct
+@@ -968,12 +1096,15 @@
  		goto exit_lock;
  
  	error = -EACCES;	/* shouldn't it be ENOSYS? */
@@ -650,7 +660,7 @@
  	unlock_kernel();
  exit_lock:
  	up(&dir->i_zombie);
-@@ -982,6 +1111,11 @@ exit_lock:
+@@ -982,6 +1113,11 @@
  	return error;
  }
  
@@ -662,7 +672,7 @@
  /*
   *	open_namei()
   *
-@@ -996,7 +1130,8 @@ exit_lock:
+@@ -996,7 +1132,8 @@
   * for symlinks (where the permissions are checked later).
   * SMP-safe
   */
@@ -672,7 +682,7 @@
  {
  	int acc_mode, error = 0;
  	struct inode *inode;
-@@ -1006,11 +1141,14 @@ int open_namei(const char * pathname, in
+@@ -1006,11 +1143,14 @@
  
  	acc_mode = ACC_MODE(flag);
  
@@ -688,7 +698,7 @@
  		if (error)
  			return error;
  		dentry = nd->dentry;
-@@ -1020,6 +1158,10 @@ int open_namei(const char * pathname, in
+@@ -1020,6 +1160,10 @@
  	/*
  	 * Create - we need to know the parent.
  	 */
@@ -699,7 +709,7 @@
  	error = path_lookup(pathname, LOOKUP_PARENT, nd);
  	if (error)
  		return error;
-@@ -1035,7 +1177,7 @@ int open_namei(const char * pathname, in
+@@ -1035,7 +1179,7 @@
  
  	dir = nd->dentry;
  	down(&dir->d_inode->i_sem);
@@ -708,7 +718,7 @@
  
  do_last:
  	error = PTR_ERR(dentry);
-@@ -1044,11 +1186,12 @@ do_last:
+@@ -1044,11 +1188,12 @@
  		goto exit;
  	}
  
@@ -722,7 +732,7 @@
  		up(&dir->d_inode->i_sem);
  		dput(nd->dentry);
  		nd->dentry = dentry;
-@@ -1073,7 +1216,7 @@ do_last:
+@@ -1073,7 +1218,7 @@
  		error = -ELOOP;
  		if (flag & O_NOFOLLOW)
  			goto exit_dput;
@@ -731,7 +741,7 @@
  	}
  	error = -ENOENT;
  	if (!dentry->d_inode)
-@@ -1152,7 +1295,7 @@ ok:
+@@ -1152,7 +1297,7 @@
  		if (!error) {
  			DQUOT_INIT(inode);
  			
@@ -740,7 +750,7 @@
  		}
  		put_write_access(inode);
  		if (error)
-@@ -1164,8 +1307,10 @@ ok:
+@@ -1164,8 +1309,10 @@
  	return 0;
  
  exit_dput:
@@ -751,7 +761,7 @@
  	path_release(nd);
  	return error;
  
-@@ -1184,7 +1329,16 @@ do_link:
+@@ -1184,7 +1331,16 @@
  	 * are done. Procfs-like symlinks just set LAST_BIND.
  	 */
  	UPDATE_ATIME(dentry->d_inode);
@@ -768,7 +778,7 @@
  	dput(dentry);
  	if (error)
  		return error;
-@@ -1206,13 +1360,20 @@ do_link:
+@@ -1206,13 +1362,20 @@
  	}
  	dir = nd->dentry;
  	down(&dir->d_inode->i_sem);
@@ -791,7 +801,7 @@
  {
  	struct dentry *dentry;
  
-@@ -1220,7 +1381,7 @@ static struct dentry *lookup_create(stru
+@@ -1220,7 +1383,7 @@
  	dentry = ERR_PTR(-EEXIST);
  	if (nd->last_type != LAST_NORM)
  		goto fail;
@@ -800,12 +810,16 @@
  	if (IS_ERR(dentry))
  		goto fail;
  	if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1276,7 +1437,16 @@ asmlinkage long sys_mknod(const char * f
+@@ -1276,7 +1439,20 @@
  	error = path_lookup(tmp, LOOKUP_PARENT, &nd);
  	if (error)
  		goto out;
 -	dentry = lookup_create(&nd, 0);
 +
++	if (nd.last_type != LAST_NORM) {
++		error = -EEXIST;
++		goto out2;
++	}
 +	if (nd.dentry->d_inode->i_op->mknod_raw) {
 +		struct inode_operations *op = nd.dentry->d_inode->i_op;
 +		error = op->mknod_raw(&nd, mode, dev);
@@ -818,7 +832,7 @@
  	error = PTR_ERR(dentry);
  
  	if (!IS_POSIXACL(nd.dentry->d_inode))
-@@ -1298,6 +1468,7 @@ asmlinkage long sys_mknod(const char * f
+@@ -1298,6 +1474,7 @@
  		dput(dentry);
  	}
  	up(&nd.dentry->d_inode->i_sem);
@@ -826,11 +840,15 @@
  	path_release(&nd);
  out:
  	putname(tmp);
-@@ -1345,7 +1516,14 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1345,7 +1522,18 @@
  		error = path_lookup(tmp, LOOKUP_PARENT, &nd);
  		if (error)
  			goto out;
 -		dentry = lookup_create(&nd, 1);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out2;
++		}
 +		if (nd.dentry->d_inode->i_op->mkdir_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->mkdir_raw(&nd, mode);
@@ -842,7 +860,7 @@
  		error = PTR_ERR(dentry);
  		if (!IS_ERR(dentry)) {
  			if (!IS_POSIXACL(nd.dentry->d_inode))
-@@ -1354,6 +1532,7 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1354,6 +1542,7 @@
  			dput(dentry);
  		}
  		up(&nd.dentry->d_inode->i_sem);
@@ -850,7 +868,7 @@
  		path_release(&nd);
  out:
  		putname(tmp);
-@@ -1454,8 +1633,16 @@ asmlinkage long sys_rmdir(const char * p
+@@ -1454,8 +1643,16 @@
  			error = -EBUSY;
  			goto exit1;
  	}
@@ -868,7 +886,7 @@
  	error = PTR_ERR(dentry);
  	if (!IS_ERR(dentry)) {
  		error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1513,8 +1700,15 @@ asmlinkage long sys_unlink(const char * 
+@@ -1513,8 +1710,15 @@
  	error = -EISDIR;
  	if (nd.last_type != LAST_NORM)
  		goto exit1;
@@ -885,11 +903,15 @@
  	error = PTR_ERR(dentry);
  	if (!IS_ERR(dentry)) {
  		/* Why not before? Because we want correct error value */
-@@ -1581,15 +1775,23 @@ asmlinkage long sys_symlink(const char *
+@@ -1581,15 +1785,27 @@
  		error = path_lookup(to, LOOKUP_PARENT, &nd);
  		if (error)
  			goto out;
 -		dentry = lookup_create(&nd, 0);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out2;
++		}
 +		if (nd.dentry->d_inode->i_op->symlink_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->symlink_raw(&nd, from);
@@ -911,11 +933,15 @@
  		putname(to);
  	}
  	putname(from);
-@@ -1665,7 +1867,14 @@ asmlinkage long sys_link(const char * ol
+@@ -1665,7 +1881,18 @@
  		error = -EXDEV;
  		if (old_nd.mnt != nd.mnt)
  			goto out_release;
 -		new_dentry = lookup_create(&nd, 0);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out_release;
++		}
 +		if (nd.dentry->d_inode->i_op->link_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->link_raw(&old_nd, &nd);
@@ -927,7 +953,7 @@
  		error = PTR_ERR(new_dentry);
  		if (!IS_ERR(new_dentry)) {
  			error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1709,7 +1918,7 @@ exit:
+@@ -1709,7 +1936,7 @@
   *	   locking].
   */
  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
@@ -936,7 +962,7 @@
  {
  	int error;
  	struct inode *target;
-@@ -1788,7 +1997,7 @@ out_unlock:
+@@ -1788,7 +2015,7 @@
  }
  
  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
@@ -945,7 +971,7 @@
  {
  	int error;
  
-@@ -1876,9 +2085,18 @@ static inline int do_rename(const char *
+@@ -1876,9 +2103,18 @@
  	if (newnd.last_type != LAST_NORM)
  		goto exit2;
  
@@ -965,7 +991,7 @@
  	error = PTR_ERR(old_dentry);
  	if (IS_ERR(old_dentry))
  		goto exit3;
-@@ -1894,16 +2112,16 @@ static inline int do_rename(const char *
+@@ -1894,16 +2130,16 @@
  		if (newnd.last.name[newnd.last.len])
  			goto exit4;
  	}
@@ -984,7 +1010,7 @@
  	dput(new_dentry);
  exit4:
  	dput(old_dentry);
-@@ -1954,20 +2172,28 @@ out:
+@@ -1954,20 +2190,28 @@
  }
  
  static inline int
@@ -1015,7 +1041,7 @@
  out:
  	if (current->link_count || res || nd->last_type!=LAST_NORM)
  		return res;
-@@ -1989,7 +2215,13 @@ fail:
+@@ -1989,7 +2233,13 @@
  
  int vfs_follow_link(struct nameidata *nd, const char *link)
  {
@@ -1030,7 +1056,7 @@
  }
  
  /* get the link contents into pagecache */
-@@ -2031,7 +2263,7 @@ int page_follow_link(struct dentry *dent
+@@ -2031,7 +2281,7 @@
  {
  	struct page *page = NULL;
  	char *s = page_getlink(dentry, &page);
@@ -1039,8 +1065,10 @@
  	if (page) {
  		kunmap(page);
  		page_cache_release(page);
---- linux-2.4.20-hp4-pnnl13/fs/open.c~vfs_intent-2.4.20-hp	2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.20-hp4-pnnl13-alexey/fs/open.c	2003-09-14 17:33:51.000000000 +0400
+Index: linux/fs/open.c
+===================================================================
+--- linux.orig/fs/open.c	Thu Nov 28 18:53:15 2002
++++ linux/fs/open.c	Wed Mar 17 13:11:25 2004
 @@ -19,6 +19,8 @@
  #include <asm/uaccess.h>
  
@@ -1050,7 +1078,7 @@
  
  int vfs_statfs(struct super_block *sb, struct statfs *buf)
  {
-@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct 
+@@ -95,9 +97,10 @@
  	write_unlock(&files->file_lock);
  }
  
@@ -1062,7 +1090,7 @@
  	int error;
  	struct iattr newattrs;
  
-@@ -108,7 +111,13 @@ int do_truncate(struct dentry *dentry, l
+@@ -108,7 +111,13 @@
  	down(&inode->i_sem);
  	newattrs.ia_size = length;
  	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
@@ -1077,7 +1105,7 @@
  	up(&inode->i_sem);
  	return error;
  }
-@@ -118,12 +127,13 @@ static inline long do_sys_truncate(const
+@@ -118,12 +127,13 @@
  	struct nameidata nd;
  	struct inode * inode;
  	int error;
@@ -1092,7 +1120,7 @@
  	if (error)
  		goto out;
  	inode = nd.dentry->d_inode;
-@@ -163,11 +173,13 @@ static inline long do_sys_truncate(const
+@@ -163,11 +173,13 @@
  	error = locks_verify_truncate(inode, NULL, length);
  	if (!error) {
  		DQUOT_INIT(inode);
@@ -1107,7 +1135,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -215,7 +227,7 @@ static inline long do_sys_ftruncate(unsi
+@@ -215,7 +227,7 @@
  
  	error = locks_verify_truncate(inode, file, length);
  	if (!error)
@@ -1116,7 +1144,7 @@
  out_putf:
  	fput(file);
  out:
-@@ -260,11 +272,13 @@ asmlinkage long sys_utime(char * filenam
+@@ -260,11 +272,13 @@
  	struct inode * inode;
  	struct iattr newattrs;
  
@@ -1131,7 +1159,7 @@
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto dput_and_out;
-@@ -279,11 +293,25 @@ asmlinkage long sys_utime(char * filenam
+@@ -279,11 +293,25 @@
  			goto dput_and_out;
  
  		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1158,7 +1186,7 @@
  	error = notify_change(nd.dentry, &newattrs);
  dput_and_out:
  	path_release(&nd);
-@@ -304,12 +332,14 @@ asmlinkage long sys_utimes(char * filena
+@@ -304,12 +332,14 @@
  	struct inode * inode;
  	struct iattr newattrs;
  
@@ -1174,7 +1202,7 @@
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto dput_and_out;
-@@ -324,7 +354,20 @@ asmlinkage long sys_utimes(char * filena
+@@ -324,7 +354,20 @@
  		newattrs.ia_atime = times[0].tv_sec;
  		newattrs.ia_mtime = times[1].tv_sec;
  		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1196,7 +1224,7 @@
  		if (current->fsuid != inode->i_uid &&
  		    (error = permission(inode,MAY_WRITE)) != 0)
  			goto dput_and_out;
-@@ -347,6 +390,7 @@ asmlinkage long sys_access(const char * 
+@@ -347,6 +390,7 @@
  	int old_fsuid, old_fsgid;
  	kernel_cap_t old_cap;
  	int res;
@@ -1204,7 +1232,7 @@
  
  	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
  		return -EINVAL;
-@@ -364,13 +408,14 @@ asmlinkage long sys_access(const char * 
+@@ -364,13 +408,14 @@
  	else
  		current->cap_effective = current->cap_permitted;
  
@@ -1220,7 +1248,7 @@
  		path_release(&nd);
  	}
  
-@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f
+@@ -385,8 +430,9 @@
  {
  	int error;
  	struct nameidata nd;
@@ -1231,7 +1259,7 @@
  	if (error)
  		goto out;
  
-@@ -397,6 +443,7 @@ asmlinkage long sys_chdir(const char * f
+@@ -397,6 +443,7 @@
  	set_fs_pwd(current->fs, nd.mnt, nd.dentry);
  
  dput_and_out:
@@ -1239,7 +1267,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -436,9 +483,10 @@ asmlinkage long sys_chroot(const char * 
+@@ -436,9 +483,10 @@
  {
  	int error;
  	struct nameidata nd;
@@ -1252,7 +1280,7 @@
  	if (error)
  		goto out;
  
-@@ -454,39 +502,56 @@ asmlinkage long sys_chroot(const char * 
+@@ -454,39 +502,56 @@
  	set_fs_altroot();
  	error = 0;
  dput_and_out:
@@ -1323,7 +1351,7 @@
  	fput(file);
  out:
  	return err;
-@@ -495,30 +560,14 @@ out:
+@@ -495,30 +560,14 @@
  asmlinkage long sys_chmod(const char * filename, mode_t mode)
  {
  	struct nameidata nd;
@@ -1355,7 +1383,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -538,6 +587,20 @@ static int chown_common(struct dentry * 
+@@ -538,6 +587,20 @@
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto out;
@@ -1376,7 +1404,7 @@
  	error = -EPERM;
  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out;
-@@ -642,6 +705,7 @@ struct file *filp_open(const char * file
+@@ -642,6 +705,7 @@
  {
  	int namei_flags, error;
  	struct nameidata nd;
@@ -1384,7 +1412,7 @@
  
  	namei_flags = flags;
  	if ((namei_flags+1) & O_ACCMODE)
-@@ -649,14 +713,15 @@ struct file *filp_open(const char * file
+@@ -649,14 +713,15 @@
  	if (namei_flags & O_TRUNC)
  		namei_flags |= 2;
  
@@ -1405,7 +1433,7 @@
  {
  	struct file * f;
  	struct inode *inode;
-@@ -693,12 +758,15 @@ struct file *dentry_open(struct dentry *
+@@ -693,12 +758,15 @@
  	}
  
  	if (f->f_op && f->f_op->open) {
@@ -1421,7 +1449,7 @@
  	return f;
  
  cleanup_all:
-@@ -713,11 +781,17 @@ cleanup_all:
+@@ -713,11 +781,17 @@
  cleanup_file:
  	put_filp(f);
  cleanup_dentry:
@@ -1439,9 +1467,11 @@
  /*
   * Find an empty file descriptor entry, and mark it busy.
   */
---- linux-2.4.20-hp4-pnnl13/fs/stat.c~vfs_intent-2.4.20-hp	2001-09-14 03:04:43.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/fs/stat.c	2003-09-14 17:34:07.000000000 +0400
-@@ -17,10 +17,14 @@
+Index: linux/fs/stat.c
+===================================================================
+--- linux.orig/fs/stat.c	Thu Sep 13 19:04:43 2001
++++ linux/fs/stat.c	Wed Mar 17 13:12:31 2004
+@@ -17,10 +17,12 @@
   * Revalidate the inode. This is required for proper NFS attribute caching.
   */
  static __inline__ int
@@ -1450,15 +1480,13 @@
  {
  	struct inode * inode = dentry->d_inode;
 -	if (inode->i_op && inode->i_op->revalidate)
-+	if (!inode)
-+		return -ENOENT;
 +	if (inode->i_op && inode->i_op->revalidate_it)
 +		return inode->i_op->revalidate_it(dentry, it);
 +	else if (inode->i_op && inode->i_op->revalidate)
  		return inode->i_op->revalidate(dentry);
  	return 0;
  }
-@@ -135,13 +139,15 @@ static int cp_new_stat(struct inode * in
+@@ -135,13 +137,15 @@
  asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
  {
  	struct nameidata nd;
@@ -1476,7 +1504,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -151,13 +157,15 @@ asmlinkage long sys_stat(char * filename
+@@ -151,13 +155,15 @@
  asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
  {
  	struct nameidata nd;
@@ -1494,7 +1522,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -172,13 +180,15 @@ asmlinkage long sys_newstat(char * filen
+@@ -172,13 +178,15 @@
  asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
  {
  	struct nameidata nd;
@@ -1512,7 +1540,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -189,13 +199,15 @@ asmlinkage long sys_lstat(char * filenam
+@@ -189,13 +197,15 @@
  asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
  {
  	struct nameidata nd;
@@ -1530,7 +1558,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -216,7 +228,7 @@ asmlinkage long sys_fstat(unsigned int f
+@@ -216,7 +226,7 @@
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1539,7 +1567,7 @@
  		if (!err)
  			err = cp_old_stat(dentry->d_inode, statbuf);
  		fput(f);
-@@ -235,7 +247,7 @@ asmlinkage long sys_newfstat(unsigned in
+@@ -235,7 +245,7 @@
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1548,7 +1576,7 @@
  		if (!err)
  			err = cp_new_stat(dentry->d_inode, statbuf);
  		fput(f);
-@@ -257,7 +269,7 @@ asmlinkage long sys_readlink(const char 
+@@ -257,7 +267,7 @@
  
  		error = -EINVAL;
  		if (inode->i_op && inode->i_op->readlink &&
@@ -1557,7 +1585,7 @@
  			UPDATE_ATIME(inode);
  			error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
  		}
-@@ -333,12 +345,14 @@ asmlinkage long sys_stat64(char * filena
+@@ -333,12 +343,14 @@
  {
  	struct nameidata nd;
  	int error;
@@ -1574,7 +1602,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -348,12 +362,14 @@ asmlinkage long sys_lstat64(char * filen
+@@ -348,12 +360,14 @@
  {
  	struct nameidata nd;
  	int error;
@@ -1591,7 +1619,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -368,7 +384,7 @@ asmlinkage long sys_fstat64(unsigned lon
+@@ -368,7 +382,7 @@
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1600,9 +1628,11 @@
  		if (!err)
  			err = cp_new_stat64(dentry->d_inode, statbuf);
  		fput(f);
---- linux-2.4.20-hp4-pnnl13/fs/proc/base.c~vfs_intent-2.4.20-hp	2003-09-13 15:19:19.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/fs/proc/base.c	2003-09-14 17:33:51.000000000 +0400
-@@ -481,6 +481,9 @@ static int proc_pid_follow_link(struct d
+Index: linux/fs/proc/base.c
+===================================================================
+--- linux.orig/fs/proc/base.c	Wed Mar 17 13:00:35 2004
++++ linux/fs/proc/base.c	Wed Mar 17 13:11:25 2004
+@@ -481,6 +481,9 @@
  
  	error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
  	nd->last_type = LAST_BIND;
@@ -1612,8 +1642,10 @@
  out:
  	return error;
  }
---- linux-2.4.20-hp4-pnnl13/include/linux/dcache.h~vfs_intent-2.4.20-hp	2002-11-29 02:53:15.000000000 +0300
-+++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/dcache.h	2003-09-14 17:33:51.000000000 +0400
+Index: linux/include/linux/dcache.h
+===================================================================
+--- linux.orig/include/linux/dcache.h	Thu Nov 28 18:53:15 2002
++++ linux/include/linux/dcache.h	Wed Mar 17 13:11:25 2004
 @@ -6,6 +6,51 @@
  #include <asm/atomic.h>
  #include <linux/mount.h>
@@ -1666,7 +1698,7 @@
  
  /*
   * linux/include/linux/dcache.h
-@@ -91,8 +136,22 @@ struct dentry_operations {
+@@ -91,8 +136,22 @@
  	int (*d_delete)(struct dentry *);
  	void (*d_release)(struct dentry *);
  	void (*d_iput)(struct dentry *, struct inode *);
@@ -1689,7 +1721,7 @@
  /* the dentry parameter passed to d_hash and d_compare is the parent
   * directory of the entries to be compared. It is used in case these
   * functions need any directory specific information for determining
-@@ -124,6 +183,7 @@ d_iput:		no		no		yes
+@@ -124,6 +183,7 @@
  					 * s_nfsd_free_path semaphore will be down
  					 */
  #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
@@ -1697,9 +1729,11 @@
  
  extern spinlock_t dcache_lock;
  
---- linux-2.4.20-hp4-pnnl13/include/linux/fs.h~vfs_intent-2.4.20-hp	2003-09-14 17:33:50.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/fs.h	2003-09-14 17:33:51.000000000 +0400
-@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena
+Index: linux/include/linux/fs.h
+===================================================================
+--- linux.orig/include/linux/fs.h	Wed Mar 17 13:11:23 2004
++++ linux/include/linux/fs.h	Wed Mar 17 13:11:31 2004
+@@ -73,6 +73,7 @@
  
  #define FMODE_READ 1
  #define FMODE_WRITE 2
@@ -1707,7 +1741,7 @@
  
  #define READ 0
  #define WRITE 1
-@@ -340,6 +341,9 @@ extern void set_bh_page(struct buffer_he
+@@ -340,6 +341,9 @@
  #define ATTR_MTIME_SET	256
  #define ATTR_FORCE	512	/* Not a change, but a change it */
  #define ATTR_ATTR_FLAG	1024
@@ -1717,7 +1751,7 @@
  
  /*
   * This is the Inode Attributes structure, used for notify_change().  It
-@@ -474,6 +478,7 @@ struct inode {
+@@ -474,6 +478,7 @@
  	struct pipe_inode_info	*i_pipe;
  	struct block_device	*i_bdev;
  	struct char_device	*i_cdev;
@@ -1725,7 +1759,7 @@
  
  	unsigned long		i_dnotify_mask; /* Directory notify events */
  	struct dnotify_struct	*i_dnotify; /* for directory notifications */
-@@ -576,6 +581,7 @@ struct file {
+@@ -576,6 +581,7 @@
  
  	/* needed for tty driver, and maybe others */
  	void			*private_data;
@@ -1733,7 +1767,7 @@
  
  	/* preallocated helper kiobuf to speedup O_DIRECT */
  	struct kiobuf		*f_iobuf;
-@@ -697,6 +703,7 @@ struct nameidata {
+@@ -697,6 +703,7 @@
  	struct qstr last;
  	unsigned int flags;
  	int last_type;
@@ -1741,7 +1775,7 @@
  };
  
  /*
-@@ -817,7 +824,8 @@ extern int vfs_symlink(struct inode *, s
+@@ -817,7 +824,8 @@
  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
  extern int vfs_rmdir(struct inode *, struct dentry *);
  extern int vfs_unlink(struct inode *, struct dentry *);
@@ -1751,7 +1785,7 @@
  
  /*
   * File types
-@@ -877,21 +885,32 @@ struct file_operations {
+@@ -877,21 +885,32 @@
  
  struct inode_operations {
  	int (*create) (struct inode *,struct dentry *,int);
@@ -1784,7 +1818,7 @@
  	int (*getattr) (struct dentry *, struct iattr *);
  	int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
  	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -1088,10 +1107,14 @@ static inline int get_lease(struct inode
+@@ -1088,10 +1107,14 @@
  
  asmlinkage long sys_open(const char *, int, int);
  asmlinkage long sys_close(unsigned int);	/* yes, it's really unsigned */
@@ -1800,7 +1834,7 @@
  extern int filp_close(struct file *, fl_owner_t id);
  extern char * getname(const char *);
  
-@@ -1353,6 +1376,7 @@ typedef int (*read_actor_t)(read_descrip
+@@ -1354,6 +1377,7 @@
  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
  
  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
@@ -1808,7 +1842,7 @@
  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
  extern int FASTCALL(path_walk(const char *, struct nameidata *));
  extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1364,6 +1388,8 @@ extern struct dentry * lookup_one_len(co
+@@ -1365,6 +1389,8 @@
  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
  #define user_path_walk(name,nd)	 __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
@@ -1816,8 +1850,8 @@
 +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
  
  extern void inode_init_once(struct inode *);
- extern void iput(struct inode *);
-@@ -1499,6 +1525,8 @@ extern struct file_operations generic_ro
+ extern void _inode_init_once(struct inode *);
+@@ -1503,6 +1529,8 @@
  
  extern int vfs_readlink(struct dentry *, char *, int, const char *);
  extern int vfs_follow_link(struct nameidata *, const char *);
@@ -1826,9 +1860,11 @@
  extern int page_readlink(struct dentry *, char *, int);
  extern int page_follow_link(struct dentry *, struct nameidata *);
  extern struct inode_operations page_symlink_inode_operations;
---- linux-2.4.20-hp4-pnnl13/include/linux/fs_struct.h~vfs_intent-2.4.20-hp	2001-07-14 02:10:44.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/fs_struct.h	2003-09-14 17:33:51.000000000 +0400
-@@ -34,10 +34,12 @@ static inline void set_fs_root(struct fs
+Index: linux/include/linux/fs_struct.h
+===================================================================
+--- linux.orig/include/linux/fs_struct.h	Fri Jul 13 18:10:44 2001
++++ linux/include/linux/fs_struct.h	Wed Mar 17 13:11:25 2004
+@@ -34,10 +34,12 @@
  	write_lock(&fs->lock);
  	old_root = fs->root;
  	old_rootmnt = fs->rootmnt;
@@ -1841,7 +1877,7 @@
  		dput(old_root);
  		mntput(old_rootmnt);
  	}
-@@ -57,10 +59,12 @@ static inline void set_fs_pwd(struct fs_
+@@ -57,10 +59,12 @@
  	write_lock(&fs->lock);
  	old_pwd = fs->pwd;
  	old_pwdmnt = fs->pwdmnt;
@@ -1854,9 +1890,11 @@
  		dput(old_pwd);
  		mntput(old_pwdmnt);
  	}
---- linux-2.4.20-hp4-pnnl13/kernel/ksyms.c~vfs_intent-2.4.20-hp	2003-09-14 17:33:50.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/kernel/ksyms.c	2003-09-14 17:33:51.000000000 +0400
-@@ -296,6 +296,7 @@ EXPORT_SYMBOL(read_cache_page);
+Index: linux/kernel/ksyms.c
+===================================================================
+--- linux.orig/kernel/ksyms.c	Wed Mar 17 13:11:23 2004
++++ linux/kernel/ksyms.c	Wed Mar 17 13:11:25 2004
+@@ -315,6 +315,7 @@
  EXPORT_SYMBOL(set_page_dirty);
  EXPORT_SYMBOL(vfs_readlink);
  EXPORT_SYMBOL(vfs_follow_link);
@@ -1864,9 +1902,11 @@
  EXPORT_SYMBOL(page_readlink);
  EXPORT_SYMBOL(page_follow_link);
  EXPORT_SYMBOL(page_symlink_inode_operations);
---- linux-2.4.20-hp4-pnnl13/kernel/fork.c~vfs_intent-2.4.20-hp	2003-09-13 15:19:27.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/kernel/fork.c	2003-09-14 17:33:51.000000000 +0400
-@@ -388,10 +388,13 @@ static inline struct fs_struct *__copy_f
+Index: linux/kernel/fork.c
+===================================================================
+--- linux.orig/kernel/fork.c	Wed Mar 17 13:00:38 2004
++++ linux/kernel/fork.c	Wed Mar 17 13:11:25 2004
+@@ -387,10 +387,13 @@
  		fs->umask = old->umask;
  		read_lock(&old->lock);
  		fs->rootmnt = mntget(old->rootmnt);
@@ -1880,9 +1920,11 @@
  			fs->altrootmnt = mntget(old->altrootmnt);
  			fs->altroot = dget(old->altroot);
  		} else {
---- linux-2.4.20-hp4-pnnl13/kernel/exit.c~vfs_intent-2.4.20-hp	2003-09-13 15:19:27.000000000 +0400
-+++ linux-2.4.20-hp4-pnnl13-alexey/kernel/exit.c	2003-09-14 17:33:51.000000000 +0400
-@@ -239,11 +239,14 @@ static inline void __put_fs_struct(struc
+Index: linux/kernel/exit.c
+===================================================================
+--- linux.orig/kernel/exit.c	Wed Mar 17 13:00:38 2004
++++ linux/kernel/exit.c	Wed Mar 17 13:11:25 2004
+@@ -239,11 +239,14 @@
  {
  	/* No need to hold fs->lock if we are killing it */
  	if (atomic_dec_and_test(&fs->count)) {
@@ -1897,5 +1939,3 @@
  			dput(fs->altroot);
  			mntput(fs->altrootmnt);
  		}
-
-_
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch
index f9096db9eb73f579debc8042d268e303c8bb1ee7..409c8f0b79c2850b7fac19c96d31b4f895ce6262 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch
@@ -13,9 +13,11 @@
  kernel/ksyms.c            |    1 
  13 files changed, 578 insertions(+), 129 deletions(-)
 
---- linux-2.4.20-rh-20.9/fs/dcache.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/dcache.c	2003-09-14 17:34:53.000000000 +0400
-@@ -186,6 +186,13 @@ int d_invalidate(struct dentry * dentry)
+Index: linux-2.4.20/fs/dcache.c
+===================================================================
+--- linux-2.4.20.orig/fs/dcache.c	Wed Mar 17 13:57:05 2004
++++ linux-2.4.20/fs/dcache.c	Wed Mar 17 13:57:11 2004
+@@ -186,6 +186,13 @@
  		spin_unlock(&dcache_lock);
  		return 0;
  	}
@@ -29,7 +31,7 @@
  	/*
  	 * Check whether to do a partial shrink_dcache
  	 * to get rid of unused child entries.
-@@ -841,13 +848,19 @@ void d_delete(struct dentry * dentry)
+@@ -841,13 +848,19 @@
   * Adds a dentry to the hash according to its name.
   */
   
@@ -52,9 +54,11 @@
  }
  
  #define do_switch(x,y) do { \
---- linux-2.4.20-rh-20.9/fs/exec.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/exec.c	2003-09-14 17:34:53.000000000 +0400
-@@ -114,8 +114,10 @@ asmlinkage long sys_uselib(const char * 
+Index: linux-2.4.20/fs/exec.c
+===================================================================
+--- linux-2.4.20.orig/fs/exec.c	Wed Mar 17 13:57:05 2004
++++ linux-2.4.20/fs/exec.c	Wed Mar 17 13:57:11 2004
+@@ -114,8 +114,10 @@
  	struct file * file;
  	struct nameidata nd;
  	int error;
@@ -66,7 +70,7 @@
  	if (error)
  		goto out;
  
-@@ -127,7 +129,8 @@ asmlinkage long sys_uselib(const char * 
+@@ -127,7 +129,8 @@
  	if (error)
  		goto exit;
  
@@ -76,7 +80,7 @@
  	error = PTR_ERR(file);
  	if (IS_ERR(file))
  		goto out;
-@@ -382,8 +385,10 @@ struct file *open_exec(const char *name)
+@@ -382,8 +385,10 @@
  	struct inode *inode;
  	struct file *file;
  	int err = 0;
@@ -88,7 +92,7 @@
  	file = ERR_PTR(err);
  	if (!err) {
  		inode = nd.dentry->d_inode;
-@@ -395,7 +400,8 @@ struct file *open_exec(const char *name)
+@@ -395,7 +400,8 @@
  				err = -EACCES;
  			file = ERR_PTR(err);
  			if (!err) {
@@ -98,7 +102,7 @@
  				if (!IS_ERR(file)) {
  					err = deny_write_access(file);
  					if (err) {
-@@ -407,6 +413,7 @@ out:
+@@ -407,6 +413,7 @@
  				return file;
  			}
  		}
@@ -106,7 +110,7 @@
  		path_release(&nd);
  	}
  	goto out;
-@@ -1296,7 +1303,7 @@ int do_coredump(long signr, int exit_cod
+@@ -1296,7 +1303,7 @@
  		goto close_fail;
  	if (!file->f_op->write)
  		goto close_fail;
@@ -115,8 +119,10 @@
  		goto close_fail;
  
  	retval = binfmt->core_dump(signr, regs, file);
---- linux-2.4.20-rh-20.9/fs/namei.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:25.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/namei.c	2003-09-14 17:34:53.000000000 +0400
+Index: linux-2.4.20/fs/namei.c
+===================================================================
+--- linux-2.4.20.orig/fs/namei.c	Wed Mar 17 13:57:03 2004
++++ linux-2.4.20/fs/namei.c	Wed Mar 17 13:58:01 2004
 @@ -94,6 +94,13 @@
   * XEmacs seems to be relying on it...
   */
@@ -131,7 +137,7 @@
  /* In order to reduce some races, while at the same time doing additional
   * checking and hopefully speeding things up, we copy filenames to the
   * kernel data space before using them..
-@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd)
+@@ -260,10 +267,19 @@
   * Internal lookup() using the new generic dcache.
   * SMP-safe
   */
@@ -152,7 +158,7 @@
  	if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
  		if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
  			dput(dentry);
-@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str
+@@ -281,11 +297,15 @@
   * make sure that nobody added the entry to the dcache in the meantime..
   * SMP-safe
   */
@@ -169,7 +175,7 @@
  	down(&dir->i_sem);
  	/*
  	 * First re-do the cached lookup just in case it was created
-@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc
+@@ -300,6 +320,9 @@
  		result = ERR_PTR(-ENOMEM);
  		if (dentry) {
  			lock_kernel();
@@ -179,7 +185,7 @@
  			result = dir->i_op->lookup(dir, dentry);
  			unlock_kernel();
  			if (result)
-@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc
+@@ -321,6 +344,15 @@
  			dput(result);
  			result = ERR_PTR(-ENOENT);
  		}
@@ -195,7 +201,7 @@
  	}
  	return result;
  }
-@@ -334,7 +366,8 @@ int max_recursive_link = 5;
+@@ -334,7 +366,8 @@
   * Without that kind of total limit, nasty chains of consecutive
   * symlinks can cause almost arbitrarily long lookups. 
   */
@@ -205,7 +211,7 @@
  {
  	int err;
  	if (current->link_count >= max_recursive_link)
-@@ -348,10 +381,18 @@ static inline int do_follow_link(struct 
+@@ -348,10 +381,18 @@
  	current->link_count++;
  	current->total_link_count++;
  	UPDATE_ATIME(dentry->d_inode);
@@ -224,7 +230,7 @@
  	path_release(nd);
  	return -ELOOP;
  }
-@@ -381,15 +422,26 @@ int follow_up(struct vfsmount **mnt, str
+@@ -381,15 +422,26 @@
  	return __follow_up(mnt, dentry);
  }
  
@@ -252,7 +258,7 @@
  		dput(*dentry);
  		mntput(mounted->mnt_parent);
  		*dentry = dget(mounted->mnt_root);
-@@ -401,7 +453,7 @@ static inline int __follow_down(struct v
+@@ -401,7 +453,7 @@
  
  int follow_down(struct vfsmount **mnt, struct dentry **dentry)
  {
@@ -261,7 +267,7 @@
  }
   
  static inline void follow_dotdot(struct nameidata *nd)
-@@ -437,7 +489,7 @@ static inline void follow_dotdot(struct 
+@@ -437,7 +489,7 @@
  		mntput(nd->mnt);
  		nd->mnt = parent;
  	}
@@ -270,7 +276,7 @@
  		;
  }
  
-@@ -449,7 +501,8 @@ static inline void follow_dotdot(struct 
+@@ -449,7 +501,8 @@
   *
   * We expect 'base' to be positive and a directory.
   */
@@ -280,7 +286,7 @@
  {
  	struct dentry *dentry;
  	struct inode *inode;
-@@ -526,19 +579,18 @@ int link_path_walk(const char * name, st
+@@ -526,19 +579,18 @@
  				break;
  		}
  		/* This does the actual lookups.. */
@@ -303,7 +309,7 @@
  
  		err = -ENOENT;
  		inode = dentry->d_inode;
-@@ -549,7 +601,7 @@ int link_path_walk(const char * name, st
+@@ -549,7 +601,7 @@
  			goto out_dput;
  
  		if (inode->i_op->follow_link) {
@@ -312,7 +318,7 @@
  			dput(dentry);
  			if (err)
  				goto return_err;
-@@ -565,7 +617,7 @@ int link_path_walk(const char * name, st
+@@ -565,7 +617,7 @@
  			nd->dentry = dentry;
  		}
  		err = -ENOTDIR; 
@@ -321,7 +327,7 @@
  			break;
  		continue;
  		/* here ends the main loop */
-@@ -592,22 +644,22 @@ last_component:
+@@ -592,22 +644,22 @@
  			if (err < 0)
  				break;
  		}
@@ -348,7 +354,7 @@
  			dput(dentry);
  			if (err)
  				goto return_err;
-@@ -621,7 +673,8 @@ last_component:
+@@ -621,7 +673,8 @@
  			goto no_inode;
  		if (lookup_flags & LOOKUP_DIRECTORY) {
  			err = -ENOTDIR; 
@@ -358,7 +364,7 @@
  				break;
  		}
  		goto return_base;
-@@ -645,6 +698,25 @@ return_reval:
+@@ -645,6 +698,27 @@
  		 * Check the cached dentry for staleness.
  		 */
  		dentry = nd->dentry;
@@ -380,11 +386,13 @@
 +				}
 +				nd->dentry = new;
 +			}
++			if (!nd->dentry->d_inode)
++				goto no_inode;
 +		} else
  		if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
  			err = -ESTALE;
  			if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -658,15 +730,28 @@ out_dput:
+@@ -658,15 +732,28 @@
  		dput(dentry);
  		break;
  	}
@@ -414,7 +422,7 @@
  }
  
  /* SMP-safe */
-@@ -751,6 +836,17 @@ walk_init_root(const char *name, struct 
+@@ -751,6 +838,17 @@
  }
  
  /* SMP-safe */
@@ -432,7 +440,7 @@
  int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
  {
  	int error = 0;
-@@ -765,6 +861,7 @@ int path_init(const char *name, unsigned
+@@ -765,6 +863,7 @@
  {
  	nd->last_type = LAST_ROOT; /* if there are only slashes... */
  	nd->flags = flags;
@@ -440,7 +448,7 @@
  	if (*name=='/')
  		return walk_init_root(name,nd);
  	read_lock(&current->fs->lock);
-@@ -779,7 +876,8 @@ int path_init(const char *name, unsigned
+@@ -779,7 +878,8 @@
   * needs parent already locked. Doesn't follow mounts.
   * SMP-safe.
   */
@@ -450,7 +458,7 @@
  {
  	struct dentry * dentry;
  	struct inode *inode;
-@@ -802,13 +900,16 @@ struct dentry * lookup_hash(struct qstr 
+@@ -802,13 +902,16 @@
  			goto out;
  	}
  
@@ -468,7 +476,7 @@
  		dentry = inode->i_op->lookup(inode, new);
  		unlock_kernel();
  		if (!dentry)
-@@ -820,6 +921,12 @@ out:
+@@ -820,6 +923,12 @@
  	return dentry;
  }
  
@@ -481,7 +489,7 @@
  /* SMP-safe */
  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
  {
-@@ -841,7 +948,7 @@ struct dentry * lookup_one_len(const cha
+@@ -841,7 +950,7 @@
  	}
  	this.hash = end_name_hash(hash);
  
@@ -490,7 +498,7 @@
  access:
  	return ERR_PTR(-EACCES);
  }
-@@ -872,6 +979,23 @@ int __user_walk(const char *name, unsign
+@@ -872,6 +981,23 @@
  	return err;
  }
  
@@ -514,7 +522,7 @@
  /*
   * It's inline, so penalty for filesystems that don't use sticky bit is
   * minimal.
-@@ -969,7 +1093,8 @@ static inline int lookup_flags(unsigned 
+@@ -969,7 +1095,8 @@
  	return retval;
  }
  
@@ -524,7 +532,7 @@
  {
  	int error;
  
-@@ -982,12 +1107,15 @@ int vfs_create(struct inode *dir, struct
+@@ -982,12 +1109,15 @@
  		goto exit_lock;
  
  	error = -EACCES;	/* shouldn't it be ENOSYS? */
@@ -542,7 +550,7 @@
  	unlock_kernel();
  exit_lock:
  	up(&dir->i_zombie);
-@@ -996,6 +1124,11 @@ exit_lock:
+@@ -996,6 +1126,11 @@
  	return error;
  }
  
@@ -554,7 +562,7 @@
  /*
   *	open_namei()
   *
-@@ -1010,7 +1143,8 @@ exit_lock:
+@@ -1010,7 +1145,8 @@
   * for symlinks (where the permissions are checked later).
   * SMP-safe
   */
@@ -564,7 +572,7 @@
  {
  	int acc_mode, error = 0;
  	struct inode *inode;
-@@ -1020,11 +1154,14 @@ int open_namei(const char * pathname, in
+@@ -1020,11 +1156,14 @@
  
  	acc_mode = ACC_MODE(flag);
  
@@ -580,7 +588,7 @@
  		if (error)
  			return error;
  		dentry = nd->dentry;
-@@ -1034,6 +1171,10 @@ int open_namei(const char * pathname, in
+@@ -1034,6 +1173,10 @@
  	/*
  	 * Create - we need to know the parent.
  	 */
@@ -591,7 +599,7 @@
  	error = path_lookup(pathname, LOOKUP_PARENT, nd);
  	if (error)
  		return error;
-@@ -1049,7 +1190,7 @@ int open_namei(const char * pathname, in
+@@ -1049,7 +1192,7 @@
  
  	dir = nd->dentry;
  	down(&dir->d_inode->i_sem);
@@ -600,7 +608,7 @@
  
  do_last:
  	error = PTR_ERR(dentry);
-@@ -1058,10 +1199,11 @@ do_last:
+@@ -1058,10 +1201,11 @@
  		goto exit;
  	}
  
@@ -614,7 +622,7 @@
  		up(&dir->d_inode->i_sem);
  		dput(nd->dentry);
  		nd->dentry = dentry;
-@@ -1086,7 +1228,7 @@ do_last:
+@@ -1086,7 +1230,7 @@
  		error = -ELOOP;
  		if (flag & O_NOFOLLOW)
  			goto exit_dput;
@@ -623,7 +631,7 @@
  	}
  	error = -ENOENT;
  	if (!dentry->d_inode)
-@@ -1165,7 +1307,7 @@ ok:
+@@ -1165,7 +1309,7 @@
  		if (!error) {
  			DQUOT_INIT(inode);
  			
@@ -632,7 +640,7 @@
  		}
  		put_write_access(inode);
  		if (error)
-@@ -1177,8 +1319,10 @@ ok:
+@@ -1177,8 +1321,10 @@
  	return 0;
  
  exit_dput:
@@ -643,7 +651,7 @@
  	path_release(nd);
  	return error;
  
-@@ -1197,7 +1341,16 @@ do_link:
+@@ -1197,7 +1343,16 @@
  	 * are done. Procfs-like symlinks just set LAST_BIND.
  	 */
  	UPDATE_ATIME(dentry->d_inode);
@@ -660,7 +668,7 @@
  	dput(dentry);
  	if (error)
  		return error;
-@@ -1219,13 +1372,20 @@ do_link:
+@@ -1219,13 +1374,20 @@
  	}
  	dir = nd->dentry;
  	down(&dir->d_inode->i_sem);
@@ -683,7 +691,7 @@
  {
  	struct dentry *dentry;
  
-@@ -1233,7 +1393,7 @@ static struct dentry *lookup_create(stru
+@@ -1233,7 +1395,7 @@
  	dentry = ERR_PTR(-EEXIST);
  	if (nd->last_type != LAST_NORM)
  		goto fail;
@@ -692,12 +700,16 @@
  	if (IS_ERR(dentry))
  		goto fail;
  	if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1289,7 +1449,16 @@ asmlinkage long sys_mknod(const char * f
+@@ -1289,7 +1451,20 @@
  	error = path_lookup(tmp, LOOKUP_PARENT, &nd);
  	if (error)
  		goto out;
 -	dentry = lookup_create(&nd, 0);
 +
++	if (nd.last_type != LAST_NORM) {
++		error = -EEXIST;
++		goto out2;
++	}
 +	if (nd.dentry->d_inode->i_op->mknod_raw) {
 +		struct inode_operations *op = nd.dentry->d_inode->i_op;
 +		error = op->mknod_raw(&nd, mode, dev);
@@ -710,7 +722,7 @@
  	error = PTR_ERR(dentry);
  
  	mode &= ~current->fs->umask;
-@@ -1310,6 +1479,7 @@ asmlinkage long sys_mknod(const char * f
+@@ -1310,6 +1485,7 @@
  		dput(dentry);
  	}
  	up(&nd.dentry->d_inode->i_sem);
@@ -718,11 +730,15 @@
  	path_release(&nd);
  out:
  	putname(tmp);
-@@ -1357,7 +1527,14 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1357,7 +1533,18 @@
  		error = path_lookup(tmp, LOOKUP_PARENT, &nd);
  		if (error)
  			goto out;
 -		dentry = lookup_create(&nd, 1);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out2;
++		}
 +		if (nd.dentry->d_inode->i_op->mkdir_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->mkdir_raw(&nd, mode);
@@ -734,7 +750,7 @@
  		error = PTR_ERR(dentry);
  		if (!IS_ERR(dentry)) {
  			error = vfs_mkdir(nd.dentry->d_inode, dentry,
-@@ -1365,6 +1542,7 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1365,6 +1552,7 @@
  			dput(dentry);
  		}
  		up(&nd.dentry->d_inode->i_sem);
@@ -742,7 +758,7 @@
  		path_release(&nd);
  out:
  		putname(tmp);
-@@ -1465,8 +1643,16 @@ asmlinkage long sys_rmdir(const char * p
+@@ -1465,8 +1653,16 @@
  			error = -EBUSY;
  			goto exit1;
  	}
@@ -760,7 +776,7 @@
  	error = PTR_ERR(dentry);
  	if (!IS_ERR(dentry)) {
  		error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1524,8 +1710,15 @@ asmlinkage long sys_unlink(const char * 
+@@ -1524,8 +1720,15 @@
  	error = -EISDIR;
  	if (nd.last_type != LAST_NORM)
  		goto exit1;
@@ -777,11 +793,15 @@
  	error = PTR_ERR(dentry);
  	if (!IS_ERR(dentry)) {
  		/* Why not before? Because we want correct error value */
-@@ -1592,15 +1785,23 @@ asmlinkage long sys_symlink(const char *
+@@ -1592,15 +1795,27 @@
  		error = path_lookup(to, LOOKUP_PARENT, &nd);
  		if (error)
  			goto out;
 -		dentry = lookup_create(&nd, 0);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out2;
++		}
 +		if (nd.dentry->d_inode->i_op->symlink_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->symlink_raw(&nd, from);
@@ -803,11 +823,15 @@
  		putname(to);
  	}
  	putname(from);
-@@ -1676,7 +1877,14 @@ asmlinkage long sys_link(const char * ol
+@@ -1676,7 +1891,18 @@
  		error = -EXDEV;
  		if (old_nd.mnt != nd.mnt)
  			goto out_release;
 -		new_dentry = lookup_create(&nd, 0);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out_release;
++		}
 +		if (nd.dentry->d_inode->i_op->link_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->link_raw(&old_nd, &nd);
@@ -819,7 +843,7 @@
  		error = PTR_ERR(new_dentry);
  		if (!IS_ERR(new_dentry)) {
  			error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1720,7 +1928,7 @@ exit:
+@@ -1720,7 +1946,7 @@
   *	   locking].
   */
  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
@@ -828,7 +852,7 @@
  {
  	int error;
  	struct inode *target;
-@@ -1799,7 +2007,7 @@ out_unlock:
+@@ -1799,7 +2025,7 @@
  }
  
  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
@@ -837,7 +861,7 @@
  {
  	int error;
  
-@@ -1887,9 +2095,18 @@ static inline int do_rename(const char *
+@@ -1887,9 +2113,18 @@
  	if (newnd.last_type != LAST_NORM)
  		goto exit2;
  
@@ -857,7 +881,7 @@
  	error = PTR_ERR(old_dentry);
  	if (IS_ERR(old_dentry))
  		goto exit3;
-@@ -1905,16 +2122,16 @@ static inline int do_rename(const char *
+@@ -1905,16 +2140,16 @@
  		if (newnd.last.name[newnd.last.len])
  			goto exit4;
  	}
@@ -876,7 +900,7 @@
  	dput(new_dentry);
  exit4:
  	dput(old_dentry);
-@@ -1965,20 +2182,28 @@ out:
+@@ -1965,20 +2200,28 @@
  }
  
  static inline int
@@ -907,7 +931,7 @@
  out:
  	if (current->link_count || res || nd->last_type!=LAST_NORM)
  		return res;
-@@ -2002,7 +2227,13 @@ fail:
+@@ -2002,7 +2245,13 @@
  
  int vfs_follow_link(struct nameidata *nd, const char *link)
  {
@@ -922,7 +946,7 @@
  }
  
  /* get the link contents into pagecache */
-@@ -2044,7 +2275,7 @@ int page_follow_link(struct dentry *dent
+@@ -2044,7 +2293,7 @@
  {
  	struct page *page = NULL;
  	char *s = page_getlink(dentry, &page);
@@ -931,9 +955,11 @@
  	if (page) {
  		kunmap(page);
  		page_cache_release(page);
---- linux-2.4.20-rh-20.9/fs/namespace.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/namespace.c	2003-09-14 17:34:53.000000000 +0400
-@@ -99,6 +99,7 @@ static void detach_mnt(struct vfsmount *
+Index: linux-2.4.20/fs/namespace.c
+===================================================================
+--- linux-2.4.20.orig/fs/namespace.c	Wed Mar 17 13:57:05 2004
++++ linux-2.4.20/fs/namespace.c	Wed Mar 17 13:57:11 2004
+@@ -99,6 +99,7 @@
  {
  	old_nd->dentry = mnt->mnt_mountpoint;
  	old_nd->mnt = mnt->mnt_parent;
@@ -941,7 +967,7 @@
  	mnt->mnt_parent = mnt;
  	mnt->mnt_mountpoint = mnt->mnt_root;
  	list_del_init(&mnt->mnt_child);
-@@ -110,6 +111,7 @@ static void attach_mnt(struct vfsmount *
+@@ -110,6 +111,7 @@
  {
  	mnt->mnt_parent = mntget(nd->mnt);
  	mnt->mnt_mountpoint = dget(nd->dentry);
@@ -949,7 +975,7 @@
  	list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
  	list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
  	nd->dentry->d_mounted++;
-@@ -485,14 +487,17 @@ static int do_loopback(struct nameidata 
+@@ -485,14 +487,17 @@
  {
  	struct nameidata old_nd;
  	struct vfsmount *mnt = NULL;
@@ -969,7 +995,7 @@
  
  	down_write(&current->namespace->sem);
  	err = -EINVAL;
-@@ -515,6 +520,7 @@ static int do_loopback(struct nameidata 
+@@ -515,6 +520,7 @@
  	}
  
  	up_write(&current->namespace->sem);
@@ -977,7 +1003,7 @@
  	path_release(&old_nd);
  	return err;
  }
-@@ -698,6 +704,7 @@ long do_mount(char * dev_name, char * di
+@@ -698,6 +704,7 @@
  		  unsigned long flags, void *data_page)
  {
  	struct nameidata nd;
@@ -985,7 +1011,7 @@
  	int retval = 0;
  	int mnt_flags = 0;
  
-@@ -722,10 +729,11 @@ long do_mount(char * dev_name, char * di
+@@ -722,10 +729,11 @@
  	flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
  
  	/* ... and get the mountpoint */
@@ -1000,7 +1026,7 @@
  	if (flags & MS_REMOUNT)
  		retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
  				    data_page);
-@@ -736,6 +744,8 @@ long do_mount(char * dev_name, char * di
+@@ -736,6 +744,8 @@
  	else
  		retval = do_add_mount(&nd, type_page, flags, mnt_flags,
  				      dev_name, data_page);
@@ -1009,7 +1035,7 @@
  	path_release(&nd);
  	return retval;
  }
-@@ -901,6 +911,8 @@ asmlinkage long sys_pivot_root(const cha
+@@ -901,6 +911,8 @@
  {
  	struct vfsmount *tmp;
  	struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
@@ -1018,7 +1044,7 @@
  	int error;
  
  	if (!capable(CAP_SYS_ADMIN))
-@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha
+@@ -908,14 +920,14 @@
  
  	lock_kernel();
  
@@ -1035,7 +1061,7 @@
  	if (error)
  		goto out1;
  
-@@ -970,8 +982,10 @@ out2:
+@@ -970,8 +982,10 @@
  	up(&old_nd.dentry->d_inode->i_zombie);
  	up_write(&current->namespace->sem);
  	path_release(&user_nd);
@@ -1046,8 +1072,10 @@
  	path_release(&new_nd);
  out0:
  	unlock_kernel();
---- linux-2.4.20-rh-20.9/fs/open.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:25.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/open.c	2003-09-14 17:34:53.000000000 +0400
+Index: linux-2.4.20/fs/open.c
+===================================================================
+--- linux-2.4.20.orig/fs/open.c	Wed Mar 17 13:57:03 2004
++++ linux-2.4.20/fs/open.c	Wed Mar 17 13:57:11 2004
 @@ -19,6 +19,8 @@
  #include <asm/uaccess.h>
  
@@ -1057,7 +1085,7 @@
  
  int vfs_statfs(struct super_block *sb, struct statfs *buf)
  {
-@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct 
+@@ -95,9 +97,10 @@
  	write_unlock(&files->file_lock);
  }
  
@@ -1069,7 +1097,7 @@
  	int error;
  	struct iattr newattrs;
  
-@@ -108,7 +111,13 @@ int do_truncate(struct dentry *dentry, l
+@@ -108,7 +111,13 @@
  	down(&inode->i_sem);
  	newattrs.ia_size = length;
  	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
@@ -1084,7 +1112,7 @@
  	up(&inode->i_sem);
  	return error;
  }
-@@ -118,12 +127,13 @@ static inline long do_sys_truncate(const
+@@ -118,12 +127,13 @@
  	struct nameidata nd;
  	struct inode * inode;
  	int error;
@@ -1099,7 +1127,7 @@
  	if (error)
  		goto out;
  	inode = nd.dentry->d_inode;
-@@ -163,11 +173,13 @@ static inline long do_sys_truncate(const
+@@ -163,11 +173,13 @@
  	error = locks_verify_truncate(inode, NULL, length);
  	if (!error) {
  		DQUOT_INIT(inode);
@@ -1114,7 +1142,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -215,7 +227,7 @@ static inline long do_sys_ftruncate(unsi
+@@ -215,7 +227,7 @@
  
  	error = locks_verify_truncate(inode, file, length);
  	if (!error)
@@ -1123,7 +1151,7 @@
  out_putf:
  	fput(file);
  out:
-@@ -260,11 +272,13 @@ asmlinkage long sys_utime(char * filenam
+@@ -260,11 +272,13 @@
  	struct inode * inode;
  	struct iattr newattrs;
  
@@ -1138,7 +1166,7 @@
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto dput_and_out;
-@@ -279,11 +293,25 @@ asmlinkage long sys_utime(char * filenam
+@@ -279,11 +293,25 @@
  			goto dput_and_out;
  
  		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1165,7 +1193,7 @@
  	error = notify_change(nd.dentry, &newattrs);
  dput_and_out:
  	path_release(&nd);
-@@ -304,12 +332,14 @@ asmlinkage long sys_utimes(char * filena
+@@ -304,12 +332,14 @@
  	struct inode * inode;
  	struct iattr newattrs;
  
@@ -1181,7 +1209,7 @@
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto dput_and_out;
-@@ -324,7 +354,20 @@ asmlinkage long sys_utimes(char * filena
+@@ -324,7 +354,20 @@
  		newattrs.ia_atime = times[0].tv_sec;
  		newattrs.ia_mtime = times[1].tv_sec;
  		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1203,7 +1231,7 @@
  		if (current->fsuid != inode->i_uid &&
  		    (error = permission(inode,MAY_WRITE)) != 0)
  			goto dput_and_out;
-@@ -347,6 +390,7 @@ asmlinkage long sys_access(const char * 
+@@ -347,6 +390,7 @@
  	int old_fsuid, old_fsgid;
  	kernel_cap_t old_cap;
  	int res;
@@ -1211,7 +1239,7 @@
  
  	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
  		return -EINVAL;
-@@ -364,13 +408,14 @@ asmlinkage long sys_access(const char * 
+@@ -364,13 +408,14 @@
  	else
  		current->cap_effective = current->cap_permitted;
  
@@ -1227,7 +1255,7 @@
  		path_release(&nd);
  	}
  
-@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f
+@@ -385,8 +430,9 @@
  {
  	int error;
  	struct nameidata nd;
@@ -1238,7 +1266,7 @@
  	if (error)
  		goto out;
  
-@@ -397,6 +443,7 @@ asmlinkage long sys_chdir(const char * f
+@@ -397,6 +443,7 @@
  	set_fs_pwd(current->fs, nd.mnt, nd.dentry);
  
  dput_and_out:
@@ -1246,7 +1274,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -436,9 +483,10 @@ asmlinkage long sys_chroot(const char * 
+@@ -436,9 +483,10 @@
  {
  	int error;
  	struct nameidata nd;
@@ -1259,7 +1287,7 @@
  	if (error)
  		goto out;
  
-@@ -454,39 +502,56 @@ asmlinkage long sys_chroot(const char * 
+@@ -454,39 +502,56 @@
  	set_fs_altroot();
  	error = 0;
  dput_and_out:
@@ -1330,7 +1358,7 @@
  	fput(file);
  out:
  	return err;
-@@ -495,30 +560,14 @@ out:
+@@ -495,30 +560,14 @@
  asmlinkage long sys_chmod(const char * filename, mode_t mode)
  {
  	struct nameidata nd;
@@ -1362,7 +1390,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -538,6 +587,20 @@ static int chown_common(struct dentry * 
+@@ -538,6 +587,20 @@
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto out;
@@ -1383,7 +1411,7 @@
  	error = -EPERM;
  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out;
-@@ -642,8 +705,9 @@ struct file *filp_open(const char * file
+@@ -642,8 +705,9 @@
  {
  	int namei_flags, error;
  	struct nameidata nd;
@@ -1395,7 +1423,7 @@
  
  	namei_flags = flags;
  	if ((namei_flags+1) & O_ACCMODE)
-@@ -651,14 +715,15 @@ struct file *filp_open(const char * file
+@@ -651,14 +715,15 @@
  	if (namei_flags & O_TRUNC)
  		namei_flags |= 2;
  
@@ -1416,7 +1444,7 @@
  {
  	struct file * f;
  	struct inode *inode;
-@@ -695,12 +760,15 @@ struct file *dentry_open(struct dentry *
+@@ -695,12 +760,15 @@
  	}
  
  	if (f->f_op && f->f_op->open) {
@@ -1432,7 +1460,7 @@
  	return f;
  
  cleanup_all:
-@@ -715,11 +783,17 @@ cleanup_all:
+@@ -715,11 +783,17 @@
  cleanup_file:
  	put_filp(f);
  cleanup_dentry:
@@ -1450,9 +1478,11 @@
  /*
   * Find an empty file descriptor entry, and mark it busy.
   */
---- linux-2.4.20-rh-20.9/fs/proc/base.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/proc/base.c	2003-09-14 17:34:53.000000000 +0400
-@@ -494,6 +494,9 @@ static int proc_pid_follow_link(struct d
+Index: linux-2.4.20/fs/proc/base.c
+===================================================================
+--- linux-2.4.20.orig/fs/proc/base.c	Wed Mar 17 13:57:05 2004
++++ linux-2.4.20/fs/proc/base.c	Wed Mar 17 13:57:11 2004
+@@ -494,6 +494,9 @@
  
  	error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
  	nd->last_type = LAST_BIND;
@@ -1462,9 +1492,11 @@
  out:
  	return error;
  }
---- linux-2.4.20-rh-20.9/fs/stat.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/fs/stat.c	2003-09-14 17:35:10.000000000 +0400
-@@ -17,10 +17,14 @@
+Index: linux-2.4.20/fs/stat.c
+===================================================================
+--- linux-2.4.20.orig/fs/stat.c	Wed Mar 17 13:57:05 2004
++++ linux-2.4.20/fs/stat.c	Wed Mar 17 13:58:01 2004
+@@ -17,10 +17,12 @@
   * Revalidate the inode. This is required for proper NFS attribute caching.
   */
  static __inline__ int
@@ -1473,15 +1505,13 @@
  {
  	struct inode * inode = dentry->d_inode;
 -	if (inode->i_op && inode->i_op->revalidate)
-+	if (!inode)
-+		return -ENOENT;
 +	if (inode->i_op && inode->i_op->revalidate_it)
 +		return inode->i_op->revalidate_it(dentry, it);
 +	else if (inode->i_op && inode->i_op->revalidate)
  		return inode->i_op->revalidate(dentry);
  	return 0;
  }
-@@ -32,13 +36,13 @@ static inline nlink_t user_nlink(struct 
+@@ -32,13 +34,13 @@
  	return inode->i_nlink;
  }
  
@@ -1497,7 +1527,7 @@
  	if (res)
  		return res;
  
-@@ -111,10 +115,12 @@ int vfs_stat(char *name, struct kstat *s
+@@ -111,10 +113,12 @@
  {
  	struct nameidata nd;
  	int error;
@@ -1512,7 +1542,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -124,10 +130,12 @@ int vfs_lstat(char *name, struct kstat *
+@@ -124,10 +128,12 @@
  {
  	struct nameidata nd;
  	int error;
@@ -1527,7 +1557,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -139,7 +147,7 @@ int vfs_fstat(unsigned int fd, struct ks
+@@ -139,7 +145,7 @@
  	int error = -EBADF;
  
  	if (f) {
@@ -1536,7 +1566,7 @@
  		fput(f);
  	}
  	return error;
-@@ -286,7 +294,7 @@ asmlinkage long sys_readlink(const char 
+@@ -286,7 +292,7 @@
  
  		error = -EINVAL;
  		if (inode->i_op && inode->i_op->readlink &&
@@ -1545,8 +1575,10 @@
  			UPDATE_ATIME(inode);
  			error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
  		}
---- linux-2.4.20-rh-20.9/include/linux/dcache.h~vfs_intent-2.4.20-rh	2003-09-13 19:34:28.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/include/linux/dcache.h	2003-09-14 17:34:53.000000000 +0400
+Index: linux-2.4.20/include/linux/dcache.h
+===================================================================
+--- linux-2.4.20.orig/include/linux/dcache.h	Wed Mar 17 13:57:04 2004
++++ linux-2.4.20/include/linux/dcache.h	Wed Mar 17 13:57:11 2004
 @@ -6,6 +6,51 @@
  #include <asm/atomic.h>
  #include <linux/mount.h>
@@ -1599,7 +1631,7 @@
  
  /*
   * linux/include/linux/dcache.h
-@@ -96,8 +141,22 @@ struct dentry_operations {
+@@ -96,8 +141,22 @@
  	int (*d_delete)(struct dentry *);
  	void (*d_release)(struct dentry *);
  	void (*d_iput)(struct dentry *, struct inode *);
@@ -1622,7 +1654,7 @@
  /* the dentry parameter passed to d_hash and d_compare is the parent
   * directory of the entries to be compared. It is used in case these
   * functions need any directory specific information for determining
-@@ -129,6 +188,7 @@ d_iput:		no		no		yes
+@@ -129,6 +188,7 @@
  					 * s_nfsd_free_path semaphore will be down
  					 */
  #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
@@ -1630,9 +1662,11 @@
  
  extern spinlock_t dcache_lock;
  
---- linux-2.4.20-rh-20.9/include/linux/fs.h~vfs_intent-2.4.20-rh	2003-09-14 17:34:50.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/include/linux/fs.h	2003-09-14 17:34:53.000000000 +0400
-@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena
+Index: linux-2.4.20/include/linux/fs.h
+===================================================================
+--- linux-2.4.20.orig/include/linux/fs.h	Wed Mar 17 13:57:11 2004
++++ linux-2.4.20/include/linux/fs.h	Wed Mar 17 13:57:11 2004
+@@ -73,6 +73,7 @@
  
  #define FMODE_READ 1
  #define FMODE_WRITE 2
@@ -1640,7 +1674,7 @@
  
  #define READ 0
  #define WRITE 1
-@@ -338,6 +339,9 @@ extern void set_bh_page(struct buffer_he
+@@ -338,6 +339,9 @@
  #define ATTR_MTIME_SET	256
  #define ATTR_FORCE	512	/* Not a change, but a change it */
  #define ATTR_ATTR_FLAG	1024
@@ -1650,7 +1684,7 @@
  
  /*
   * This is the Inode Attributes structure, used for notify_change().  It
-@@ -473,6 +477,7 @@ struct inode {
+@@ -473,6 +477,7 @@
  	struct pipe_inode_info	*i_pipe;
  	struct block_device	*i_bdev;
  	struct char_device	*i_cdev;
@@ -1658,7 +1692,7 @@
  
  	unsigned long		i_dnotify_mask; /* Directory notify events */
  	struct dnotify_struct	*i_dnotify; /* for directory notifications */
-@@ -575,6 +580,7 @@ struct file {
+@@ -575,6 +580,7 @@
  
  	/* needed for tty driver, and maybe others */
  	void			*private_data;
@@ -1666,7 +1700,7 @@
  
  	/* preallocated helper kiobuf to speedup O_DIRECT */
  	struct kiobuf		*f_iobuf;
-@@ -702,6 +708,7 @@ struct nameidata {
+@@ -702,6 +708,7 @@
  	struct qstr last;
  	unsigned int flags;
  	int last_type;
@@ -1674,7 +1708,7 @@
  };
  
  /*
-@@ -822,7 +829,8 @@ extern int vfs_symlink(struct inode *, s
+@@ -822,7 +829,8 @@
  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
  extern int vfs_rmdir(struct inode *, struct dentry *);
  extern int vfs_unlink(struct inode *, struct dentry *);
@@ -1684,7 +1718,7 @@
  
  /*
   * File types
-@@ -882,21 +890,32 @@ struct file_operations {
+@@ -882,21 +890,32 @@
  
  struct inode_operations {
  	int (*create) (struct inode *,struct dentry *,int);
@@ -1717,7 +1751,7 @@
  	int (*getattr) (struct dentry *, struct iattr *);
  	int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
  	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -1092,10 +1111,14 @@ static inline int get_lease(struct inode
+@@ -1092,10 +1111,14 @@
  
  asmlinkage long sys_open(const char *, int, int);
  asmlinkage long sys_close(unsigned int);	/* yes, it's really unsigned */
@@ -1733,7 +1767,7 @@
  extern int filp_close(struct file *, fl_owner_t id);
  extern char * getname(const char *);
  
-@@ -1386,6 +1409,7 @@ typedef int (*read_actor_t)(read_descrip
+@@ -1386,6 +1409,7 @@
  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
  
  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
@@ -1741,7 +1775,7 @@
  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
  extern int FASTCALL(path_walk(const char *, struct nameidata *));
  extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1397,6 +1421,8 @@ extern struct dentry * lookup_one_len(co
+@@ -1397,6 +1421,8 @@
  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
  #define user_path_walk(name,nd)	 __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
@@ -1750,7 +1784,7 @@
  
  extern void inode_init_once(struct inode *);
  extern void iput(struct inode *);
-@@ -1504,6 +1530,8 @@ extern struct file_operations generic_ro
+@@ -1504,6 +1530,8 @@
  
  extern int vfs_readlink(struct dentry *, char *, int, const char *);
  extern int vfs_follow_link(struct nameidata *, const char *);
@@ -1759,9 +1793,11 @@
  extern int page_readlink(struct dentry *, char *, int);
  extern int page_follow_link(struct dentry *, struct nameidata *);
  extern struct inode_operations page_symlink_inode_operations;
---- linux-2.4.20-rh-20.9/include/linux/fs_struct.h~vfs_intent-2.4.20-rh	2003-09-13 19:34:19.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/include/linux/fs_struct.h	2003-09-14 17:34:53.000000000 +0400
-@@ -37,10 +37,12 @@ static inline void set_fs_root(struct fs
+Index: linux-2.4.20/include/linux/fs_struct.h
+===================================================================
+--- linux-2.4.20.orig/include/linux/fs_struct.h	Wed Mar 17 13:57:02 2004
++++ linux-2.4.20/include/linux/fs_struct.h	Wed Mar 17 13:57:11 2004
+@@ -37,10 +37,12 @@
  	write_lock(&fs->lock);
  	old_root = fs->root;
  	old_rootmnt = fs->rootmnt;
@@ -1774,7 +1810,7 @@
  		dput(old_root);
  		mntput(old_rootmnt);
  	}
-@@ -60,10 +62,12 @@ static inline void set_fs_pwd(struct fs_
+@@ -60,10 +62,12 @@
  	write_lock(&fs->lock);
  	old_pwd = fs->pwd;
  	old_pwdmnt = fs->pwdmnt;
@@ -1787,9 +1823,11 @@
  		dput(old_pwd);
  		mntput(old_pwdmnt);
  	}
---- linux-2.4.20-rh-20.9/kernel/ksyms.c~vfs_intent-2.4.20-rh	2003-09-14 17:34:51.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/kernel/ksyms.c	2003-09-14 17:34:53.000000000 +0400
-@@ -298,6 +298,7 @@ EXPORT_SYMBOL(read_cache_page);
+Index: linux-2.4.20/kernel/ksyms.c
+===================================================================
+--- linux-2.4.20.orig/kernel/ksyms.c	Wed Mar 17 13:57:11 2004
++++ linux-2.4.20/kernel/ksyms.c	Wed Mar 17 13:57:11 2004
+@@ -297,6 +297,7 @@
  EXPORT_SYMBOL(set_page_dirty);
  EXPORT_SYMBOL(vfs_readlink);
  EXPORT_SYMBOL(vfs_follow_link);
@@ -1797,9 +1835,11 @@
  EXPORT_SYMBOL(page_readlink);
  EXPORT_SYMBOL(page_follow_link);
  EXPORT_SYMBOL(page_symlink_inode_operations);
---- linux-2.4.20-rh-20.9/kernel/fork.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/kernel/fork.c	2003-09-14 17:34:53.000000000 +0400
-@@ -440,10 +440,13 @@ static inline struct fs_struct *__copy_f
+Index: linux-2.4.20/kernel/fork.c
+===================================================================
+--- linux-2.4.20.orig/kernel/fork.c	Wed Mar 17 13:57:05 2004
++++ linux-2.4.20/kernel/fork.c	Wed Mar 17 13:57:11 2004
+@@ -440,10 +440,13 @@
  		fs->umask = old->umask;
  		read_lock(&old->lock);
  		fs->rootmnt = mntget(old->rootmnt);
@@ -1813,9 +1853,11 @@
  			fs->altrootmnt = mntget(old->altrootmnt);
  			fs->altroot = dget(old->altroot);
  		} else {
---- linux-2.4.20-rh-20.9/kernel/exit.c~vfs_intent-2.4.20-rh	2003-09-13 19:34:35.000000000 +0400
-+++ linux-2.4.20-rh-20.9-alexey/kernel/exit.c	2003-09-14 17:34:53.000000000 +0400
-@@ -345,11 +345,14 @@ static inline void __put_fs_struct(struc
+Index: linux-2.4.20/kernel/exit.c
+===================================================================
+--- linux-2.4.20.orig/kernel/exit.c	Wed Mar 17 13:57:05 2004
++++ linux-2.4.20/kernel/exit.c	Wed Mar 17 13:57:11 2004
+@@ -345,11 +345,14 @@
  {
  	/* No need to hold fs->lock if we are killing it */
  	if (atomic_dec_and_test(&fs->count)) {
@@ -1830,5 +1872,3 @@
  			dput(fs->altroot);
  			mntput(fs->altrootmnt);
  		}
-
-_
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch
index 7d83b5e44f82ed6941c0292144d9eca85bb7dcde..1ef0b01483a4a11414834de37618083ab618413f 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch
@@ -12,9 +12,11 @@
  kernel/ksyms.c            |    1 
  12 files changed, 558 insertions(+), 128 deletions(-)
 
---- linux-2.4.20-vanilla/fs/exec.c~vfs_intent-2.4.20-vanilla	2003-05-16 05:29:12.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/fs/exec.c	2003-09-17 21:05:04.000000000 +0400
-@@ -107,8 +107,10 @@ asmlinkage long sys_uselib(const char * 
+Index: linux-2.4.24/fs/exec.c
+===================================================================
+--- linux-2.4.24.orig/fs/exec.c	Fri Nov 28 10:26:21 2003
++++ linux-2.4.24/fs/exec.c	Wed Mar 17 17:36:14 2004
+@@ -112,8 +112,10 @@ asmlinkage long sys_uselib(const char * 
  	struct file * file;
  	struct nameidata nd;
  	int error;
@@ -26,7 +28,7 @@
  	if (error)
  		goto out;
  
-@@ -120,7 +122,8 @@ asmlinkage long sys_uselib(const char * 
+@@ -125,7 +127,8 @@ asmlinkage long sys_uselib(const char * 
  	if (error)
  		goto exit;
  
@@ -36,7 +38,7 @@
  	error = PTR_ERR(file);
  	if (IS_ERR(file))
  		goto out;
-@@ -363,8 +366,10 @@ struct file *open_exec(const char *name)
+@@ -374,8 +377,10 @@ struct file *open_exec(const char *name)
  	struct inode *inode;
  	struct file *file;
  	int err = 0;
@@ -48,7 +50,7 @@
  	file = ERR_PTR(err);
  	if (!err) {
  		inode = nd.dentry->d_inode;
-@@ -376,7 +381,8 @@ struct file *open_exec(const char *name)
+@@ -387,7 +392,8 @@ struct file *open_exec(const char *name)
  				err = -EACCES;
  			file = ERR_PTR(err);
  			if (!err) {
@@ -58,7 +60,7 @@
  				if (!IS_ERR(file)) {
  					err = deny_write_access(file);
  					if (err) {
-@@ -388,6 +394,7 @@ out:
+@@ -399,6 +405,7 @@ out:
  				return file;
  			}
  		}
@@ -66,7 +68,7 @@
  		path_release(&nd);
  	}
  	goto out;
-@@ -989,7 +996,7 @@ int do_coredump(long signr, struct pt_re
+@@ -1132,7 +1139,7 @@ int do_coredump(long signr, struct pt_re
  		goto close_fail;
  	if (!file->f_op->write)
  		goto close_fail;
@@ -75,8 +77,10 @@
  		goto close_fail;
  
  	retval = binfmt->core_dump(signr, regs, file);
---- linux-2.4.20-vanilla/fs/dcache.c~vfs_intent-2.4.20-vanilla	2003-05-16 05:29:12.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/fs/dcache.c	2003-09-17 21:05:04.000000000 +0400
+Index: linux-2.4.24/fs/dcache.c
+===================================================================
+--- linux-2.4.24.orig/fs/dcache.c	Fri Jun 13 07:51:37 2003
++++ linux-2.4.24/fs/dcache.c	Wed Mar 17 17:36:14 2004
 @@ -181,6 +181,13 @@ int d_invalidate(struct dentry * dentry)
  		spin_unlock(&dcache_lock);
  		return 0;
@@ -114,9 +118,11 @@
  }
  
  #define do_switch(x,y) do { \
---- linux-2.4.20-vanilla/fs/namespace.c~vfs_intent-2.4.20-vanilla	2003-05-16 05:29:12.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/fs/namespace.c	2003-09-17 21:05:04.000000000 +0400
-@@ -99,6 +99,7 @@ static void detach_mnt(struct vfsmount *
+Index: linux-2.4.24/fs/namespace.c
+===================================================================
+--- linux-2.4.24.orig/fs/namespace.c	Fri Nov 28 10:26:21 2003
++++ linux-2.4.24/fs/namespace.c	Wed Mar 17 17:36:14 2004
+@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount *
  {
  	old_nd->dentry = mnt->mnt_mountpoint;
  	old_nd->mnt = mnt->mnt_parent;
@@ -124,15 +130,15 @@
  	mnt->mnt_parent = mnt;
  	mnt->mnt_mountpoint = mnt->mnt_root;
  	list_del_init(&mnt->mnt_child);
-@@ -110,6 +111,7 @@ static void attach_mnt(struct vfsmount *
+@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount *
  {
  	mnt->mnt_parent = mntget(nd->mnt);
  	mnt->mnt_mountpoint = dget(nd->dentry);
 +	PIN(nd->dentry, nd->mnt, 1);
  	list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
- 	list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
+ 	list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts);
  	nd->dentry->d_mounted++;
-@@ -485,14 +487,17 @@ static int do_loopback(struct nameidata 
+@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata 
  {
  	struct nameidata old_nd;
  	struct vfsmount *mnt = NULL;
@@ -152,7 +158,7 @@
  
  	down_write(&current->namespace->sem);
  	err = -EINVAL;
-@@ -515,6 +520,7 @@ static int do_loopback(struct nameidata 
+@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata 
  	}
  
  	up_write(&current->namespace->sem);
@@ -160,7 +166,7 @@
  	path_release(&old_nd);
  	return err;
  }
-@@ -698,6 +704,7 @@ long do_mount(char * dev_name, char * di
+@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di
  		  unsigned long flags, void *data_page)
  {
  	struct nameidata nd;
@@ -168,7 +174,7 @@
  	int retval = 0;
  	int mnt_flags = 0;
  
-@@ -722,10 +729,11 @@ long do_mount(char * dev_name, char * di
+@@ -725,10 +732,11 @@ long do_mount(char * dev_name, char * di
  	flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
  
  	/* ... and get the mountpoint */
@@ -183,7 +189,7 @@
  	if (flags & MS_REMOUNT)
  		retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
  				    data_page);
-@@ -736,6 +744,8 @@ long do_mount(char * dev_name, char * di
+@@ -739,6 +747,8 @@ long do_mount(char * dev_name, char * di
  	else
  		retval = do_add_mount(&nd, type_page, flags, mnt_flags,
  				      dev_name, data_page);
@@ -192,7 +198,7 @@
  	path_release(&nd);
  	return retval;
  }
-@@ -901,6 +911,8 @@ asmlinkage long sys_pivot_root(const cha
+@@ -904,6 +914,8 @@ asmlinkage long sys_pivot_root(const cha
  {
  	struct vfsmount *tmp;
  	struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
@@ -201,7 +207,7 @@
  	int error;
  
  	if (!capable(CAP_SYS_ADMIN))
-@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha
+@@ -911,14 +923,14 @@ asmlinkage long sys_pivot_root(const cha
  
  	lock_kernel();
  
@@ -218,7 +224,7 @@
  	if (error)
  		goto out1;
  
-@@ -970,8 +982,10 @@ out2:
+@@ -973,8 +985,10 @@ out2:
  	up(&old_nd.dentry->d_inode->i_zombie);
  	up_write(&current->namespace->sem);
  	path_release(&user_nd);
@@ -229,8 +235,10 @@
  	path_release(&new_nd);
  out0:
  	unlock_kernel();
---- linux-2.4.20-vanilla/fs/namei.c~vfs_intent-2.4.20-vanilla	2003-05-16 05:29:12.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/fs/namei.c	2003-09-17 21:05:04.000000000 +0400
+Index: linux-2.4.24/fs/namei.c
+===================================================================
+--- linux-2.4.24.orig/fs/namei.c	Mon Aug 25 04:44:43 2003
++++ linux-2.4.24/fs/namei.c	Wed Mar 17 17:36:52 2004
 @@ -94,6 +94,13 @@
   * XEmacs seems to be relying on it...
   */
@@ -403,7 +411,7 @@
  				break;
  		}
  		goto return_base;
-@@ -633,6 +670,25 @@ return_reval:
+@@ -635,6 +672,27 @@ return_reval:
  		 * Check the cached dentry for staleness.
  		 */
  		dentry = nd->dentry;
@@ -419,17 +427,19 @@
 +						  &dentry->d_name, 0, NULL);
 +				d_invalidate(dentry);
 +				dput(dentry);
-+				if (IS_ERR(new)) { 
++				if (IS_ERR(new)) {
 +					err = PTR_ERR(new);
 +					break;
 +				}
 +				nd->dentry = new;
 +			}
++			if (!nd->dentry->d_inode)
++				goto no_inode;
 +		} else
  		if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
  			err = -ESTALE;
  			if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -646,15 +702,28 @@ out_dput:
+@@ -648,15 +706,28 @@ out_dput:
  		dput(dentry);
  		break;
  	}
@@ -459,7 +469,7 @@
  }
  
  /* SMP-safe */
-@@ -739,6 +808,17 @@ walk_init_root(const char *name, struct 
+@@ -741,6 +812,17 @@ walk_init_root(const char *name, struct 
  }
  
  /* SMP-safe */
@@ -477,7 +487,7 @@
  int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
  {
  	int error = 0;
-@@ -753,6 +833,7 @@ int path_init(const char *name, unsigned
+@@ -755,6 +837,7 @@ int path_init(const char *name, unsigned
  {
  	nd->last_type = LAST_ROOT; /* if there are only slashes... */
  	nd->flags = flags;
@@ -485,7 +495,7 @@
  	if (*name=='/')
  		return walk_init_root(name,nd);
  	read_lock(&current->fs->lock);
-@@ -767,7 +848,8 @@ int path_init(const char *name, unsigned
+@@ -769,7 +852,8 @@ int path_init(const char *name, unsigned
   * needs parent already locked. Doesn't follow mounts.
   * SMP-safe.
   */
@@ -495,7 +505,7 @@
  {
  	struct dentry * dentry;
  	struct inode *inode;
-@@ -790,13 +872,16 @@ struct dentry * lookup_hash(struct qstr 
+@@ -792,13 +876,16 @@ struct dentry * lookup_hash(struct qstr 
  			goto out;
  	}
  
@@ -513,7 +523,7 @@
  		dentry = inode->i_op->lookup(inode, new);
  		unlock_kernel();
  		if (!dentry)
-@@ -808,6 +893,12 @@ out:
+@@ -810,6 +897,12 @@ out:
  	return dentry;
  }
  
@@ -526,7 +536,7 @@
  /* SMP-safe */
  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
  {
-@@ -829,7 +920,7 @@ struct dentry * lookup_one_len(const cha
+@@ -831,7 +924,7 @@ struct dentry * lookup_one_len(const cha
  	}
  	this.hash = end_name_hash(hash);
  
@@ -535,7 +545,7 @@
  access:
  	return ERR_PTR(-EACCES);
  }
-@@ -860,6 +951,23 @@ int __user_walk(const char *name, unsign
+@@ -862,6 +955,23 @@ int __user_walk(const char *name, unsign
  	return err;
  }
  
@@ -559,7 +569,7 @@
  /*
   * It's inline, so penalty for filesystems that don't use sticky bit is
   * minimal.
-@@ -955,7 +1063,8 @@ static inline int lookup_flags(unsigned 
+@@ -957,7 +1067,8 @@ static inline int lookup_flags(unsigned 
  	return retval;
  }
  
@@ -569,7 +579,7 @@
  {
  	int error;
  
-@@ -968,12 +1077,15 @@ int vfs_create(struct inode *dir, struct
+@@ -970,12 +1081,15 @@ int vfs_create(struct inode *dir, struct
  		goto exit_lock;
  
  	error = -EACCES;	/* shouldn't it be ENOSYS? */
@@ -587,7 +597,7 @@
  	unlock_kernel();
  exit_lock:
  	up(&dir->i_zombie);
-@@ -982,6 +1094,11 @@ exit_lock:
+@@ -984,6 +1098,11 @@ exit_lock:
  	return error;
  }
  
@@ -599,7 +609,7 @@
  /*
   *	open_namei()
   *
-@@ -996,7 +1113,8 @@ exit_lock:
+@@ -998,7 +1117,8 @@ exit_lock:
   * for symlinks (where the permissions are checked later).
   * SMP-safe
   */
@@ -609,7 +619,7 @@
  {
  	int acc_mode, error = 0;
  	struct inode *inode;
-@@ -1006,11 +1124,14 @@ int open_namei(const char * pathname, in
+@@ -1008,11 +1128,14 @@ int open_namei(const char * pathname, in
  
  	acc_mode = ACC_MODE(flag);
  
@@ -625,7 +635,7 @@
  		if (error)
  			return error;
  		dentry = nd->dentry;
-@@ -1020,6 +1141,10 @@ int open_namei(const char * pathname, in
+@@ -1022,6 +1145,10 @@ int open_namei(const char * pathname, in
  	/*
  	 * Create - we need to know the parent.
  	 */
@@ -636,7 +646,7 @@
  	error = path_lookup(pathname, LOOKUP_PARENT, nd);
  	if (error)
  		return error;
-@@ -1035,7 +1160,7 @@ int open_namei(const char * pathname, in
+@@ -1037,7 +1164,7 @@ int open_namei(const char * pathname, in
  
  	dir = nd->dentry;
  	down(&dir->d_inode->i_sem);
@@ -645,7 +655,7 @@
  
  do_last:
  	error = PTR_ERR(dentry);
-@@ -1044,10 +1169,11 @@ do_last:
+@@ -1046,10 +1173,11 @@ do_last:
  		goto exit;
  	}
  
@@ -659,7 +669,7 @@
  		up(&dir->d_inode->i_sem);
  		dput(nd->dentry);
  		nd->dentry = dentry;
-@@ -1151,7 +1277,7 @@ ok:
+@@ -1153,7 +1281,7 @@ ok:
  		if (!error) {
  			DQUOT_INIT(inode);
  			
@@ -668,7 +678,7 @@
  		}
  		put_write_access(inode);
  		if (error)
-@@ -1163,8 +1289,10 @@ ok:
+@@ -1165,8 +1293,10 @@ ok:
  	return 0;
  
  exit_dput:
@@ -679,7 +689,7 @@
  	path_release(nd);
  	return error;
  
-@@ -1183,7 +1311,10 @@ do_link:
+@@ -1185,7 +1315,10 @@ do_link:
  	 * are done. Procfs-like symlinks just set LAST_BIND.
  	 */
  	UPDATE_ATIME(dentry->d_inode);
@@ -690,7 +700,7 @@
  	dput(dentry);
  	if (error)
  		return error;
-@@ -1205,13 +1336,20 @@ do_link:
+@@ -1207,13 +1340,20 @@ do_link:
  	}
  	dir = nd->dentry;
  	down(&dir->d_inode->i_sem);
@@ -713,7 +723,7 @@
  {
  	struct dentry *dentry;
  
-@@ -1219,7 +1357,7 @@ static struct dentry *lookup_create(stru
+@@ -1221,7 +1361,7 @@ static struct dentry *lookup_create(stru
  	dentry = ERR_PTR(-EEXIST);
  	if (nd->last_type != LAST_NORM)
  		goto fail;
@@ -722,12 +732,16 @@
  	if (IS_ERR(dentry))
  		goto fail;
  	if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1275,7 +1413,16 @@ asmlinkage long sys_mknod(const char * f
+@@ -1277,7 +1417,20 @@ asmlinkage long sys_mknod(const char * f
  	error = path_lookup(tmp, LOOKUP_PARENT, &nd);
  	if (error)
  		goto out;
 -	dentry = lookup_create(&nd, 0);
 +
++	if (nd.last_type != LAST_NORM) {
++		error = -EEXIST;
++		goto out2;
++	}
 +	if (nd.dentry->d_inode->i_op->mknod_raw) {
 +		struct inode_operations *op = nd.dentry->d_inode->i_op;
 +		error = op->mknod_raw(&nd, mode, dev);
@@ -740,7 +754,7 @@
  	error = PTR_ERR(dentry);
  
  	mode &= ~current->fs->umask;
-@@ -1296,6 +1443,7 @@ asmlinkage long sys_mknod(const char * f
+@@ -1298,6 +1451,7 @@ asmlinkage long sys_mknod(const char * f
  		dput(dentry);
  	}
  	up(&nd.dentry->d_inode->i_sem);
@@ -748,11 +762,15 @@
  	path_release(&nd);
  out:
  	putname(tmp);
-@@ -1343,7 +1491,14 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1345,7 +1499,18 @@ asmlinkage long sys_mkdir(const char * p
  		error = path_lookup(tmp, LOOKUP_PARENT, &nd);
  		if (error)
  			goto out;
 -		dentry = lookup_create(&nd, 1);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out2;
++		}
 +		if (nd.dentry->d_inode->i_op->mkdir_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->mkdir_raw(&nd, mode);
@@ -764,7 +782,7 @@
  		error = PTR_ERR(dentry);
  		if (!IS_ERR(dentry)) {
  			error = vfs_mkdir(nd.dentry->d_inode, dentry,
-@@ -1351,6 +1506,7 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1353,6 +1518,7 @@ asmlinkage long sys_mkdir(const char * p
  			dput(dentry);
  		}
  		up(&nd.dentry->d_inode->i_sem);
@@ -772,7 +790,7 @@
  		path_release(&nd);
  out:
  		putname(tmp);
-@@ -1451,8 +1607,16 @@ asmlinkage long sys_rmdir(const char * p
+@@ -1453,8 +1619,16 @@ asmlinkage long sys_rmdir(const char * p
  			error = -EBUSY;
  			goto exit1;
  	}
@@ -790,7 +808,7 @@
  	error = PTR_ERR(dentry);
  	if (!IS_ERR(dentry)) {
  		error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1510,8 +1674,15 @@ asmlinkage long sys_unlink(const char * 
+@@ -1512,8 +1686,15 @@ asmlinkage long sys_unlink(const char * 
  	error = -EISDIR;
  	if (nd.last_type != LAST_NORM)
  		goto exit1;
@@ -807,11 +825,15 @@
  	error = PTR_ERR(dentry);
  	if (!IS_ERR(dentry)) {
  		/* Why not before? Because we want correct error value */
-@@ -1578,15 +1749,23 @@ asmlinkage long sys_symlink(const char *
+@@ -1580,15 +1761,27 @@ asmlinkage long sys_symlink(const char *
  		error = path_lookup(to, LOOKUP_PARENT, &nd);
  		if (error)
  			goto out;
 -		dentry = lookup_create(&nd, 0);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out2;
++		}
 +		if (nd.dentry->d_inode->i_op->symlink_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->symlink_raw(&nd, from);
@@ -833,11 +855,15 @@
  		putname(to);
  	}
  	putname(from);
-@@ -1662,7 +1841,14 @@ asmlinkage long sys_link(const char * ol
+@@ -1664,7 +1857,18 @@ asmlinkage long sys_link(const char * ol
  		error = -EXDEV;
  		if (old_nd.mnt != nd.mnt)
  			goto out_release;
 -		new_dentry = lookup_create(&nd, 0);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out_release;
++		}
 +		if (nd.dentry->d_inode->i_op->link_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->link_raw(&old_nd, &nd);
@@ -849,7 +875,7 @@
  		error = PTR_ERR(new_dentry);
  		if (!IS_ERR(new_dentry)) {
  			error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1706,7 +1892,7 @@ exit:
+@@ -1708,7 +1912,7 @@ exit:
   *	   locking].
   */
  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
@@ -858,7 +884,7 @@
  {
  	int error;
  	struct inode *target;
-@@ -1785,7 +1971,7 @@ out_unlock:
+@@ -1787,7 +1991,7 @@ out_unlock:
  }
  
  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
@@ -867,7 +893,7 @@
  {
  	int error;
  
-@@ -1873,9 +2059,18 @@ static inline int do_rename(const char *
+@@ -1875,9 +2079,18 @@ static inline int do_rename(const char *
  	if (newnd.last_type != LAST_NORM)
  		goto exit2;
  
@@ -887,7 +913,7 @@
  	error = PTR_ERR(old_dentry);
  	if (IS_ERR(old_dentry))
  		goto exit3;
-@@ -1891,16 +2086,16 @@ static inline int do_rename(const char *
+@@ -1893,16 +2106,16 @@ static inline int do_rename(const char *
  		if (newnd.last.name[newnd.last.len])
  			goto exit4;
  	}
@@ -906,7 +932,7 @@
  	dput(new_dentry);
  exit4:
  	dput(old_dentry);
-@@ -1951,20 +2146,26 @@ out:
+@@ -1953,20 +2166,26 @@ out:
  }
  
  static inline int
@@ -935,7 +961,7 @@
  out:
  	if (current->link_count || res || nd->last_type!=LAST_NORM)
  		return res;
-@@ -1986,7 +2187,13 @@ fail:
+@@ -1990,7 +2209,13 @@ fail:
  
  int vfs_follow_link(struct nameidata *nd, const char *link)
  {
@@ -950,7 +976,7 @@
  }
  
  /* get the link contents into pagecache */
-@@ -2028,7 +2235,7 @@ int page_follow_link(struct dentry *dent
+@@ -2032,7 +2257,7 @@ int page_follow_link(struct dentry *dent
  {
  	struct page *page = NULL;
  	char *s = page_getlink(dentry, &page);
@@ -959,8 +985,10 @@
  	if (page) {
  		kunmap(page);
  		page_cache_release(page);
---- linux-2.4.20-vanilla/fs/open.c~vfs_intent-2.4.20-vanilla	2003-05-16 05:29:13.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/fs/open.c	2003-09-17 21:05:04.000000000 +0400
+Index: linux-2.4.24/fs/open.c
+===================================================================
+--- linux-2.4.24.orig/fs/open.c	Mon Aug 25 04:44:43 2003
++++ linux-2.4.24/fs/open.c	Wed Mar 17 17:36:14 2004
 @@ -19,6 +19,8 @@
  #include <asm/uaccess.h>
  
@@ -982,7 +1010,7 @@
  	int error;
  	struct iattr newattrs;
  
-@@ -108,7 +111,13 @@ int do_truncate(struct dentry *dentry, l
+@@ -109,7 +112,13 @@ int do_truncate(struct dentry *dentry, l
  	down(&inode->i_sem);
  	newattrs.ia_size = length;
  	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
@@ -995,9 +1023,9 @@
 +	} else
 +		error = notify_change(dentry, &newattrs);
  	up(&inode->i_sem);
+ 	up_write(&inode->i_alloc_sem);
  	return error;
- }
-@@ -118,12 +127,13 @@ static inline long do_sys_truncate(const
+@@ -120,12 +129,13 @@ static inline long do_sys_truncate(const
  	struct nameidata nd;
  	struct inode * inode;
  	int error;
@@ -1012,7 +1040,7 @@
  	if (error)
  		goto out;
  	inode = nd.dentry->d_inode;
-@@ -163,11 +173,13 @@ static inline long do_sys_truncate(const
+@@ -165,11 +175,13 @@ static inline long do_sys_truncate(const
  	error = locks_verify_truncate(inode, NULL, length);
  	if (!error) {
  		DQUOT_INIT(inode);
@@ -1027,7 +1055,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -215,7 +227,7 @@ static inline long do_sys_ftruncate(unsi
+@@ -217,7 +229,7 @@ static inline long do_sys_ftruncate(unsi
  
  	error = locks_verify_truncate(inode, file, length);
  	if (!error)
@@ -1036,7 +1064,7 @@
  out_putf:
  	fput(file);
  out:
-@@ -260,11 +272,13 @@ asmlinkage long sys_utime(char * filenam
+@@ -262,11 +274,13 @@ asmlinkage long sys_utime(char * filenam
  	struct inode * inode;
  	struct iattr newattrs;
  
@@ -1051,7 +1079,7 @@
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto dput_and_out;
-@@ -279,11 +293,25 @@ asmlinkage long sys_utime(char * filenam
+@@ -281,11 +295,25 @@ asmlinkage long sys_utime(char * filenam
  			goto dput_and_out;
  
  		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1078,7 +1106,7 @@
  	error = notify_change(nd.dentry, &newattrs);
  dput_and_out:
  	path_release(&nd);
-@@ -304,12 +332,14 @@ asmlinkage long sys_utimes(char * filena
+@@ -306,12 +334,14 @@ asmlinkage long sys_utimes(char * filena
  	struct inode * inode;
  	struct iattr newattrs;
  
@@ -1094,7 +1122,7 @@
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto dput_and_out;
-@@ -324,7 +354,20 @@ asmlinkage long sys_utimes(char * filena
+@@ -326,7 +356,20 @@ asmlinkage long sys_utimes(char * filena
  		newattrs.ia_atime = times[0].tv_sec;
  		newattrs.ia_mtime = times[1].tv_sec;
  		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1116,7 +1144,7 @@
  		if (current->fsuid != inode->i_uid &&
  		    (error = permission(inode,MAY_WRITE)) != 0)
  			goto dput_and_out;
-@@ -347,6 +390,7 @@ asmlinkage long sys_access(const char * 
+@@ -349,6 +392,7 @@ asmlinkage long sys_access(const char * 
  	int old_fsuid, old_fsgid;
  	kernel_cap_t old_cap;
  	int res;
@@ -1124,7 +1152,7 @@
  
  	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
  		return -EINVAL;
-@@ -364,13 +408,14 @@ asmlinkage long sys_access(const char * 
+@@ -366,13 +410,14 @@ asmlinkage long sys_access(const char * 
  	else
  		current->cap_effective = current->cap_permitted;
  
@@ -1140,7 +1168,7 @@
  		path_release(&nd);
  	}
  
-@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f
+@@ -387,8 +432,9 @@ asmlinkage long sys_chdir(const char * f
  {
  	int error;
  	struct nameidata nd;
@@ -1151,7 +1179,7 @@
  	if (error)
  		goto out;
  
-@@ -397,6 +443,7 @@ asmlinkage long sys_chdir(const char * f
+@@ -399,6 +445,7 @@ asmlinkage long sys_chdir(const char * f
  	set_fs_pwd(current->fs, nd.mnt, nd.dentry);
  
  dput_and_out:
@@ -1159,7 +1187,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -436,9 +483,10 @@ asmlinkage long sys_chroot(const char * 
+@@ -438,9 +485,10 @@ asmlinkage long sys_chroot(const char * 
  {
  	int error;
  	struct nameidata nd;
@@ -1172,7 +1200,7 @@
  	if (error)
  		goto out;
  
-@@ -454,39 +502,56 @@ asmlinkage long sys_chroot(const char * 
+@@ -456,39 +504,56 @@ asmlinkage long sys_chroot(const char * 
  	set_fs_altroot();
  	error = 0;
  dput_and_out:
@@ -1243,7 +1271,7 @@
  	fput(file);
  out:
  	return err;
-@@ -495,30 +560,14 @@ out:
+@@ -497,30 +562,14 @@ out:
  asmlinkage long sys_chmod(const char * filename, mode_t mode)
  {
  	struct nameidata nd;
@@ -1275,7 +1303,7 @@
  	path_release(&nd);
  out:
  	return error;
-@@ -538,6 +587,20 @@ static int chown_common(struct dentry * 
+@@ -540,6 +589,20 @@ static int chown_common(struct dentry * 
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto out;
@@ -1296,7 +1324,7 @@
  	error = -EPERM;
  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out;
-@@ -642,6 +705,7 @@ struct file *filp_open(const char * file
+@@ -644,6 +707,7 @@ struct file *filp_open(const char * file
  {
  	int namei_flags, error;
  	struct nameidata nd;
@@ -1304,7 +1332,7 @@
  
  	namei_flags = flags;
  	if ((namei_flags+1) & O_ACCMODE)
-@@ -649,14 +713,15 @@ struct file *filp_open(const char * file
+@@ -651,14 +715,15 @@ struct file *filp_open(const char * file
  	if (namei_flags & O_TRUNC)
  		namei_flags |= 2;
  
@@ -1325,7 +1353,7 @@
  {
  	struct file * f;
  	struct inode *inode;
-@@ -693,12 +758,15 @@ struct file *dentry_open(struct dentry *
+@@ -695,12 +760,15 @@ struct file *dentry_open(struct dentry *
  	}
  
  	if (f->f_op && f->f_op->open) {
@@ -1341,7 +1369,7 @@
  	return f;
  
  cleanup_all:
-@@ -713,11 +781,17 @@ cleanup_all:
+@@ -715,11 +783,17 @@ cleanup_all:
  cleanup_file:
  	put_filp(f);
  cleanup_dentry:
@@ -1359,9 +1387,11 @@
  /*
   * Find an empty file descriptor entry, and mark it busy.
   */
---- linux-2.4.20-vanilla/fs/stat.c~vfs_intent-2.4.20-vanilla	2001-09-14 03:04:43.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/fs/stat.c	2003-09-17 21:05:04.000000000 +0400
-@@ -17,10 +17,14 @@
+Index: linux-2.4.24/fs/stat.c
+===================================================================
+--- linux-2.4.24.orig/fs/stat.c	Mon Aug 25 04:44:43 2003
++++ linux-2.4.24/fs/stat.c	Wed Mar 17 17:36:52 2004
+@@ -17,10 +17,12 @@
   * Revalidate the inode. This is required for proper NFS attribute caching.
   */
  static __inline__ int
@@ -1370,15 +1400,13 @@
  {
  	struct inode * inode = dentry->d_inode;
 -	if (inode->i_op && inode->i_op->revalidate)
-+	if (!inode)
-+		return -ENOENT;
 +	if (inode->i_op && inode->i_op->revalidate_it)
 +		return inode->i_op->revalidate_it(dentry, it);
 +	else if (inode->i_op && inode->i_op->revalidate)
  		return inode->i_op->revalidate(dentry);
  	return 0;
  }
-@@ -135,13 +139,15 @@ static int cp_new_stat(struct inode * in
+@@ -137,13 +139,15 @@ static int cp_new_stat(struct inode * in
  asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
  {
  	struct nameidata nd;
@@ -1396,7 +1424,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -151,13 +157,15 @@ asmlinkage long sys_stat(char * filename
+@@ -153,13 +157,15 @@ asmlinkage long sys_stat(char * filename
  asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
  {
  	struct nameidata nd;
@@ -1414,7 +1442,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -172,13 +180,15 @@ asmlinkage long sys_newstat(char * filen
+@@ -174,13 +180,15 @@ asmlinkage long sys_newstat(char * filen
  asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
  {
  	struct nameidata nd;
@@ -1432,7 +1460,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -189,13 +199,15 @@ asmlinkage long sys_lstat(char * filenam
+@@ -191,13 +199,15 @@ asmlinkage long sys_lstat(char * filenam
  asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
  {
  	struct nameidata nd;
@@ -1450,7 +1478,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -216,7 +228,7 @@ asmlinkage long sys_fstat(unsigned int f
+@@ -218,7 +228,7 @@ asmlinkage long sys_fstat(unsigned int f
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1459,7 +1487,7 @@
  		if (!err)
  			err = cp_old_stat(dentry->d_inode, statbuf);
  		fput(f);
-@@ -235,7 +247,7 @@ asmlinkage long sys_newfstat(unsigned in
+@@ -237,7 +247,7 @@ asmlinkage long sys_newfstat(unsigned in
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1468,7 +1496,7 @@
  		if (!err)
  			err = cp_new_stat(dentry->d_inode, statbuf);
  		fput(f);
-@@ -257,7 +269,7 @@ asmlinkage long sys_readlink(const char 
+@@ -259,7 +269,7 @@ asmlinkage long sys_readlink(const char 
  
  		error = -EINVAL;
  		if (inode->i_op && inode->i_op->readlink &&
@@ -1477,7 +1505,7 @@
  			UPDATE_ATIME(inode);
  			error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
  		}
-@@ -333,12 +345,14 @@ asmlinkage long sys_stat64(char * filena
+@@ -335,12 +345,14 @@ asmlinkage long sys_stat64(char * filena
  {
  	struct nameidata nd;
  	int error;
@@ -1494,7 +1522,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -348,12 +362,14 @@ asmlinkage long sys_lstat64(char * filen
+@@ -350,12 +362,14 @@ asmlinkage long sys_lstat64(char * filen
  {
  	struct nameidata nd;
  	int error;
@@ -1511,7 +1539,7 @@
  		path_release(&nd);
  	}
  	return error;
-@@ -368,7 +384,7 @@ asmlinkage long sys_fstat64(unsigned lon
+@@ -370,7 +384,7 @@ asmlinkage long sys_fstat64(unsigned lon
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1520,8 +1548,10 @@
  		if (!err)
  			err = cp_new_stat64(dentry->d_inode, statbuf);
  		fput(f);
---- linux-2.4.20-vanilla/include/linux/dcache.h~vfs_intent-2.4.20-vanilla	2003-05-16 05:29:15.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/include/linux/dcache.h	2003-09-17 21:05:42.000000000 +0400
+Index: linux-2.4.24/include/linux/dcache.h
+===================================================================
+--- linux-2.4.24.orig/include/linux/dcache.h	Thu Nov 28 15:53:15 2002
++++ linux-2.4.24/include/linux/dcache.h	Wed Mar 17 17:36:14 2004
 @@ -6,6 +6,51 @@
  #include <asm/atomic.h>
  #include <linux/mount.h>
@@ -1605,8 +1635,10 @@
  
  extern spinlock_t dcache_lock;
  
---- linux-2.4.20-vanilla/include/linux/fs.h~vfs_intent-2.4.20-vanilla	2003-09-17 21:05:03.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/include/linux/fs.h	2003-09-17 21:05:04.000000000 +0400
+Index: linux-2.4.24/include/linux/fs.h
+===================================================================
+--- linux-2.4.24.orig/include/linux/fs.h	Wed Mar 17 17:36:14 2004
++++ linux-2.4.24/include/linux/fs.h	Wed Mar 17 17:36:14 2004
 @@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena
  
  #define FMODE_READ 1
@@ -1615,7 +1647,7 @@
  
  #define READ 0
  #define WRITE 1
-@@ -338,6 +339,9 @@ extern void set_bh_page(struct buffer_he
+@@ -340,6 +341,9 @@ extern void set_bh_page(struct buffer_he
  #define ATTR_MTIME_SET	256
  #define ATTR_FORCE	512	/* Not a change, but a change it */
  #define ATTR_ATTR_FLAG	1024
@@ -1625,7 +1657,7 @@
  
  /*
   * This is the Inode Attributes structure, used for notify_change().  It
-@@ -471,6 +475,7 @@ struct inode {
+@@ -478,6 +482,7 @@ struct inode {
  	struct pipe_inode_info	*i_pipe;
  	struct block_device	*i_bdev;
  	struct char_device	*i_cdev;
@@ -1633,7 +1665,7 @@
  
  	unsigned long		i_dnotify_mask; /* Directory notify events */
  	struct dnotify_struct	*i_dnotify; /* for directory notifications */
-@@ -542,6 +547,7 @@ struct file {
+@@ -582,6 +587,7 @@ struct file {
  
  	/* needed for tty driver, and maybe others */
  	void			*private_data;
@@ -1641,15 +1673,15 @@
  
  	/* preallocated helper kiobuf to speedup O_DIRECT */
  	struct kiobuf		*f_iobuf;
-@@ -661,6 +667,7 @@ struct nameidata {
+@@ -702,6 +708,7 @@ struct nameidata {
  	struct qstr last;
  	unsigned int flags;
  	int last_type;
 +	struct lookup_intent *intent;
  };
  
- #define DQUOT_USR_ENABLED	0x01		/* User diskquotas enabled */
-@@ -794,7 +801,8 @@ extern int vfs_symlink(struct inode *, s
+ /*
+@@ -822,7 +829,8 @@ extern int vfs_symlink(struct inode *, s
  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
  extern int vfs_rmdir(struct inode *, struct dentry *);
  extern int vfs_unlink(struct inode *, struct dentry *);
@@ -1659,7 +1691,7 @@
  
  /*
   * File types
-@@ -854,21 +862,32 @@ struct file_operations {
+@@ -884,21 +892,32 @@ struct file_operations {
  
  struct inode_operations {
  	int (*create) (struct inode *,struct dentry *,int);
@@ -1692,7 +1724,7 @@
  	int (*getattr) (struct dentry *, struct iattr *);
  	int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
  	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -1070,10 +1089,14 @@ static inline int get_lease(struct inode
+@@ -1094,10 +1113,14 @@ static inline int get_lease(struct inode
  
  asmlinkage long sys_open(const char *, int, int);
  asmlinkage long sys_close(unsigned int);	/* yes, it's really unsigned */
@@ -1708,7 +1740,7 @@
  extern int filp_close(struct file *, fl_owner_t id);
  extern char * getname(const char *);
  
-@@ -1335,6 +1358,7 @@ typedef int (*read_actor_t)(read_descrip
+@@ -1386,6 +1409,7 @@ typedef int (*read_actor_t)(read_descrip
  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
  
  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
@@ -1716,16 +1748,16 @@
  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
  extern int FASTCALL(path_walk(const char *, struct nameidata *));
  extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1346,6 +1370,8 @@ extern struct dentry * lookup_one_len(co
+@@ -1397,6 +1421,8 @@ extern struct dentry * lookup_one_len(co
  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
  #define user_path_walk(name,nd)	 __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
 +#define user_path_walk_it(name,nd,it)  __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
 +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
  
+ extern void inode_init_once(struct inode *);
  extern void iput(struct inode *);
- extern void force_delete(struct inode *);
-@@ -1455,6 +1481,8 @@ extern struct file_operations generic_ro
+@@ -1500,6 +1526,8 @@ extern struct file_operations generic_ro
  
  extern int vfs_readlink(struct dentry *, char *, int, const char *);
  extern int vfs_follow_link(struct nameidata *, const char *);
@@ -1734,8 +1766,10 @@
  extern int page_readlink(struct dentry *, char *, int);
  extern int page_follow_link(struct dentry *, struct nameidata *);
  extern struct inode_operations page_symlink_inode_operations;
---- linux-2.4.20-vanilla/include/linux/fs_struct.h~vfs_intent-2.4.20-vanilla	2001-07-14 02:10:44.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/include/linux/fs_struct.h	2003-09-17 21:05:04.000000000 +0400
+Index: linux-2.4.24/include/linux/fs_struct.h
+===================================================================
+--- linux-2.4.24.orig/include/linux/fs_struct.h	Fri Jul 13 15:10:44 2001
++++ linux-2.4.24/include/linux/fs_struct.h	Wed Mar 17 17:36:14 2004
 @@ -34,10 +34,12 @@ static inline void set_fs_root(struct fs
  	write_lock(&fs->lock);
  	old_root = fs->root;
@@ -1762,19 +1796,23 @@
  		dput(old_pwd);
  		mntput(old_pwdmnt);
  	}
---- linux-2.4.20-vanilla/kernel/ksyms.c~vfs_intent-2.4.20-vanilla	2003-09-17 21:05:03.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/kernel/ksyms.c	2003-09-17 21:05:04.000000000 +0400
-@@ -269,6 +269,7 @@ EXPORT_SYMBOL(read_cache_page);
- EXPORT_SYMBOL(set_page_dirty);
+Index: linux-2.4.24/kernel/ksyms.c
+===================================================================
+--- linux-2.4.24.orig/kernel/ksyms.c	Wed Mar 17 17:36:14 2004
++++ linux-2.4.24/kernel/ksyms.c	Wed Mar 17 17:36:14 2004
+@@ -275,6 +275,7 @@ EXPORT_SYMBOL(set_page_dirty);
+ EXPORT_SYMBOL(mark_page_accessed);
  EXPORT_SYMBOL(vfs_readlink);
  EXPORT_SYMBOL(vfs_follow_link);
 +EXPORT_SYMBOL(vfs_follow_link_it);
  EXPORT_SYMBOL(page_readlink);
  EXPORT_SYMBOL(page_follow_link);
  EXPORT_SYMBOL(page_symlink_inode_operations);
---- linux-2.4.20-vanilla/kernel/fork.c~vfs_intent-2.4.20-vanilla	2003-05-16 05:29:15.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/kernel/fork.c	2003-09-17 21:05:04.000000000 +0400
-@@ -384,10 +384,13 @@ static inline struct fs_struct *__copy_f
+Index: linux-2.4.24/kernel/fork.c
+===================================================================
+--- linux-2.4.24.orig/kernel/fork.c	Fri Nov 28 10:26:21 2003
++++ linux-2.4.24/kernel/fork.c	Wed Mar 17 17:36:14 2004
+@@ -386,10 +386,13 @@ static inline struct fs_struct *__copy_f
  		fs->umask = old->umask;
  		read_lock(&old->lock);
  		fs->rootmnt = mntget(old->rootmnt);
@@ -1788,8 +1826,10 @@
  			fs->altrootmnt = mntget(old->altrootmnt);
  			fs->altroot = dget(old->altroot);
  		} else {
---- linux-2.4.20-vanilla/kernel/exit.c~vfs_intent-2.4.20-vanilla	2003-05-16 05:29:15.000000000 +0400
-+++ linux-2.4.20-vanilla-alexey/kernel/exit.c	2003-09-17 21:05:04.000000000 +0400
+Index: linux-2.4.24/kernel/exit.c
+===================================================================
+--- linux-2.4.24.orig/kernel/exit.c	Thu Nov 28 15:53:15 2002
++++ linux-2.4.24/kernel/exit.c	Wed Mar 17 17:36:14 2004
 @@ -238,11 +238,14 @@ static inline void __put_fs_struct(struc
  {
  	/* No need to hold fs->lock if we are killing it */
@@ -1805,5 +1845,3 @@
  			dput(fs->altroot);
  			mntput(fs->altrootmnt);
  		}
-
-_
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch
index 7587ad28a61c4d8009c81b3edd3b6fdd070da245..09ef2f9520dd1b05121daeec5822edf93945883e 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch
@@ -12,11 +12,11 @@
  kernel/ksyms.c            |    1 
  12 files changed, 558 insertions(+), 128 deletions(-)
 
-Index: linux-2.4.21-chaos/fs/dcache.c
+Index: linux-ia64/fs/dcache.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/dcache.c	2003-09-19 03:49:54.000000000 +0400
-+++ linux-2.4.21-chaos/fs/dcache.c	2003-12-12 17:02:47.000000000 +0300
-@@ -186,6 +186,13 @@
+--- linux-ia64.orig/fs/dcache.c	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/fs/dcache.c	2004-03-17 16:05:28.000000000 -0800
+@@ -186,6 +186,13 @@ int d_invalidate(struct dentry * dentry)
  		spin_unlock(&dcache_lock);
  		return 0;
  	}
@@ -30,7 +30,7 @@ Index: linux-2.4.21-chaos/fs/dcache.c
  	/*
  	 * Check whether to do a partial shrink_dcache
  	 * to get rid of unused child entries.
-@@ -847,13 +854,19 @@
+@@ -850,13 +857,19 @@ void d_delete(struct dentry * dentry)
   * Adds a dentry to the hash according to its name.
   */
   
@@ -53,11 +53,11 @@ Index: linux-2.4.21-chaos/fs/dcache.c
  }
  
  #define do_switch(x,y) do { \
-Index: linux-2.4.21-chaos/fs/exec.c
+Index: linux-ia64/fs/exec.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/exec.c	2003-12-05 07:55:47.000000000 +0300
-+++ linux-2.4.21-chaos/fs/exec.c	2003-12-12 17:02:47.000000000 +0300
-@@ -119,8 +119,10 @@
+--- linux-ia64.orig/fs/exec.c	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/fs/exec.c	2004-03-17 16:05:28.000000000 -0800
+@@ -119,8 +119,10 @@ asmlinkage long sys_uselib(const char * 
  	struct file * file;
  	struct nameidata nd;
  	int error;
@@ -69,7 +69,7 @@ Index: linux-2.4.21-chaos/fs/exec.c
  	if (error)
  		goto out;
  
-@@ -132,7 +134,8 @@
+@@ -132,7 +134,8 @@ asmlinkage long sys_uselib(const char * 
  	if (error)
  		goto exit;
  
@@ -79,7 +79,7 @@ Index: linux-2.4.21-chaos/fs/exec.c
  	error = PTR_ERR(file);
  	if (IS_ERR(file))
  		goto out;
-@@ -400,8 +403,10 @@
+@@ -400,8 +403,10 @@ struct file *open_exec(const char *name)
  	struct inode *inode;
  	struct file *file;
  	int err = 0;
@@ -91,7 +91,7 @@ Index: linux-2.4.21-chaos/fs/exec.c
  	file = ERR_PTR(err);
  	if (!err) {
  		inode = nd.dentry->d_inode;
-@@ -413,7 +418,8 @@
+@@ -413,7 +418,8 @@ struct file *open_exec(const char *name)
  				err = -EACCES;
  			file = ERR_PTR(err);
  			if (!err) {
@@ -101,7 +101,7 @@ Index: linux-2.4.21-chaos/fs/exec.c
  				if (!IS_ERR(file)) {
  					err = deny_write_access(file);
  					if (err) {
-@@ -425,6 +431,7 @@
+@@ -425,6 +431,7 @@ out:
  				return file;
  			}
  		}
@@ -109,7 +109,7 @@ Index: linux-2.4.21-chaos/fs/exec.c
  		path_release(&nd);
  	}
  	goto out;
-@@ -1348,7 +1355,7 @@
+@@ -1348,7 +1355,7 @@ int do_coredump(long signr, int exit_cod
  		goto close_fail;
  	if (!file->f_op->write)
  		goto close_fail;
@@ -118,10 +118,10 @@ Index: linux-2.4.21-chaos/fs/exec.c
  		goto close_fail;
  
  	retval = binfmt->core_dump(signr, regs, file);
-Index: linux-2.4.21-chaos/fs/namei.c
+Index: linux-ia64/fs/namei.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/namei.c	2003-07-15 04:41:01.000000000 +0400
-+++ linux-2.4.21-chaos/fs/namei.c	2003-12-12 17:03:37.000000000 +0300
+--- linux-ia64.orig/fs/namei.c	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/fs/namei.c	2004-03-17 16:06:13.000000000 -0800
 @@ -94,6 +94,13 @@
   * XEmacs seems to be relying on it...
   */
@@ -136,7 +136,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  /* In order to reduce some races, while at the same time doing additional
   * checking and hopefully speeding things up, we copy filenames to the
   * kernel data space before using them..
-@@ -260,10 +267,19 @@
+@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd)
   * Internal lookup() using the new generic dcache.
   * SMP-safe
   */
@@ -157,7 +157,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
  		if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
  			dput(dentry);
-@@ -281,11 +297,15 @@
+@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str
   * make sure that nobody added the entry to the dcache in the meantime..
   * SMP-safe
   */
@@ -174,7 +174,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	down(&dir->i_sem);
  	/*
  	 * First re-do the cached lookup just in case it was created
-@@ -300,6 +320,9 @@
+@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc
  		result = ERR_PTR(-ENOMEM);
  		if (dentry) {
  			lock_kernel();
@@ -184,7 +184,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  			result = dir->i_op->lookup(dir, dentry);
  			unlock_kernel();
  			if (result)
-@@ -321,6 +344,15 @@
+@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc
  			dput(result);
  			result = ERR_PTR(-ENOENT);
  		}
@@ -200,7 +200,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	}
  	return result;
  }
-@@ -332,7 +364,8 @@
+@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc
   * Without that kind of total limit, nasty chains of consecutive
   * symlinks can cause almost arbitrarily long lookups. 
   */
@@ -210,7 +210,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  {
  	int err;
  	if (current->link_count >= 8)
-@@ -346,10 +379,12 @@
+@@ -346,10 +379,12 @@ static inline int do_follow_link(struct 
  	current->link_count++;
  	current->total_link_count++;
  	UPDATE_ATIME(dentry->d_inode);
@@ -223,7 +223,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	path_release(nd);
  	return -ELOOP;
  }
-@@ -447,7 +482,8 @@
+@@ -447,7 +482,8 @@ static inline void follow_dotdot(struct 
   *
   * We expect 'base' to be positive and a directory.
   */
@@ -233,7 +233,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  {
  	struct dentry *dentry;
  	struct inode *inode;
-@@ -524,12 +560,12 @@
+@@ -524,12 +560,12 @@ int link_path_walk(const char * name, st
  				break;
  		}
  		/* This does the actual lookups.. */
@@ -248,7 +248,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  			err = PTR_ERR(dentry);
  			if (IS_ERR(dentry))
  				break;
-@@ -547,7 +583,7 @@
+@@ -547,7 +583,7 @@ int link_path_walk(const char * name, st
  			goto out_dput;
  
  		if (inode->i_op->follow_link) {
@@ -257,7 +257,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  			dput(dentry);
  			if (err)
  				goto return_err;
-@@ -563,7 +599,7 @@
+@@ -563,7 +599,7 @@ int link_path_walk(const char * name, st
  			nd->dentry = dentry;
  		}
  		err = -ENOTDIR; 
@@ -266,7 +266,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  			break;
  		continue;
  		/* here ends the main loop */
-@@ -590,12 +626,12 @@
+@@ -590,12 +626,12 @@ last_component:
  			if (err < 0)
  				break;
  		}
@@ -281,7 +281,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  			err = PTR_ERR(dentry);
  			if (IS_ERR(dentry))
  				break;
-@@ -605,7 +641,7 @@
+@@ -605,7 +641,7 @@ last_component:
  		inode = dentry->d_inode;
  		if ((lookup_flags & LOOKUP_FOLLOW)
  		    && inode && inode->i_op && inode->i_op->follow_link) {
@@ -290,7 +290,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  			dput(dentry);
  			if (err)
  				goto return_err;
-@@ -619,7 +655,8 @@
+@@ -619,7 +655,8 @@ last_component:
  			goto no_inode;
  		if (lookup_flags & LOOKUP_DIRECTORY) {
  			err = -ENOTDIR; 
@@ -300,7 +300,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  				break;
  		}
  		goto return_base;
-@@ -643,6 +680,25 @@
+@@ -643,6 +680,27 @@ return_reval:
  		 * Check the cached dentry for staleness.
  		 */
  		dentry = nd->dentry;
@@ -316,17 +316,19 @@ Index: linux-2.4.21-chaos/fs/namei.c
 +						&dentry->d_name, 0, NULL);
 +				d_invalidate(dentry);
 +				dput(dentry);
-+				if (IS_ERR(new)) { 
++				if (IS_ERR(new)) {
 +					err = PTR_ERR(new);
 +					break;
 +				}
 +				nd->dentry = new;
 +			}
++			if (!nd->dentry->d_inode)
++				goto no_inode;
 +		} else
  		if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
  			err = -ESTALE;
  			if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -656,15 +712,28 @@
+@@ -656,15 +714,28 @@ out_dput:
  		dput(dentry);
  		break;
  	}
@@ -356,7 +358,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  }
  
  /* SMP-safe */
-@@ -749,6 +818,17 @@
+@@ -749,6 +820,17 @@ walk_init_root(const char *name, struct 
  }
  
  /* SMP-safe */
@@ -374,7 +376,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
  {
  	int error = 0;
-@@ -763,6 +843,7 @@
+@@ -763,6 +845,7 @@ int path_init(const char *name, unsigned
  {
  	nd->last_type = LAST_ROOT; /* if there are only slashes... */
  	nd->flags = flags;
@@ -382,7 +384,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	if (*name=='/')
  		return walk_init_root(name,nd);
  	read_lock(&current->fs->lock);
-@@ -777,7 +858,8 @@
+@@ -777,7 +860,8 @@ int path_init(const char *name, unsigned
   * needs parent already locked. Doesn't follow mounts.
   * SMP-safe.
   */
@@ -392,7 +394,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  {
  	struct dentry * dentry;
  	struct inode *inode;
-@@ -800,13 +882,16 @@
+@@ -800,13 +884,16 @@ struct dentry * lookup_hash(struct qstr 
  			goto out;
  	}
  
@@ -410,7 +412,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  		dentry = inode->i_op->lookup(inode, new);
  		unlock_kernel();
  		if (!dentry)
-@@ -818,6 +903,12 @@
+@@ -818,6 +905,12 @@ out:
  	return dentry;
  }
  
@@ -423,7 +425,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  /* SMP-safe */
  struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
  {
-@@ -839,7 +930,7 @@
+@@ -839,7 +932,7 @@ struct dentry * lookup_one_len(const cha
  	}
  	this.hash = end_name_hash(hash);
  
@@ -432,7 +434,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  access:
  	return ERR_PTR(-EACCES);
  }
-@@ -870,6 +961,23 @@
+@@ -870,6 +963,23 @@ int __user_walk(const char *name, unsign
  	return err;
  }
  
@@ -456,7 +458,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  /*
   * It's inline, so penalty for filesystems that don't use sticky bit is
   * minimal.
-@@ -967,7 +1075,8 @@
+@@ -967,7 +1077,8 @@ static inline int lookup_flags(unsigned 
  	return retval;
  }
  
@@ -466,7 +468,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  {
  	int error;
  
-@@ -980,12 +1089,15 @@
+@@ -980,12 +1091,15 @@ int vfs_create(struct inode *dir, struct
  		goto exit_lock;
  
  	error = -EACCES;	/* shouldn't it be ENOSYS? */
@@ -484,7 +486,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	unlock_kernel();
  exit_lock:
  	up(&dir->i_zombie);
-@@ -994,6 +1106,11 @@
+@@ -994,6 +1108,11 @@ exit_lock:
  	return error;
  }
  
@@ -496,7 +498,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  /*
   *	open_namei()
   *
-@@ -1008,7 +1125,8 @@
+@@ -1008,7 +1127,8 @@ exit_lock:
   * for symlinks (where the permissions are checked later).
   * SMP-safe
   */
@@ -506,7 +508,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  {
  	int acc_mode, error = 0;
  	struct inode *inode;
-@@ -1018,11 +1136,14 @@
+@@ -1018,11 +1138,14 @@ int open_namei(const char * pathname, in
  
  	acc_mode = ACC_MODE(flag);
  
@@ -522,7 +524,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  		if (error)
  			return error;
  		dentry = nd->dentry;
-@@ -1032,6 +1153,10 @@
+@@ -1032,6 +1155,10 @@ int open_namei(const char * pathname, in
  	/*
  	 * Create - we need to know the parent.
  	 */
@@ -533,7 +535,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	error = path_lookup(pathname, LOOKUP_PARENT, nd);
  	if (error)
  		return error;
-@@ -1047,7 +1172,7 @@
+@@ -1047,7 +1174,7 @@ int open_namei(const char * pathname, in
  
  	dir = nd->dentry;
  	down(&dir->d_inode->i_sem);
@@ -542,7 +544,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  
  do_last:
  	error = PTR_ERR(dentry);
-@@ -1056,11 +1181,12 @@
+@@ -1056,11 +1183,12 @@ do_last:
  		goto exit;
  	}
  
@@ -556,7 +558,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  		up(&dir->d_inode->i_sem);
  		dput(nd->dentry);
  		nd->dentry = dentry;
-@@ -1164,7 +1290,7 @@
+@@ -1164,7 +1292,7 @@ ok:
  		if (!error) {
  			DQUOT_INIT(inode);
  			
@@ -565,7 +567,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  		}
  		put_write_access(inode);
  		if (error)
-@@ -1176,8 +1302,10 @@
+@@ -1176,8 +1304,10 @@ ok:
  	return 0;
  
  exit_dput:
@@ -576,7 +578,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	path_release(nd);
  	return error;
  
-@@ -1196,7 +1324,10 @@
+@@ -1196,7 +1326,10 @@ do_link:
  	 * are done. Procfs-like symlinks just set LAST_BIND.
  	 */
  	UPDATE_ATIME(dentry->d_inode);
@@ -587,7 +589,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	dput(dentry);
  	if (error)
  		return error;
-@@ -1218,13 +1349,20 @@
+@@ -1218,13 +1351,20 @@ do_link:
  	}
  	dir = nd->dentry;
  	down(&dir->d_inode->i_sem);
@@ -610,7 +612,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  {
  	struct dentry *dentry;
  
-@@ -1232,7 +1370,7 @@
+@@ -1232,7 +1372,7 @@ static struct dentry *lookup_create(stru
  	dentry = ERR_PTR(-EEXIST);
  	if (nd->last_type != LAST_NORM)
  		goto fail;
@@ -619,12 +621,16 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	if (IS_ERR(dentry))
  		goto fail;
  	if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1288,7 +1426,16 @@
+@@ -1288,7 +1428,20 @@ asmlinkage long sys_mknod(const char * f
  	error = path_lookup(tmp, LOOKUP_PARENT, &nd);
  	if (error)
  		goto out;
 -	dentry = lookup_create(&nd, 0);
 +
++	if (nd.last_type != LAST_NORM) {
++		error = -EEXIST;
++		goto out2;
++	}
 +	if (nd.dentry->d_inode->i_op->mknod_raw) {
 +		struct inode_operations *op = nd.dentry->d_inode->i_op;
 +		error = op->mknod_raw(&nd, mode, dev);
@@ -637,7 +643,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	error = PTR_ERR(dentry);
  
  	if (!IS_POSIXACL(nd.dentry->d_inode))
-@@ -1310,6 +1457,7 @@
+@@ -1310,6 +1463,7 @@ asmlinkage long sys_mknod(const char * f
  		dput(dentry);
  	}
  	up(&nd.dentry->d_inode->i_sem);
@@ -645,11 +651,15 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	path_release(&nd);
  out:
  	putname(tmp);
-@@ -1357,7 +1505,14 @@
+@@ -1357,7 +1511,18 @@ asmlinkage long sys_mkdir(const char * p
  		error = path_lookup(tmp, LOOKUP_PARENT, &nd);
  		if (error)
  			goto out;
 -		dentry = lookup_create(&nd, 1);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out2;
++		}
 +		if (nd.dentry->d_inode->i_op->mkdir_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->mkdir_raw(&nd, mode);
@@ -661,7 +671,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  		error = PTR_ERR(dentry);
  		if (!IS_ERR(dentry)) {
  			if (!IS_POSIXACL(nd.dentry->d_inode))
-@@ -1366,6 +1521,7 @@
+@@ -1366,6 +1531,7 @@ asmlinkage long sys_mkdir(const char * p
  			dput(dentry);
  		}
  		up(&nd.dentry->d_inode->i_sem);
@@ -669,7 +679,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  		path_release(&nd);
  out:
  		putname(tmp);
-@@ -1466,8 +1622,16 @@
+@@ -1466,8 +1632,16 @@ asmlinkage long sys_rmdir(const char * p
  			error = -EBUSY;
  			goto exit1;
  	}
@@ -687,7 +697,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	error = PTR_ERR(dentry);
  	if (!IS_ERR(dentry)) {
  		error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1525,8 +1689,15 @@
+@@ -1525,8 +1699,15 @@ asmlinkage long sys_unlink(const char * 
  	error = -EISDIR;
  	if (nd.last_type != LAST_NORM)
  		goto exit1;
@@ -704,11 +714,15 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	error = PTR_ERR(dentry);
  	if (!IS_ERR(dentry)) {
  		/* Why not before? Because we want correct error value */
-@@ -1593,15 +1764,23 @@
+@@ -1593,15 +1774,27 @@ asmlinkage long sys_symlink(const char *
  		error = path_lookup(to, LOOKUP_PARENT, &nd);
  		if (error)
  			goto out;
 -		dentry = lookup_create(&nd, 0);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out2;
++		}
 +		if (nd.dentry->d_inode->i_op->symlink_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->symlink_raw(&nd, from);
@@ -730,11 +744,15 @@ Index: linux-2.4.21-chaos/fs/namei.c
  		putname(to);
  	}
  	putname(from);
-@@ -1677,7 +1856,14 @@
+@@ -1677,7 +1870,18 @@ asmlinkage long sys_link(const char * ol
  		error = -EXDEV;
  		if (old_nd.mnt != nd.mnt)
  			goto out_release;
 -		new_dentry = lookup_create(&nd, 0);
++		if (nd.last_type != LAST_NORM) {
++			error = -EEXIST;
++			goto out_release;
++		}
 +		if (nd.dentry->d_inode->i_op->link_raw) {
 +			struct inode_operations *op = nd.dentry->d_inode->i_op;
 +			error = op->link_raw(&old_nd, &nd);
@@ -746,7 +764,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  		error = PTR_ERR(new_dentry);
  		if (!IS_ERR(new_dentry)) {
  			error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1721,7 +1907,7 @@
+@@ -1721,7 +1925,7 @@ exit:
   *	   locking].
   */
  int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
@@ -755,7 +773,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  {
  	int error;
  	struct inode *target;
-@@ -1800,7 +1986,7 @@
+@@ -1800,7 +2004,7 @@ out_unlock:
  }
  
  int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
@@ -764,7 +782,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  {
  	int error;
  
-@@ -1888,9 +2074,18 @@
+@@ -1888,9 +2092,18 @@ static inline int do_rename(const char *
  	if (newnd.last_type != LAST_NORM)
  		goto exit2;
  
@@ -784,7 +802,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	error = PTR_ERR(old_dentry);
  	if (IS_ERR(old_dentry))
  		goto exit3;
-@@ -1906,16 +2101,16 @@
+@@ -1906,16 +2119,16 @@ static inline int do_rename(const char *
  		if (newnd.last.name[newnd.last.len])
  			goto exit4;
  	}
@@ -803,7 +821,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	dput(new_dentry);
  exit4:
  	dput(old_dentry);
-@@ -1966,20 +2161,26 @@
+@@ -1966,20 +2179,26 @@ out:
  }
  
  static inline int
@@ -832,7 +850,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  out:
  	if (current->link_count || res || nd->last_type!=LAST_NORM)
  		return res;
-@@ -2003,7 +2204,13 @@
+@@ -2003,7 +2222,13 @@ fail:
  
  int vfs_follow_link(struct nameidata *nd, const char *link)
  {
@@ -847,7 +865,7 @@ Index: linux-2.4.21-chaos/fs/namei.c
  }
  
  /* get the link contents into pagecache */
-@@ -2045,7 +2252,7 @@
+@@ -2045,7 +2270,7 @@ int page_follow_link(struct dentry *dent
  {
  	struct page *page = NULL;
  	char *s = page_getlink(dentry, &page);
@@ -856,11 +874,11 @@ Index: linux-2.4.21-chaos/fs/namei.c
  	if (page) {
  		kunmap(page);
  		page_cache_release(page);
-Index: linux-2.4.21-chaos/fs/namespace.c
+Index: linux-ia64/fs/namespace.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/namespace.c	2003-07-15 04:41:01.000000000 +0400
-+++ linux-2.4.21-chaos/fs/namespace.c	2003-12-12 17:02:47.000000000 +0300
-@@ -98,6 +98,7 @@
+--- linux-ia64.orig/fs/namespace.c	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/fs/namespace.c	2004-03-17 16:05:28.000000000 -0800
+@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount *
  {
  	old_nd->dentry = mnt->mnt_mountpoint;
  	old_nd->mnt = mnt->mnt_parent;
@@ -868,7 +886,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	mnt->mnt_parent = mnt;
  	mnt->mnt_mountpoint = mnt->mnt_root;
  	list_del_init(&mnt->mnt_child);
-@@ -109,6 +110,7 @@
+@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount *
  {
  	mnt->mnt_parent = mntget(nd->mnt);
  	mnt->mnt_mountpoint = dget(nd->dentry);
@@ -876,7 +894,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
  	list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
  	nd->dentry->d_mounted++;
-@@ -488,14 +490,17 @@
+@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata 
  {
  	struct nameidata old_nd;
  	struct vfsmount *mnt = NULL;
@@ -896,7 +914,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  
  	down_write(&current->namespace->sem);
  	err = -EINVAL;
-@@ -518,6 +523,7 @@
+@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata 
  	}
  
  	up_write(&current->namespace->sem);
@@ -904,7 +922,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	path_release(&old_nd);
  	return err;
  }
-@@ -701,6 +707,7 @@
+@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di
  		  unsigned long flags, void *data_page)
  {
  	struct nameidata nd;
@@ -912,7 +930,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	int retval = 0;
  	int mnt_flags = 0;
  
-@@ -725,10 +732,11 @@
+@@ -725,10 +732,11 @@ long do_mount(char * dev_name, char * di
  	flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
  
  	/* ... and get the mountpoint */
@@ -927,7 +945,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	if (flags & MS_REMOUNT)
  		retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
  				    data_page);
-@@ -739,6 +747,8 @@
+@@ -739,6 +747,8 @@ long do_mount(char * dev_name, char * di
  	else
  		retval = do_add_mount(&nd, type_page, flags, mnt_flags,
  				      dev_name, data_page);
@@ -936,7 +954,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	path_release(&nd);
  	return retval;
  }
-@@ -904,6 +914,8 @@
+@@ -904,6 +914,8 @@ asmlinkage long sys_pivot_root(const cha
  {
  	struct vfsmount *tmp;
  	struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
@@ -945,7 +963,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	int error;
  
  	if (!capable(CAP_SYS_ADMIN))
-@@ -911,14 +923,14 @@
+@@ -911,14 +923,14 @@ asmlinkage long sys_pivot_root(const cha
  
  	lock_kernel();
  
@@ -962,7 +980,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	if (error)
  		goto out1;
  
-@@ -973,8 +985,10 @@
+@@ -973,8 +985,10 @@ out2:
  	up(&old_nd.dentry->d_inode->i_zombie);
  	up_write(&current->namespace->sem);
  	path_release(&user_nd);
@@ -973,10 +991,10 @@ Index: linux-2.4.21-chaos/fs/namespace.c
  	path_release(&new_nd);
  out0:
  	unlock_kernel();
-Index: linux-2.4.21-chaos/fs/open.c
+Index: linux-ia64/fs/open.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/open.c	2003-07-15 04:41:01.000000000 +0400
-+++ linux-2.4.21-chaos/fs/open.c	2003-12-12 17:02:47.000000000 +0300
+--- linux-ia64.orig/fs/open.c	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/fs/open.c	2004-03-17 16:05:28.000000000 -0800
 @@ -19,6 +19,8 @@
  #include <asm/uaccess.h>
  
@@ -986,7 +1004,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  
  int vfs_statfs(struct super_block *sb, struct statfs *buf)
  {
-@@ -95,9 +97,10 @@
+@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct 
  	write_unlock(&files->file_lock);
  }
  
@@ -998,7 +1016,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	int error;
  	struct iattr newattrs;
  
-@@ -109,7 +112,13 @@
+@@ -109,7 +112,13 @@ int do_truncate(struct dentry *dentry, l
  	down(&inode->i_sem);
  	newattrs.ia_size = length;
  	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
@@ -1013,7 +1031,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	up(&inode->i_sem);
  	up_write(&inode->i_alloc_sem);
  	return error;
-@@ -120,12 +129,13 @@
+@@ -120,12 +129,13 @@ static inline long do_sys_truncate(const
  	struct nameidata nd;
  	struct inode * inode;
  	int error;
@@ -1028,7 +1046,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	if (error)
  		goto out;
  	inode = nd.dentry->d_inode;
-@@ -165,11 +175,13 @@
+@@ -165,11 +175,13 @@ static inline long do_sys_truncate(const
  	error = locks_verify_truncate(inode, NULL, length);
  	if (!error) {
  		DQUOT_INIT(inode);
@@ -1043,7 +1061,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	path_release(&nd);
  out:
  	return error;
-@@ -217,7 +229,7 @@
+@@ -217,7 +229,7 @@ static inline long do_sys_ftruncate(unsi
  
  	error = locks_verify_truncate(inode, file, length);
  	if (!error)
@@ -1052,7 +1070,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  out_putf:
  	fput(file);
  out:
-@@ -262,11 +274,13 @@
+@@ -262,11 +274,13 @@ asmlinkage long sys_utime(char * filenam
  	struct inode * inode;
  	struct iattr newattrs;
  
@@ -1067,7 +1085,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto dput_and_out;
-@@ -281,11 +295,25 @@
+@@ -281,11 +295,25 @@ asmlinkage long sys_utime(char * filenam
  			goto dput_and_out;
  
  		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1094,7 +1112,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	error = notify_change(nd.dentry, &newattrs);
  dput_and_out:
  	path_release(&nd);
-@@ -306,12 +334,14 @@
+@@ -306,12 +334,14 @@ asmlinkage long sys_utimes(char * filena
  	struct inode * inode;
  	struct iattr newattrs;
  
@@ -1110,7 +1128,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto dput_and_out;
-@@ -326,7 +356,20 @@
+@@ -326,7 +356,20 @@ asmlinkage long sys_utimes(char * filena
  		newattrs.ia_atime = times[0].tv_sec;
  		newattrs.ia_mtime = times[1].tv_sec;
  		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -1132,7 +1150,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  		if (current->fsuid != inode->i_uid &&
  		    (error = permission(inode,MAY_WRITE)) != 0)
  			goto dput_and_out;
-@@ -349,6 +392,7 @@
+@@ -349,6 +392,7 @@ asmlinkage long sys_access(const char * 
  	int old_fsuid, old_fsgid;
  	kernel_cap_t old_cap;
  	int res;
@@ -1140,7 +1158,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  
  	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
  		return -EINVAL;
-@@ -366,13 +410,14 @@
+@@ -366,13 +410,14 @@ asmlinkage long sys_access(const char * 
  	else
  		current->cap_effective = current->cap_permitted;
  
@@ -1156,7 +1174,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  		path_release(&nd);
  	}
  
-@@ -387,8 +432,9 @@
+@@ -387,8 +432,9 @@ asmlinkage long sys_chdir(const char * f
  {
  	int error;
  	struct nameidata nd;
@@ -1167,7 +1185,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	if (error)
  		goto out;
  
-@@ -399,6 +445,7 @@
+@@ -399,6 +445,7 @@ asmlinkage long sys_chdir(const char * f
  	set_fs_pwd(current->fs, nd.mnt, nd.dentry);
  
  dput_and_out:
@@ -1175,7 +1193,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	path_release(&nd);
  out:
  	return error;
-@@ -438,9 +485,10 @@
+@@ -438,9 +485,10 @@ asmlinkage long sys_chroot(const char * 
  {
  	int error;
  	struct nameidata nd;
@@ -1188,7 +1206,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	if (error)
  		goto out;
  
-@@ -456,39 +504,56 @@
+@@ -456,39 +504,56 @@ asmlinkage long sys_chroot(const char * 
  	set_fs_altroot();
  	error = 0;
  dput_and_out:
@@ -1259,7 +1277,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	fput(file);
  out:
  	return err;
-@@ -497,30 +562,14 @@
+@@ -497,30 +562,14 @@ out:
  asmlinkage long sys_chmod(const char * filename, mode_t mode)
  {
  	struct nameidata nd;
@@ -1291,7 +1309,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	path_release(&nd);
  out:
  	return error;
-@@ -540,6 +589,20 @@
+@@ -540,6 +589,20 @@ static int chown_common(struct dentry * 
  	error = -EROFS;
  	if (IS_RDONLY(inode))
  		goto out;
@@ -1312,7 +1330,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	error = -EPERM;
  	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out;
-@@ -644,6 +707,7 @@
+@@ -644,6 +707,7 @@ struct file *filp_open(const char * file
  {
  	int namei_flags, error;
  	struct nameidata nd;
@@ -1320,7 +1338,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  
  	namei_flags = flags;
  	if ((namei_flags+1) & O_ACCMODE)
-@@ -651,14 +715,15 @@
+@@ -651,14 +715,15 @@ struct file *filp_open(const char * file
  	if (namei_flags & O_TRUNC)
  		namei_flags |= 2;
  
@@ -1341,7 +1359,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  {
  	struct file * f;
  	struct inode *inode;
-@@ -695,7 +760,9 @@
+@@ -695,7 +760,9 @@ struct file *dentry_open(struct dentry *
  	}
  
  	if (f->f_op && f->f_op->open) {
@@ -1351,7 +1369,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  		if (error)
  			goto cleanup_all;
  	}
-@@ -708,6 +775,7 @@
+@@ -708,6 +775,7 @@ struct file *dentry_open(struct dentry *
  					inode->i_mapping->a_ops->direct_sector_IO)))
  		goto cleanup_all;
  
@@ -1359,7 +1377,7 @@ Index: linux-2.4.21-chaos/fs/open.c
  	return f;
  
  cleanup_all:
-@@ -722,11 +790,17 @@
+@@ -722,11 +790,17 @@ cleanup_all:
  cleanup_file:
  	put_filp(f);
  cleanup_dentry:
@@ -1377,11 +1395,11 @@ Index: linux-2.4.21-chaos/fs/open.c
  /*
   * Find an empty file descriptor entry, and mark it busy.
   */
-Index: linux-2.4.21-chaos/fs/stat.c
+Index: linux-ia64/fs/stat.c
 ===================================================================
---- linux-2.4.21-chaos.orig/fs/stat.c	2003-09-19 03:49:54.000000000 +0400
-+++ linux-2.4.21-chaos/fs/stat.c	2003-12-12 17:02:47.000000000 +0300
-@@ -17,10 +17,14 @@
+--- linux-ia64.orig/fs/stat.c	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/fs/stat.c	2004-03-17 16:06:13.000000000 -0800
+@@ -17,10 +17,12 @@
   * Revalidate the inode. This is required for proper NFS attribute caching.
   */
  static __inline__ int
@@ -1390,15 +1408,13 @@ Index: linux-2.4.21-chaos/fs/stat.c
  {
  	struct inode * inode = dentry->d_inode;
 -	if (inode->i_op && inode->i_op->revalidate)
-+	if (!inode)
-+		return -ENOENT;
 +	if (inode->i_op && inode->i_op->revalidate_it)
 +		return inode->i_op->revalidate_it(dentry, it);
 +	else if (inode->i_op && inode->i_op->revalidate)
  		return inode->i_op->revalidate(dentry);
  	return 0;
  }
-@@ -143,13 +147,15 @@
+@@ -143,13 +145,15 @@ static int cp_new_stat(struct inode * in
  asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
  {
  	struct nameidata nd;
@@ -1416,7 +1432,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		path_release(&nd);
  	}
  	return error;
-@@ -159,13 +165,15 @@
+@@ -159,13 +163,15 @@ asmlinkage long sys_stat(char * filename
  asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
  {
  	struct nameidata nd;
@@ -1434,7 +1450,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		path_release(&nd);
  	}
  	return error;
-@@ -180,13 +188,15 @@
+@@ -180,13 +186,15 @@ asmlinkage long sys_newstat(char * filen
  asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
  {
  	struct nameidata nd;
@@ -1452,7 +1468,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		path_release(&nd);
  	}
  	return error;
-@@ -197,13 +207,15 @@
+@@ -197,13 +205,15 @@ asmlinkage long sys_lstat(char * filenam
  asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
  {
  	struct nameidata nd;
@@ -1470,7 +1486,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		path_release(&nd);
  	}
  	return error;
-@@ -224,7 +236,7 @@
+@@ -224,7 +234,7 @@ asmlinkage long sys_fstat(unsigned int f
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1479,7 +1495,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		if (!err)
  			err = cp_old_stat(dentry->d_inode, statbuf);
  		fput(f);
-@@ -243,7 +255,7 @@
+@@ -243,7 +253,7 @@ asmlinkage long sys_newfstat(unsigned in
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1488,7 +1504,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		if (!err)
  			err = cp_new_stat(dentry->d_inode, statbuf);
  		fput(f);
-@@ -265,7 +277,7 @@
+@@ -265,7 +275,7 @@ asmlinkage long sys_readlink(const char 
  
  		error = -EINVAL;
  		if (inode->i_op && inode->i_op->readlink &&
@@ -1497,7 +1513,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  			UPDATE_ATIME(inode);
  			error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
  		}
-@@ -341,12 +353,14 @@
+@@ -341,12 +351,14 @@ asmlinkage long sys_stat64(char * filena
  {
  	struct nameidata nd;
  	int error;
@@ -1514,7 +1530,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		path_release(&nd);
  	}
  	return error;
-@@ -356,12 +370,14 @@
+@@ -356,12 +368,14 @@ asmlinkage long sys_lstat64(char * filen
  {
  	struct nameidata nd;
  	int error;
@@ -1531,7 +1547,7 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		path_release(&nd);
  	}
  	return error;
-@@ -376,7 +392,7 @@
+@@ -376,7 +390,7 @@ asmlinkage long sys_fstat64(unsigned lon
  	if (f) {
  		struct dentry * dentry = f->f_dentry;
  
@@ -1540,10 +1556,10 @@ Index: linux-2.4.21-chaos/fs/stat.c
  		if (!err)
  			err = cp_new_stat64(dentry->d_inode, statbuf);
  		fput(f);
-Index: linux-2.4.21-chaos/include/linux/dcache.h
+Index: linux-ia64/include/linux/dcache.h
 ===================================================================
---- linux-2.4.21-chaos.orig/include/linux/dcache.h	2003-12-05 16:54:33.000000000 +0300
-+++ linux-2.4.21-chaos/include/linux/dcache.h	2003-12-12 17:02:47.000000000 +0300
+--- linux-ia64.orig/include/linux/dcache.h	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/include/linux/dcache.h	2004-03-17 16:05:28.000000000 -0800
 @@ -6,6 +6,51 @@
  #include <asm/atomic.h>
  #include <linux/mount.h>
@@ -1596,7 +1612,7 @@ Index: linux-2.4.21-chaos/include/linux/dcache.h
  
  /*
   * linux/include/linux/dcache.h
-@@ -96,8 +141,22 @@
+@@ -96,8 +141,22 @@ struct dentry_operations {
  	int (*d_delete)(struct dentry *);
  	void (*d_release)(struct dentry *);
  	void (*d_iput)(struct dentry *, struct inode *);
@@ -1619,7 +1635,7 @@ Index: linux-2.4.21-chaos/include/linux/dcache.h
  /* the dentry parameter passed to d_hash and d_compare is the parent
   * directory of the entries to be compared. It is used in case these
   * functions need any directory specific information for determining
-@@ -129,6 +188,7 @@
+@@ -129,6 +188,7 @@ d_iput:		no		no		yes
  					 * s_nfsd_free_path semaphore will be down
  					 */
  #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
@@ -1627,11 +1643,11 @@ Index: linux-2.4.21-chaos/include/linux/dcache.h
  
  extern spinlock_t dcache_lock;
  
-Index: linux-2.4.21-chaos/include/linux/fs.h
+Index: linux-ia64/include/linux/fs.h
 ===================================================================
---- linux-2.4.21-chaos.orig/include/linux/fs.h	2003-12-12 17:02:46.000000000 +0300
-+++ linux-2.4.21-chaos/include/linux/fs.h	2003-12-12 17:02:47.000000000 +0300
-@@ -73,6 +73,7 @@
+--- linux-ia64.orig/include/linux/fs.h	2004-03-17 16:05:28.000000000 -0800
++++ linux-ia64/include/linux/fs.h	2004-03-17 16:05:52.000000000 -0800
+@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena
  
  #define FMODE_READ 1
  #define FMODE_WRITE 2
@@ -1639,7 +1655,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  
  #define READ 0
  #define WRITE 1
-@@ -359,6 +360,9 @@
+@@ -359,6 +360,9 @@ extern void set_bh_page(struct buffer_he
  #define ATTR_MTIME_SET	256
  #define ATTR_FORCE	512	/* Not a change, but a change it */
  #define ATTR_ATTR_FLAG	1024
@@ -1649,7 +1665,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  
  /*
   * This is the Inode Attributes structure, used for notify_change().  It
-@@ -496,6 +500,7 @@
+@@ -496,6 +500,7 @@ struct inode {
  	struct pipe_inode_info	*i_pipe;
  	struct block_device	*i_bdev;
  	struct char_device	*i_cdev;
@@ -1657,7 +1673,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  
  	unsigned long		i_dnotify_mask; /* Directory notify events */
  	struct dnotify_struct	*i_dnotify; /* for directory notifications */
-@@ -598,6 +603,7 @@
+@@ -598,6 +603,7 @@ struct file {
  
  	/* needed for tty driver, and maybe others */
  	void			*private_data;
@@ -1665,7 +1681,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  
  	/* preallocated helper kiobuf to speedup O_DIRECT */
  	struct kiobuf		*f_iobuf;
-@@ -726,6 +732,7 @@
+@@ -726,6 +732,7 @@ struct nameidata {
  	struct qstr last;
  	unsigned int flags;
  	int last_type;
@@ -1673,7 +1689,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  };
  
  /*
-@@ -846,7 +853,8 @@
+@@ -846,7 +853,8 @@ extern int vfs_symlink(struct inode *, s
  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
  extern int vfs_rmdir(struct inode *, struct dentry *);
  extern int vfs_unlink(struct inode *, struct dentry *);
@@ -1683,7 +1699,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  
  /*
   * File types
-@@ -920,21 +928,32 @@
+@@ -920,21 +928,32 @@ struct file_operations {
  
  struct inode_operations {
  	int (*create) (struct inode *,struct dentry *,int);
@@ -1716,7 +1732,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  	int (*getattr) (struct dentry *, struct iattr *);
  	int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
  	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -1131,10 +1150,14 @@
+@@ -1131,10 +1150,14 @@ static inline int get_lease(struct inode
  
  asmlinkage long sys_open(const char *, int, int);
  asmlinkage long sys_close(unsigned int);	/* yes, it's really unsigned */
@@ -1732,7 +1748,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  extern int filp_close(struct file *, fl_owner_t id);
  extern char * getname(const char *);
  
-@@ -1425,6 +1448,7 @@
+@@ -1425,6 +1448,7 @@ typedef int (*read_actor_t)(read_descrip
  extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
  
  extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
@@ -1740,7 +1756,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
  extern int FASTCALL(path_walk(const char *, struct nameidata *));
  extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1436,6 +1460,8 @@
+@@ -1436,6 +1460,8 @@ extern struct dentry * lookup_one_len(co
  extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
  #define user_path_walk(name,nd)	 __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
  #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
@@ -1749,7 +1765,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  
  extern void inode_init_once(struct inode *);
  extern void iput(struct inode *);
-@@ -1599,6 +1625,8 @@
+@@ -1599,6 +1625,8 @@ extern struct file_operations generic_ro
  
  extern int vfs_readlink(struct dentry *, char *, int, const char *);
  extern int vfs_follow_link(struct nameidata *, const char *);
@@ -1758,11 +1774,11 @@ Index: linux-2.4.21-chaos/include/linux/fs.h
  extern int page_readlink(struct dentry *, char *, int);
  extern int page_follow_link(struct dentry *, struct nameidata *);
  extern struct inode_operations page_symlink_inode_operations;
-Index: linux-2.4.21-chaos/include/linux/fs_struct.h
+Index: linux-ia64/include/linux/fs_struct.h
 ===================================================================
---- linux-2.4.21-chaos.orig/include/linux/fs_struct.h	2003-12-05 16:54:33.000000000 +0300
-+++ linux-2.4.21-chaos/include/linux/fs_struct.h	2003-12-12 17:02:47.000000000 +0300
-@@ -37,10 +37,12 @@
+--- linux-ia64.orig/include/linux/fs_struct.h	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/include/linux/fs_struct.h	2004-03-17 16:05:28.000000000 -0800
+@@ -37,10 +37,12 @@ static inline void set_fs_root(struct fs
  	write_lock(&fs->lock);
  	old_root = fs->root;
  	old_rootmnt = fs->rootmnt;
@@ -1775,7 +1791,7 @@ Index: linux-2.4.21-chaos/include/linux/fs_struct.h
  		dput(old_root);
  		mntput(old_rootmnt);
  	}
-@@ -60,10 +62,12 @@
+@@ -60,10 +62,12 @@ static inline void set_fs_pwd(struct fs_
  	write_lock(&fs->lock);
  	old_pwd = fs->pwd;
  	old_pwdmnt = fs->pwdmnt;
@@ -1788,11 +1804,11 @@ Index: linux-2.4.21-chaos/include/linux/fs_struct.h
  		dput(old_pwd);
  		mntput(old_pwdmnt);
  	}
-Index: linux-2.4.21-chaos/kernel/exit.c
+Index: linux-ia64/kernel/exit.c
 ===================================================================
---- linux-2.4.21-chaos.orig/kernel/exit.c	2003-09-19 03:50:00.000000000 +0400
-+++ linux-2.4.21-chaos/kernel/exit.c	2003-12-12 17:02:47.000000000 +0300
-@@ -347,11 +347,14 @@
+--- linux-ia64.orig/kernel/exit.c	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/kernel/exit.c	2004-03-17 16:05:28.000000000 -0800
+@@ -347,11 +347,14 @@ static inline void __put_fs_struct(struc
  {
  	/* No need to hold fs->lock if we are killing it */
  	if (atomic_dec_and_test(&fs->count)) {
@@ -1807,11 +1823,11 @@ Index: linux-2.4.21-chaos/kernel/exit.c
  			dput(fs->altroot);
  			mntput(fs->altrootmnt);
  		}
-Index: linux-2.4.21-chaos/kernel/fork.c
+Index: linux-ia64/kernel/fork.c
 ===================================================================
---- linux-2.4.21-chaos.orig/kernel/fork.c	2003-12-05 07:55:51.000000000 +0300
-+++ linux-2.4.21-chaos/kernel/fork.c	2003-12-12 17:02:47.000000000 +0300
-@@ -463,10 +463,13 @@
+--- linux-ia64.orig/kernel/fork.c	2004-03-17 15:47:15.000000000 -0800
++++ linux-ia64/kernel/fork.c	2004-03-17 16:05:28.000000000 -0800
+@@ -463,10 +463,13 @@ static inline struct fs_struct *__copy_f
  		fs->umask = old->umask;
  		read_lock(&old->lock);
  		fs->rootmnt = mntget(old->rootmnt);
@@ -1825,11 +1841,11 @@ Index: linux-2.4.21-chaos/kernel/fork.c
  			fs->altrootmnt = mntget(old->altrootmnt);
  			fs->altroot = dget(old->altroot);
  		} else {
-Index: linux-2.4.21-chaos/kernel/ksyms.c
+Index: linux-ia64/kernel/ksyms.c
 ===================================================================
---- linux-2.4.21-chaos.orig/kernel/ksyms.c	2003-12-12 17:02:46.000000000 +0300
-+++ linux-2.4.21-chaos/kernel/ksyms.c	2003-12-12 17:02:47.000000000 +0300
-@@ -318,6 +318,7 @@
+--- linux-ia64.orig/kernel/ksyms.c	2004-03-17 16:05:28.000000000 -0800
++++ linux-ia64/kernel/ksyms.c	2004-03-17 16:05:51.000000000 -0800
+@@ -318,6 +318,7 @@ EXPORT_SYMBOL(read_cache_page);
  EXPORT_SYMBOL(set_page_dirty);
  EXPORT_SYMBOL(vfs_readlink);
  EXPORT_SYMBOL(vfs_follow_link);
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch
index 492e32a7344cf73e3f1206e4022916aa7a1747eb..25d147d10757cf30b444022e865737e271350f8b 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch
@@ -316,7 +316,7 @@ Index: linux-2.4.21-suse2/fs/namei.c
 +						&dentry->d_name, 0, NULL);
 +				d_invalidate(dentry);
 +				dput(dentry);
-+				if (IS_ERR(new)) { 
++				if (IS_ERR(new)) {
 +					err = PTR_ERR(new);
 +					break;
 +				}
diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch
index ff5ef612fd2ab24ad723905c8c9cd5157b5c36c3..29ad74f2cf2a211f45a32bd9b073f3b13254bd7f 100644
--- a/lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch
+++ b/lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch
@@ -304,7 +304,7 @@
 +						&dentry->d_name, 0, NULL);
 +				d_invalidate(dentry);
 +				dput(dentry);
-+				if (IS_ERR(new)) { 
++				if (IS_ERR(new)) {
 +					err = PTR_ERR(new);
 +					break;
 +				}
diff --git a/lustre/kernel_patches/series/chaos-2.4.21 b/lustre/kernel_patches/series/chaos-2.4.21
index 8e20c517ea8f2127318654cddf125b584ce38f2b..bdcae1e94506a3c34e1d0d9630c182cd54c6550e 100644
--- a/lustre/kernel_patches/series/chaos-2.4.21
+++ b/lustre/kernel_patches/series/chaos-2.4.21
@@ -32,3 +32,4 @@ ext3-xattr-ptr-arith-fix.patch
 kernel_text_address-2.4.18-chaos.patch
 pagecache-lock-2.4.21-chaos.patch 
 ext3-truncate-buffer-head.patch
+inode-max-readahead-2.4.24.patch
diff --git a/lustre/kernel_patches/series/hp-pnnl-2.4.20 b/lustre/kernel_patches/series/hp-pnnl-2.4.20
index 6cfe6670e1f7234522e4eb0b53b2c10b3210eb2f..cb9c74c671ee0de2e6adafce9140233643f83c67 100644
--- a/lustre/kernel_patches/series/hp-pnnl-2.4.20
+++ b/lustre/kernel_patches/series/hp-pnnl-2.4.20
@@ -2,7 +2,7 @@ configurable-x86-stack-2.4.20.patch
 dev_read_only_hp_2.4.20.patch
 exports_2.4.20-rh-hp.patch
 lustre_version.patch
-vfs_intent-2.4.20-hp.patch
+vfs_intent-2.4.20-hp.patch 
 invalidate_show-2.4.20-hp.patch 
 export-truncate.patch
 iod-stock-24-exports_hp.patch
@@ -42,3 +42,5 @@ gfp_memalloc-2.4.22.patch
 ext3-xattr-ptr-arith-fix.patch
 procfs-ndynamic-2.4.patch
 ext3-truncate-buffer-head.patch
+inode-max-readahead-2.4.24.patch
+dcache_refcount_debug.patch
diff --git a/lustre/kernel_patches/series/rh-2.4.20 b/lustre/kernel_patches/series/rh-2.4.20
index d9c6f394ad491190dd67980d83b1a1e521b79063..06b2642f027663d672048d06c2d16f55fca9ce4f 100644
--- a/lustre/kernel_patches/series/rh-2.4.20
+++ b/lustre/kernel_patches/series/rh-2.4.20
@@ -4,7 +4,7 @@ dsp.patch
 dev_read_only_2.4.20-rh.patch
 exports_2.4.20-rh-hp.patch
 lustre_version.patch
-vfs_intent-2.4.20-rh.patch
+vfs_intent-2.4.20-rh.patch 
 invalidate_show-2.4.20-rh.patch
 iod-rmap-exports-2.4.20.patch
 export-truncate.patch
@@ -28,7 +28,7 @@ ext3-o_direct-1.2.4.20-rh.patch
 ext3-no-write-super-chaos.patch
 dynamic-locks-2.4.20-rh.patch 
 vfs-pdirops-2.4.20-rh.patch 
-ext3-pdirops-2.4.18-chaos.patch
+ext3-pdirops-2.4.20-chaos.patch 
 tcp_zero_copy_2.4.20_chaos.patch
 gpl_header-chaos-2.4.20.patch
 add_page_private.patch
@@ -44,3 +44,4 @@ gfp_memalloc-2.4.20-rh.patch
 ext3-xattr-ptr-arith-fix.patch
 procfs-ndynamic-2.4.patch
 ext3-truncate-buffer-head.patch
+inode-max-readahead-2.4.24.patch
diff --git a/lustre/kernel_patches/series/vanilla-2.4.24 b/lustre/kernel_patches/series/vanilla-2.4.24
index 220d3bcf4cf7a9688ece0d2ccb4bc1bd12c76609..76ee9fa1f9831890eb973d43b1af62732f8dbb74 100644
--- a/lustre/kernel_patches/series/vanilla-2.4.24
+++ b/lustre/kernel_patches/series/vanilla-2.4.24
@@ -5,7 +5,7 @@ configurable-x86-stack-2.4.20.patch
 dev_read_only_2.4.20-rh.patch
 exports_2.4.20-rh-hp.patch
 lustre_version.patch
-vfs_intent-2.4.20-vanilla.patch
+vfs_intent-2.4.20-vanilla.patch 
 invalidate_show.patch
 export-truncate.patch
 iod-stock-exports-2.4.22.patch 
@@ -35,3 +35,4 @@ ext3-xattr-ptr-arith-fix.patch
 3.5G-address-space-2.4.22-vanilla.patch
 procfs-ndynamic-2.4.patch
 ext3-truncate-buffer-head.patch
+inode-max-readahead-2.4.24.patch
diff --git a/lustre/liblustre/namei.c b/lustre/liblustre/namei.c
index 1f23df942871a767fd9b5d8ca242cb40d9ac1bc0..3929e2cd05b970f43b99370765755b95149de76b 100644
--- a/lustre/liblustre/namei.c
+++ b/lustre/liblustre/namei.c
@@ -312,7 +312,7 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset,
         int rc;
 
         /* NB 1 request reference will be taken away by ll_intent_lock()
-         * when I return 
+         * when I return
          * Note: libsysio require the inode must be generated here
          */
         if ((it->it_op & IT_CREAT) || !it_disposition(it, DISP_LOOKUP_NEG)) {
@@ -352,7 +352,7 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset,
                         rc = llu_glimpse_size(inode, &lvb);
                         if (rc) {
                                 I_RELE(inode);
-                                RETURN(-EIO);
+                                RETURN(rc);
                         }
                         lli->lli_st_size = lvb.lvb_size;
                 }
diff --git a/lustre/llite/Makefile.am b/lustre/llite/Makefile.am
index 493d95c6f24c631715c66a330b0cba80b7be001c..18c3a3a3fba9143dfbc03ec42fa0970cccd3de20 100644
--- a/lustre/llite/Makefile.am
+++ b/lustre/llite/Makefile.am
@@ -10,7 +10,7 @@ modulefs_DATA = llite.o
 EXTRA_PROGRAMS = llite
 
 COMMON_SRC = dcache.c dir.c file.c llite_close.c llite_lib.c llite_nfs.c rw.c \
-             lproc_llite.c namei.c symlink.c sysctl.c llite_internal.h
+             lproc_llite.c namei.c symlink.c llite_internal.h
 
 if LINUX25
 llite_SOURCES = $(COMMON_SRC) rw26.c super25.c
diff --git a/lustre/llite/Makefile.mk b/lustre/llite/Makefile.mk
index 0cc6697ddb253974c7fcf7172928186a4da7a3c4..40345b6f97b9107768a51e02d9cc3b2b8fd7a055 100644
--- a/lustre/llite/Makefile.mk
+++ b/lustre/llite/Makefile.mk
@@ -7,5 +7,5 @@ include $(src)/../portals/Kernelenv
 
 obj-y += llite.o
 llite-objs := llite_lib.o dcache.o super.o rw.o \
-	super25.o file.o dir.o sysctl.o symlink.o namei.o lproc_llite.o \
+	super25.o file.o dir.o symlink.o namei.o lproc_llite.o \
 	rw26.o llite_nfs.o llite_close.o
diff --git a/lustre/llite/file.c b/lustre/llite/file.c
index c786211e04efd19eb4d3b14d0bf95e9b60e484e0..60c8304eee1c167fe38e7c9e2cec446b5c246be2 100644
--- a/lustre/llite/file.c
+++ b/lustre/llite/file.c
@@ -368,8 +368,15 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
          * lockers handled correctly.  fixes from bug 20 will make it
          * more efficient by associating locks with pages and with
          * batching writeback under the lock explicitly. */
-        for (i = start, j = start % count ; i <= end;
+        for (i = start, j = start % count; i <= end;
              j++, i++, tmpex.l_extent.start += PAGE_CACHE_SIZE) {
+                if (j == count) {
+                        CDEBUG(D_PAGE, "skip index %lu to %lu\n", i, i + skip);
+                        i += skip;
+                        j = 0;
+                        if (i > end)
+                                break;
+                }
                 LASSERTF(tmpex.l_extent.start< lock->l_policy_data.l_extent.end,
                          LPU64" >= "LPU64" start %lu i %lu end %lu\n",
                          tmpex.l_extent.start, lock->l_policy_data.l_extent.end,
@@ -389,8 +396,9 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
 
                 page = find_get_page(inode->i_mapping, i);
                 if (page == NULL)
-                        goto next_index;
-                LL_CDEBUG_PAGE(D_PAGE, page, "locking page\n");
+                        continue;
+                LL_CDEBUG_PAGE(D_PAGE, page, "lock page idx %lu ext "LPU64"\n",
+                               i, tmpex.l_extent.start);
                 lock_page(page);
 
                 /* page->mapping to check with racing against teardown */
@@ -425,13 +433,13 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm,
                 }
                 unlock_page(page);
                 page_cache_release(page);
-
-        next_index:
-                if (j == count) {
-                        i += skip;
-                        j = 0;
-                }
         }
+        LASSERTF(tmpex.l_extent.start <=
+                 (lock->l_policy_data.l_extent.end == ~0ULL ? ~0ULL :
+                  lock->l_policy_data.l_extent.end + 1),
+                 "loop too long "LPU64" > "LPU64" start %lu i %lu end %lu\n",
+                 tmpex.l_extent.start, lock->l_policy_data.l_extent.end,
+                 start, i, end);
         EXIT;
 }
 
@@ -615,9 +623,9 @@ int ll_glimpse_size(struct inode *inode, struct ost_lvb *lvb)
                          LCK_PR, &flags, ll_extent_lock_callback,
                          ldlm_completion_ast, ll_glimpse_callback, inode,
                          sizeof(*lvb), lustre_swab_ost_lvb, &lockh);
-        if (rc > 0) {
+        if (rc != 0) {
                 CERROR("obd_enqueue returned rc %d, returning -EIO\n", rc);
-                RETURN(-EIO);
+                RETURN(rc > 0 ? -EIO : rc);
         }
 
         lvb->lvb_size = lov_merge_size(lli->lli_smd, 0);
@@ -810,10 +818,9 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
         retval = generic_file_write(file, buf, count, ppos);
 
 out:
-        /* XXX errors? */
-        lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, LPROC_LL_WRITE_BYTES,
-                            retval);
         ll_extent_unlock(fd, inode, lsm, LCK_PW, &lockh);
+        lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, LPROC_LL_WRITE_BYTES,
+                            retval > 0 ? retval : 0);
         RETURN(retval);
 }
 
@@ -878,7 +885,8 @@ static int ll_lov_recreate_obj(struct inode *inode, struct file *file,
 }
 
 static int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file,
-                                    int flags, struct lov_user_md *lum, int lum_size)
+                                    int flags, struct lov_user_md *lum,
+                                    int lum_size)
 {
         struct ll_inode_info *lli = ll_i2info(inode);
         struct file *f;
@@ -1255,6 +1263,7 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it)
         struct inode *inode = dentry->d_inode;
         struct ll_inode_info *lli;
         struct lov_stripe_md *lsm;
+        int rc;
         ENTRY;
 
         if (!inode) {
@@ -1273,7 +1282,7 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it)
                 struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
                 struct ll_fid fid;
                 unsigned long valid = 0;
-                int rc, ealen = 0;
+                int ealen = 0;
 
                 if (S_ISREG(inode->i_mode)) {
                         ealen = obd_size_diskmd(sbi->ll_osc_exp, NULL);
@@ -1301,12 +1310,11 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it)
          * the file */
         {
                 struct ost_lvb lvb;
-                ldlm_error_t err;
 
-                err = ll_glimpse_size(inode, &lvb);
+                rc = ll_glimpse_size(inode, &lvb);
                 inode->i_size = lvb.lvb_size;
         }
-        RETURN(0);
+        RETURN(rc);
 }
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
diff --git a/lustre/llite/sysctl.c b/lustre/llite/sysctl.c
deleted file mode 100644
index b62604693c48e38cb40c764eb5cd1960924e7c80..0000000000000000000000000000000000000000
--- a/lustre/llite/sysctl.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001  Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/version.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include <linux/swapctl.h>
-#endif
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <asm/bitops.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/utsname.h>
-
-struct ctl_table_header *ll_table_header = NULL;
-
-int ll_debug_level = 0;
-int ll_print_entry = 1;
-
-
-#define LL_SYSCTL 1
-
-#define LL_DEBUG  	    1  	    /* control debugging */
-#define LL_ENTRY	    2       /* control enter/leave pattern */
-#define LL_TIMEOUT         3       /* timeout on upcalls to become intrble */
-#define LL_HARD            4       /* mount type "hard" or "soft" */
-#define LL_VARS            5       
-#define LL_INDEX           6
-#define LL_RESET           7
-
-#define LL_VARS_SLOT       2
-
-static ctl_table ll_table[] = {
-	{LL_DEBUG, "debug", &ll_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
-	{LL_ENTRY, "trace", &ll_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
-	{ 0 }
-};
-
-static ctl_table top_table[] = {
-       {LL_SYSCTL, "lustre_light",    NULL, 0, 0555, ll_table},
-       {0}
-};
-
-void ll_sysctl_init (void)
-{
-
-#ifdef CONFIG_SYSCTL
-	if ( !ll_table_header )
-		ll_table_header = register_sysctl_table(top_table, 0); 
-#endif
-}
-
-void ll_sysctl_clean (void)
-{
-#ifdef CONFIG_SYSCTL
-	if ( ll_table_header )
-		unregister_sysctl_table(ll_table_header);
-	ll_table_header = NULL;
-#endif
-}
diff --git a/lustre/lvfs/.cvsignore b/lustre/lvfs/.cvsignore
index 49c6100f1c2fb7df19792a3171bd71a1ac6ec10a..f686b8122e15f55aed0e9fba4b7f40ab537b9649 100644
--- a/lustre/lvfs/.cvsignore
+++ b/lustre/lvfs/.cvsignore
@@ -7,3 +7,4 @@ Makefile.in
 .deps
 TAGS
 .*.cmd
+fsfilt_extN.c
diff --git a/lustre/lvfs/Makefile.am b/lustre/lvfs/Makefile.am
index 1569d3bb57ef8177e1d3adf0b1255e8195d324e5..9e91de31743565e52b70ce8f9e689a92e78064ce 100644
--- a/lustre/lvfs/Makefile.am
+++ b/lustre/lvfs/Makefile.am
@@ -34,6 +34,9 @@ fsfilt_ext3_SOURCES = fsfilt_ext3.c lvfs_internal.h
 endif
 endif
 
+fsfilt_extN.c: fsfilt_ext3.c
+	sed -e "s/EXT3/EXTN/g" -e "s/ext3/extN/g" $< > $@
+
 include $(top_srcdir)/Rules
 
 if LINUX25
diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c
index 76a50886b1b8d896fa37718cfdcc1561dbac3f71..25eb31c561f56d791d5696c1f1bc393fe5f3cea7 100644
--- a/lustre/lvfs/fsfilt_ext3.c
+++ b/lustre/lvfs/fsfilt_ext3.c
@@ -71,10 +71,12 @@ struct fsfilt_cb_data {
  * the inode (which we will be changing anyways as part of this
  * transaction).
  */
-static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private)
+static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
+                               int logs)
 {
         /* For updates to the last recieved file */
-        int nblocks = EXT3_DATA_TRANS_BLOCKS;
+        int nblocks = EXT3_SINGLEDATA_TRANS_BLOCKS;
+        journal_t *journal;
         void *handle;
 
         if (current->journal_info) {
@@ -83,31 +85,27 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private)
                 goto journal_start;
         }
 
-        switch(op) {
-        case FSFILT_OP_CREATE_LOG:
-                nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS;
-                op = FSFILT_OP_CREATE;
-                break;
-        case FSFILT_OP_UNLINK_LOG:
-                nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS;
-                op = FSFILT_OP_UNLINK;
-                break;
-        }
-
         switch(op) {
         case FSFILT_OP_RMDIR:
         case FSFILT_OP_UNLINK:
+                /* delete one file + create/update logs for each stripe */
                 nblocks += EXT3_DELETE_TRANS_BLOCKS;
+                nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
+                            EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
                 break;
         case FSFILT_OP_RENAME:
                 /* modify additional directory */
-                nblocks += EXT3_DATA_TRANS_BLOCKS;
+                nblocks += EXT3_SINGLEDATA_TRANS_BLOCKS;
                 /* no break */
         case FSFILT_OP_SYMLINK:
                 /* additional block + block bitmap + GDT for long symlink */
                 nblocks += 3;
                 /* no break */
         case FSFILT_OP_CREATE:
+                /* create/update logs for each stripe */
+                nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
+                            EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
+                /* no break */
         case FSFILT_OP_MKDIR:
         case FSFILT_OP_MKNOD:
                 /* modify one inode + block bitmap + GDT */
@@ -115,21 +113,30 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private)
                 /* no break */
         case FSFILT_OP_LINK:
                 /* modify parent directory */
-                nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS;
+                nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS +
+                        EXT3_DATA_TRANS_BLOCKS;
                 break;
         case FSFILT_OP_SETATTR:
                 /* Setattr on inode */
                 nblocks += 1;
                 break;
-        case FSFILT_OP_CANCEL_UNLINK_LOG:
+        case FSFILT_OP_CANCEL_UNLINK:
+                /* blocks for log header bitmap update OR
+                 * blocks for catalog header bitmap update + unlink of logs */
                 nblocks = (LLOG_CHUNK_SIZE >> inode->i_blkbits) +
-                        EXT3_DELETE_TRANS_BLOCKS;
+                        EXT3_DELETE_TRANS_BLOCKS * logs;
                 break;
         default: CERROR("unknown transaction start op %d\n", op);
                  LBUG();
         }
 
         LASSERT(current->journal_info == desc_private);
+        journal = EXT3_SB(inode->i_sb)->s_journal;
+        if (nblocks > journal->j_max_transaction_buffers) {
+                CERROR("too many credits %d for op %ux%u using %d instead\n",
+                       nblocks, op, logs, journal->j_max_transaction_buffers);
+                nblocks = journal->j_max_transaction_buffers;
+        }
 
  journal_start:
         lock_kernel();
@@ -138,6 +145,9 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private)
 
         if (!IS_ERR(handle))
                 LASSERT(current->journal_info == handle);
+        else
+                CERROR("error starting handle for op %u (%u credits): rc %ld\n",
+                       op, nblocks, PTR_ERR(handle));
         return handle;
 }
 
@@ -240,7 +250,7 @@ static int fsfilt_ext3_credits_needed(int objcount, struct fsfilt_objinfo *fso,
  */
 static void *fsfilt_ext3_brw_start(int objcount, struct fsfilt_objinfo *fso,
                                    int niocount, struct niobuf_local *nb,
-                                   void *desc_private)
+                                   void *desc_private, int logs)
 {
         journal_t *journal;
         handle_t *handle;
@@ -846,6 +856,37 @@ static int fsfilt_ext3_setup(struct super_block *sb)
         return 0;
 }
 
+/* If fso is NULL, op is FSFILT operation, otherwise op is number of fso
+   objects. Logs is number of logfiles to update */
+static int fsfilt_ext3_get_op_len(int op, struct fsfilt_objinfo *fso, int logs)
+{
+        if ( !fso ) {
+                switch(op) {
+                case FSFILT_OP_CREATE:
+                                 /* directory leaf, index & indirect & EA*/
+                        return 4 + 3 * logs;
+                case FSFILT_OP_UNLINK:
+                        return 3 * logs;
+                }
+        } else {
+                int i;
+                int needed = 0;
+                struct super_block *sb = fso->fso_dentry->d_inode->i_sb;
+                int blockpp = 1 << (PAGE_CACHE_SHIFT - sb->s_blocksize_bits);
+                int addrpp = EXT3_ADDR_PER_BLOCK(sb) * blockpp;
+                for (i = 0; i < op; i++, fso++) {
+                        int nblocks = fso->fso_bufcnt * blockpp;
+                        int ndindirect = min(nblocks, addrpp + 1);
+                        int nindir = nblocks + ndindirect + 1;
+
+                        needed += nindir;
+                }
+                return needed + 3 * logs;
+        }
+
+        return 0;
+}
+
 static struct fsfilt_operations fsfilt_ext3_ops = {
         fs_type:                "ext3",
         fs_owner:               THIS_MODULE,
@@ -867,6 +908,7 @@ static struct fsfilt_operations fsfilt_ext3_ops = {
         fs_write_record:        fsfilt_ext3_write_record,
         fs_read_record:         fsfilt_ext3_read_record,
         fs_setup:               fsfilt_ext3_setup,
+        fs_get_op_len:          fsfilt_ext3_get_op_len,
 };
 
 static int __init fsfilt_ext3_init(void)
diff --git a/lustre/lvfs/fsfilt_extN.c b/lustre/lvfs/fsfilt_extN.c
deleted file mode 100644
index 8756f9a2cfa43efdde541c14371e497d02994604..0000000000000000000000000000000000000000
--- a/lustre/lvfs/fsfilt_extN.c
+++ /dev/null
@@ -1,865 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- *  lustre/lib/fsfilt_extN.c
- *  Lustre filesystem abstraction routines
- *
- *  Copyright (C) 2002, 2003 Cluster File Systems, Inc.
- *   Author: Andreas Dilger <adilger@clusterfs.com>
- *
- *   This file is part of Lustre, http://www.lustre.org.
- *
- *   Lustre is free software; you can redistribute it and/or
- *   modify it under the terms of version 2 of the GNU General Public
- *   License as published by the Free Software Foundation.
- *
- *   Lustre is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with Lustre; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_FILTER
-
-#include <linux/fs.h>
-#include <linux/jbd.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/quotaops.h>
-#include <linux/extN_fs.h>
-#include <linux/extN_jbd.h>
-#include <linux/version.h>
-/* XXX ugh */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- #include <linux/extN_xattr.h>
-#else
- #include <linux/../../fs/extN/xattr.h>
-#endif
-#include <linux/kp30.h>
-#include <linux/lustre_fsfilt.h>
-#include <linux/obd.h>
-#include <linux/obd_class.h>
-#include <linux/module.h>
-
-static kmem_cache_t *fcb_cache;
-static atomic_t fcb_cache_count = ATOMIC_INIT(0);
-
-struct fsfilt_cb_data {
-        struct journal_callback cb_jcb; /* jbd private data - MUST BE FIRST */
-        fsfilt_cb_t cb_func;            /* MDS/OBD completion function */
-        struct obd_device *cb_obd;      /* MDS/OBD completion device */
-        __u64 cb_last_rcvd;             /* MDS/OST last committed operation */
-        void *cb_data;                  /* MDS/OST completion function data */
-};
-
-#ifndef EXTN_XATTR_INDEX_TRUSTED        /* temporary until we hit l28 kernel */
-#define EXTN_XATTR_INDEX_TRUSTED        4
-#endif
-#define XATTR_LUSTRE_MDS_LOV_EA         "lov"
-
-#define EXTN_XATTR_INDEX_LUSTRE         5                         /* old */
-#define XATTR_LUSTRE_MDS_OBJID          "system.lustre_mds_objid" /* old */
-
-/*
- * We don't currently need any additional blocks for rmdir and
- * unlink transactions because we are storing the OST oa_id inside
- * the inode (which we will be changing anyways as part of this
- * transaction).
- */
-static void *fsfilt_extN_start(struct inode *inode, int op, void *desc_private)
-{
-        /* For updates to the last recieved file */
-        int nblocks = EXTN_DATA_TRANS_BLOCKS;
-        void *handle;
-
-        if (current->journal_info) {
-                CDEBUG(D_INODE, "increasing refcount on %p\n", current->journal_info);
-                goto journal_start;
-        }
-
-        switch(op) {
-        case FSFILT_OP_CREATE_LOG:
-                nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS;
-                op = FSFILT_OP_CREATE;
-                break;
-        case FSFILT_OP_UNLINK_LOG:
-                nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS;
-                op = FSFILT_OP_UNLINK;
-                break;
-        }
-
-        switch(op) {
-        case FSFILT_OP_RMDIR:
-        case FSFILT_OP_UNLINK:
-                nblocks += EXTN_DELETE_TRANS_BLOCKS;
-                break;
-        case FSFILT_OP_RENAME:
-                /* modify additional directory */
-                nblocks += EXTN_DATA_TRANS_BLOCKS;
-                /* no break */
-        case FSFILT_OP_SYMLINK:
-                /* additional block + block bitmap + GDT for long symlink */
-                nblocks += 3;
-                /* no break */
-        case FSFILT_OP_CREATE:
-        case FSFILT_OP_MKDIR:
-        case FSFILT_OP_MKNOD:
-                /* modify one inode + block bitmap + GDT */
-                nblocks += 3;
-                /* no break */
-        case FSFILT_OP_LINK:
-                /* modify parent directory */
-                nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS;
-                break;
-        case FSFILT_OP_SETATTR:
-                /* Setattr on inode */
-                nblocks += 1;
-                break;
-        default: CERROR("unknown transaction start op %d\n", op);
-                 LBUG();
-        }
-
-        LASSERT(current->journal_info == desc_private);
-
- journal_start:
-        lock_kernel();
-        handle = journal_start(EXTN_JOURNAL(inode), nblocks);
-        unlock_kernel();
-
-        if (!IS_ERR(handle))
-                LASSERT(current->journal_info == handle);
-        return handle;
-}
-
-/*
- * Calculate the number of buffer credits needed to write multiple pages in
- * a single extN transaction.  No, this shouldn't be here, but as yet extN
- * doesn't have a nice API for calculating this sort of thing in advance.
- *
- * See comment above extN_writepage_trans_blocks for details.  We assume
- * no data journaling is being done, but it does allow for all of the pages
- * being non-contiguous.  If we are guaranteed contiguous pages we could
- * reduce the number of (d)indirect blocks a lot.
- *
- * With N blocks per page and P pages, for each inode we have at most:
- * N*P indirect
- * min(N*P, blocksize/4 + 1) dindirect blocks
- * niocount tindirect
- *
- * For the entire filesystem, we have at most:
- * min(sum(nindir + P), ngroups) bitmap blocks (from the above)
- * min(sum(nindir + P), gdblocks) group descriptor blocks (from the above)
- * objcount inode blocks
- * 1 superblock
- * 2 * EXTN_SINGLEDATA_TRANS_BLOCKS for the quota files
- *
- * 1 EXTN_DATA_TRANS_BLOCKS for the last_rcvd update.
- */
-static int fsfilt_extN_credits_needed(int objcount, struct fsfilt_objinfo *fso)
-{
-        struct super_block *sb = fso->fso_dentry->d_inode->i_sb;
-        int blockpp = 1 << (PAGE_CACHE_SHIFT - sb->s_blocksize_bits);
-        int addrpp = EXTN_ADDR_PER_BLOCK(sb) * blockpp;
-        int nbitmaps = 0;
-        int ngdblocks = 0;
-        int needed = objcount + 1;
-        int i;
-
-        for (i = 0; i < objcount; i++, fso++) {
-                int nblocks = fso->fso_bufcnt * blockpp;
-                int ndindirect = min(nblocks, addrpp + 1);
-                int nindir = nblocks + ndindirect + 1;
-
-                nbitmaps += nindir + nblocks;
-                ngdblocks += nindir + nblocks;
-
-                needed += nindir;
-        }
-
-        /* Assumes extN and extN have same sb_info layout at the start. */
-        if (nbitmaps > EXTN_SB(sb)->s_groups_count)
-                nbitmaps = EXTN_SB(sb)->s_groups_count;
-        if (ngdblocks > EXTN_SB(sb)->s_gdb_count)
-                ngdblocks = EXTN_SB(sb)->s_gdb_count;
-
-        needed += nbitmaps + ngdblocks;
-
-        /* last_rcvd update */
-        needed += EXTN_DATA_TRANS_BLOCKS;
-
-#ifdef CONFIG_QUOTA
-        /* We assume that there will be 1 bit set in s_dquot.flags for each
-         * quota file that is active.  This is at least true for now.
-         */
-        needed += hweight32(sb_any_quota_enabled(sb)) *
-                EXTN_SINGLEDATA_TRANS_BLOCKS;
-#endif
-
-        return needed;
-}
-
-/* We have to start a huge journal transaction here to hold all of the
- * metadata for the pages being written here.  This is necessitated by
- * the fact that we do lots of prepare_write operations before we do
- * any of the matching commit_write operations, so even if we split
- * up to use "smaller" transactions none of them could complete until
- * all of them were opened.  By having a single journal transaction,
- * we eliminate duplicate reservations for common blocks like the
- * superblock and group descriptors or bitmaps.
- *
- * We will start the transaction here, but each prepare_write will
- * add a refcount to the transaction, and each commit_write will
- * remove a refcount.  The transaction will be closed when all of
- * the pages have been written.
- */
-static void *fsfilt_extN_brw_start(int objcount, struct fsfilt_objinfo *fso,
-                                   int niocount, void *desc_private)
-{
-        journal_t *journal;
-        handle_t *handle;
-        int needed;
-        ENTRY;
-
-        LASSERT(current->journal_info == desc_private);
-        journal = EXTN_SB(fso->fso_dentry->d_inode->i_sb)->s_journal;
-        needed = fsfilt_extN_credits_needed(objcount, fso);
-
-        /* The number of blocks we could _possibly_ dirty can very large.
-         * We reduce our request if it is absurd (and we couldn't get that
-         * many credits for a single handle anyways).
-         *
-         * At some point we have to limit the size of I/Os sent at one time,
-         * increase the size of the journal, or we have to calculate the
-         * actual journal requirements more carefully by checking all of
-         * the blocks instead of being maximally pessimistic.  It remains to
-         * be seen if this is a real problem or not.
-         */
-        if (needed > journal->j_max_transaction_buffers) {
-                CERROR("want too many journal credits (%d) using %d instead\n",
-                       needed, journal->j_max_transaction_buffers);
-                needed = journal->j_max_transaction_buffers;
-        }
-
-        lock_kernel();
-        handle = journal_start(journal, needed);
-        unlock_kernel();
-        if (IS_ERR(handle)) {
-                CERROR("can't get handle for %d credits: rc = %ld\n", needed,
-                       PTR_ERR(handle));
-        } else {
-                LASSERT(handle->h_buffer_credits >= needed);
-                LASSERT(current->journal_info == handle);
-        }
-
-        RETURN(handle);
-}
-
-static int fsfilt_extN_commit(struct inode *inode, void *h, int force_sync)
-{
-        int rc;
-        handle_t *handle = h;
-
-        LASSERT(current->journal_info == handle);
-        if (force_sync)
-                handle->h_sync = 1; /* recovery likes this */
-
-        lock_kernel();
-        rc = journal_stop(handle);
-        unlock_kernel();
-
-        // LASSERT(current->journal_info == NULL);
-        return rc;
-}
-
-static int fsfilt_extN_commit_async(struct inode *inode, void *h,
-                                        void **wait_handle)
-{
-        transaction_t *transaction;
-        unsigned long tid, rtid;
-        handle_t *handle = h;
-        journal_t *journal;
-        int rc;
-
-        LASSERT(current->journal_info == handle);
-
-        lock_kernel();
-        transaction = handle->h_transaction;
-        journal = transaction->t_journal;
-        tid = transaction->t_tid;
-        /* we don't want to be blocked */
-        handle->h_sync = 0;
-        rc = journal_stop(handle);
-        if (rc) {
-                CERROR("error while stopping transaction: %d\n", rc);
-                unlock_kernel();
-                return rc;
-        }
-
-        rtid = log_start_commit(journal, transaction);
-        if (rtid != tid)
-                CERROR("strange race: %lu != %lu\n",
-                       (unsigned long) tid, (unsigned long) rtid);
-        unlock_kernel();
-
-        *wait_handle = (void *) tid;
-        CDEBUG(D_INODE, "commit async: %lu\n", (unsigned long) tid);
-        return 0;
-}
-
-static int fsfilt_extN_commit_wait(struct inode *inode, void *h)
-{
-        tid_t tid = (tid_t)(long)h;
-
-        CDEBUG(D_INODE, "commit wait: %lu\n", (unsigned long) tid);
-	if (is_journal_aborted(EXTN_JOURNAL(inode)))
-                return -EIO;
-
-        log_wait_commit(EXTN_JOURNAL(inode), tid);
-
-        return 0;
-}
-
-static int fsfilt_extN_setattr(struct dentry *dentry, void *handle,
-                               struct iattr *iattr, int do_trunc)
-{
-        struct inode *inode = dentry->d_inode;
-        int rc;
-
-        lock_kernel();
-
-        /* A _really_ horrible hack to avoid removing the data stored
-         * in the block pointers; this is really the "small" stripe MD data.
-         * We can avoid further hackery by virtue of the MDS file size being
-         * zero all the time (which doesn't invoke block truncate at unlink
-         * time), so we assert we never change the MDS file size from zero. */
-        if (iattr->ia_valid & ATTR_SIZE && !do_trunc) {
-                /* ATTR_SIZE would invoke truncate: clear it */
-                iattr->ia_valid &= ~ATTR_SIZE;
-                EXTN_I(inode)->i_disksize = inode->i_size = iattr->ia_size;
-
-                /* make sure _something_ gets set - so new inode
-                 * goes to disk (probably won't work over XFS */
-                if (!(iattr->ia_valid & (ATTR_MODE | ATTR_MTIME | ATTR_CTIME))){
-                        iattr->ia_valid |= ATTR_MODE;
-                        iattr->ia_mode = inode->i_mode;
-                }
-        }
-
-        /* Don't allow setattr to change file type */
-        iattr->ia_mode = (inode->i_mode & S_IFMT)|(iattr->ia_mode & ~S_IFMT);
-
-        /* We set these flags on the client, but have already checked perms
-         * so don't confuse inode_change_ok. */
-        iattr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET);
-
-        if (inode->i_op->setattr) {
-                rc = inode->i_op->setattr(dentry, iattr);
-        } else {
-                rc = inode_change_ok(inode, iattr);
-                if (!rc)
-                        rc = inode_setattr(inode, iattr);
-        }
-
-        unlock_kernel();
-
-        return rc;
-}
-
-static int fsfilt_extN_iocontrol(struct inode * inode, struct file *file,
-                                 unsigned int cmd, unsigned long arg)
-{
-        int rc = 0;
-        ENTRY;
-
-        if (inode->i_fop->ioctl)
-                rc = inode->i_fop->ioctl(inode, file, cmd, arg);
-        else
-                RETURN(-ENOTTY);
-
-        RETURN(rc);
-}
-
-#undef INLINE_EA
-#undef OLD_EA
-static int fsfilt_extN_set_md(struct inode *inode, void *handle,
-                              void *lmm, int lmm_size)
-{
-        int rc, old_ea = 0;
-
-#ifdef INLINE_EA  /* can go away before 1.0 - just for testing bug 2097 now */
-        /* Nasty hack city - store stripe MD data in the block pointers if
-         * it will fit, because putting it in an EA currently kills the MDS
-         * performance.  We'll fix this with "fast EAs" in the future.
-         */
-        if (inode->i_blocks == 0 && lmm_size <= sizeof(EXTN_I(inode)->i_data) -
-                                            sizeof(EXTN_I(inode)->i_data[0])) {
-                unsigned old_size = EXTN_I(inode)->i_data[0];
-                if (old_size != 0) {
-                        LASSERT(old_size < sizeof(EXTN_I(inode)->i_data));
-                        CERROR("setting EA on %lu/%u again... interesting\n",
-                               inode->i_ino, inode->i_generation);
-                }
-
-                EXTN_I(inode)->i_data[0] = cpu_to_le32(lmm_size);
-                memcpy(&EXTN_I(inode)->i_data[1], lmm, lmm_size);
-                mark_inode_dirty(inode);
-                return 0;
-        }
-#endif
-#ifdef OLD_EA
-        /* keep this when we get rid of OLD_EA (too noisy during conversion) */
-        if (EXTN_I(inode)->i_file_acl /* || large inode EA flag */) {
-                CWARN("setting EA on %lu/%u again... interesting\n",
-                       inode->i_ino, inode->i_generation);
-                old_ea = 1;
-        }
-
-        lock_kernel();
-        /* this can go away before 1.0.  For bug 2097 testing only. */
-        rc = extN_xattr_set_handle(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
-                                   XATTR_LUSTRE_MDS_OBJID, lmm, lmm_size, 0);
-#else
-        lock_kernel();
-        rc = extN_xattr_set_handle(handle, inode, EXTN_XATTR_INDEX_TRUSTED,
-                                   XATTR_LUSTRE_MDS_LOV_EA, lmm, lmm_size, 0);
-
-        /* This tries to delete the old-format LOV EA, but only as long as we
-         * have successfully saved the new-format LOV EA (we can always try
-         * the conversion again the next time the file is accessed).  It is
-         * possible (although unlikely) that the new-format LOV EA couldn't be
-         * saved because it ran out of space but we would need a file striped
-         * over least 123 OSTs before the two EAs filled a 4kB block.
-         *
-         * This can be removed when all filesystems have converted to the
-         * new EA format, but otherwise adds little if any overhead.  If we
-         * wanted backward compatibility for existing files, we could keep
-         * the old EA around for a while but we'd have to clean it up later. */
-        if (rc >= 0 && old_ea) {
-                int err = extN_xattr_set_handle(handle, inode,
-                                                EXTN_XATTR_INDEX_LUSTRE,
-                                                XATTR_LUSTRE_MDS_OBJID,
-                                                NULL, 0, 0);
-                if (err)
-                        CERROR("error deleting old LOV EA on %lu/%u: rc %d\n",
-                               inode->i_ino, inode->i_generation, err);
-        }
-#endif
-        unlock_kernel();
-
-        if (rc)
-                CERROR("error adding MD data to inode %lu: rc = %d\n",
-                       inode->i_ino, rc);
-        return rc;
-}
-
-/* Must be called with i_sem held */
-static int fsfilt_extN_get_md(struct inode *inode, void *lmm, int lmm_size)
-{
-        int rc;
-
-        LASSERT(down_trylock(&inode->i_sem) != 0);
-        lock_kernel();
-        /* Keep support for reading "inline EAs" until we convert
-         * users over to new format entirely.  See bug 841/2097. */
-        if (inode->i_blocks == 0 && EXTN_I(inode)->i_data[0]) {
-                unsigned size = le32_to_cpu(EXTN_I(inode)->i_data[0]);
-                void *handle;
-
-                LASSERT(size < sizeof(EXTN_I(inode)->i_data));
-                if (lmm) {
-                        if (size > lmm_size) {
-                                CERROR("inline EA on %lu/%u bad size %u > %u\n",
-                                       inode->i_ino, inode->i_generation,
-                                       size, lmm_size);
-                                return -ERANGE;
-                        }
-                        memcpy(lmm, &EXTN_I(inode)->i_data[1], size);
-                }
-
-#ifndef INLINE_EA
-                /* migrate LOV EA data to external block - keep same format */
-                CWARN("DEBUG: migrate inline EA for inode %lu/%u to block\n",
-                      inode->i_ino, inode->i_generation);
-
-                handle = journal_start(EXTN_JOURNAL(inode),
-                                       EXTN_XATTR_TRANS_BLOCKS);
-                if (!IS_ERR(handle)) {
-                        int err;
-                        rc = fsfilt_extN_set_md(inode, handle,
-                                                &EXTN_I(inode)->i_data[1],size);
-                        if (rc == 0) {
-                                memset(EXTN_I(inode)->i_data, 0,
-                                       sizeof(EXTN_I(inode)->i_data));
-                                mark_inode_dirty(inode);
-                        }
-                        err = journal_stop(handle);
-                        if (err && rc == 0)
-                                rc = err;
-                } else {
-                        rc = PTR_ERR(handle);
-                }
-#endif
-                unlock_kernel();
-                return size;
-        }
-
-        rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_TRUSTED,
-                            XATTR_LUSTRE_MDS_LOV_EA, lmm, lmm_size);
-        /* try old EA type if new one failed - MDS will convert it for us */
-        if (rc == -ENODATA) {
-                CDEBUG(D_INFO,"failed new LOV EA %d/%s from inode %lu: rc %d\n",
-                       EXTN_XATTR_INDEX_TRUSTED, XATTR_LUSTRE_MDS_LOV_EA,
-                       inode->i_ino, rc);
-
-                rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_LUSTRE,
-                                    XATTR_LUSTRE_MDS_OBJID, lmm, lmm_size);
-        }
-        unlock_kernel();
-
-        /* This gives us the MD size */
-        if (lmm == NULL)
-                return (rc == -ENODATA) ? 0 : rc;
-
-        if (rc < 0) {
-                CDEBUG(D_INFO, "error getting EA %d/%s from inode %lu: rc %d\n",
-                       EXTN_XATTR_INDEX_LUSTRE, XATTR_LUSTRE_MDS_OBJID,
-                       inode->i_ino, rc);
-                memset(lmm, 0, lmm_size);
-                return (rc == -ENODATA) ? 0 : rc;
-        }
-
-        return rc;
-}
-
-static ssize_t fsfilt_extN_readpage(struct file *file, char *buf, size_t count,
-                                    loff_t *off)
-{
-        struct inode *inode = file->f_dentry->d_inode;
-        int rc = 0;
-
-        if (S_ISREG(inode->i_mode))
-                rc = file->f_op->read(file, buf, count, off);
-        else {
-                const int blkbits = inode->i_sb->s_blocksize_bits;
-                const int blksize = inode->i_sb->s_blocksize;
-
-                CDEBUG(D_EXT2, "reading "LPSZ" at dir %lu+%llu\n",
-                       count, inode->i_ino, *off);
-                while (count > 0) {
-                        struct buffer_head *bh;
-
-                        bh = NULL;
-                        if (*off < inode->i_size) {
-                                int err = 0;
-
-                                bh = extN_bread(NULL, inode, *off >> blkbits,
-                                                0, &err);
-
-                                CDEBUG(D_EXT2, "read %u@%llu\n", blksize, *off);
-
-                                if (bh) {
-                                        memcpy(buf, bh->b_data, blksize);
-                                        brelse(bh);
-                                } else if (err) {
-                                        /* XXX in theory we should just fake
-                                         * this buffer and continue like extN,
-                                         * especially if this is a partial read
-                                         */
-                                        CERROR("error read dir %lu+%llu: %d\n",
-                                               inode->i_ino, *off, err);
-                                        RETURN(err);
-                                }
-                        }
-                        if (!bh) {
-                                struct extN_dir_entry_2 *fake = (void *)buf;
-
-                                CDEBUG(D_EXT2, "fake %u@%llu\n", blksize, *off);
-                                memset(fake, 0, sizeof(*fake));
-                                fake->rec_len = cpu_to_le32(blksize);
-                        }
-                        count -= blksize;
-                        buf += blksize;
-                        *off += blksize;
-                        rc += blksize;
-                }
-        }
-
-        return rc;
-}
-
-static void fsfilt_extN_cb_func(struct journal_callback *jcb, int error)
-{
-        struct fsfilt_cb_data *fcb = (struct fsfilt_cb_data *)jcb;
-
-        fcb->cb_func(fcb->cb_obd, fcb->cb_last_rcvd, fcb->cb_data, error);
-
-        OBD_SLAB_FREE(fcb, fcb_cache, sizeof *fcb);
-        atomic_dec(&fcb_cache_count);
-}
-
-static int fsfilt_extN_add_journal_cb(struct obd_device *obd, __u64 last_rcvd,
-                                      void *handle, fsfilt_cb_t cb_func,
-                                      void *cb_data)
-{
-        struct fsfilt_cb_data *fcb;
-
-        OBD_SLAB_ALLOC(fcb, fcb_cache, GFP_NOFS, sizeof *fcb);
-        if (fcb == NULL)
-                RETURN(-ENOMEM);
-
-        atomic_inc(&fcb_cache_count);
-        fcb->cb_func = cb_func;
-        fcb->cb_obd = obd;
-        fcb->cb_last_rcvd = last_rcvd;
-        fcb->cb_data = cb_data;
-
-        CDEBUG(D_EXT2, "set callback for last_rcvd: "LPD64"\n", last_rcvd);
-        lock_kernel();
-        journal_callback_set(handle, fsfilt_extN_cb_func,
-                             (struct journal_callback *)fcb);
-        unlock_kernel();
-
-        return 0;
-}
-
-/*
- * We need to hack the return value for the free inode counts because
- * the current EA code requires one filesystem block per inode with EAs,
- * so it is possible to run out of blocks before we run out of inodes.
- *
- * This can be removed when the extN EA code is fixed.
- */
-static int fsfilt_extN_statfs(struct super_block *sb, struct obd_statfs *osfs)
-{
-        struct kstatfs sfs;
-        int rc;
-
-        memset(&sfs, 0, sizeof(sfs));
-
-        rc = sb->s_op->statfs(sb, &sfs);
-
-        if (!rc && sfs.f_bfree < sfs.f_ffree) {
-                sfs.f_files = (sfs.f_files - sfs.f_ffree) + sfs.f_bfree;
-                sfs.f_ffree = sfs.f_bfree;
-        }
-
-        statfs_pack(osfs, &sfs);
-        return rc;
-}
-
-static int fsfilt_extN_sync(struct super_block *sb)
-{
-        return extN_force_commit(sb);
-}
-
-extern int extN_map_inode_page(struct inode *inode, struct page *page,
-                               unsigned long *blocks, int *created, int create);
-int fsfilt_extN_map_inode_page(struct inode *inode, struct page *page,
-                               unsigned long *blocks, int *created, int create)
-{
-        return extN_map_inode_page(inode, page, blocks, created, create);
-}
-
-extern int extN_prep_san_write(struct inode *inode, long *blocks,
-                               int nblocks, loff_t newsize);
-static int fsfilt_extN_prep_san_write(struct inode *inode, long *blocks,
-                                      int nblocks, loff_t newsize)
-{
-        return extN_prep_san_write(inode, blocks, nblocks, newsize);
-}
-
-static int fsfilt_extN_read_record(struct file * file, void *buf,
-                                   int size, loff_t *offs)
-{
-        struct buffer_head *bh;
-        unsigned long block, boffs;
-        struct inode *inode = file->f_dentry->d_inode;
-        int err;
-
-        if (inode->i_size < *offs + size) {
-                size = inode->i_size - *offs;
-                if (size < 0) {
-                        CERROR("size %llu is too short for read %u@%llu\n",
-                                        inode->i_size, size, *offs);
-                        return -EIO;
-                } else if (size == 0)
-                        return 0;
-        }
-
-        block = *offs >> inode->i_blkbits;
-        bh = extN_bread(NULL, inode, block, 0, &err);
-        if (!bh) {
-                CERROR("can't read block: %d\n", err);
-                return err;
-        }
-
-        boffs = (unsigned)*offs % bh->b_size;
-        if (boffs + size > bh->b_size) {
-                CERROR("request crosses block's border. offset %llu, size %u\n",
-                       *offs, size);
-                brelse(bh);
-                return -EIO;
-        }
-
-        memcpy(buf, bh->b_data + boffs, size);
-        brelse(bh);
-        *offs += size;
-        return 0;
-}
-
-static int fsfilt_extN_write_record(struct file *file, void *buf, int size,
-                                    loff_t *offs, int force_sync)
-{
-        struct buffer_head *bh;
-        unsigned long block, boffs;
-        struct inode *inode = file->f_dentry->d_inode;
-        loff_t old_size = inode->i_size;
-        journal_t *journal;
-        handle_t *handle;
-        int err;
-
-        journal = EXTN_SB(inode->i_sb)->s_journal;
-        handle = journal_start(journal, EXTN_DATA_TRANS_BLOCKS + 2);
-        if (IS_ERR(handle)) {
-                CERROR("can't start transaction\n");
-                return PTR_ERR(handle);
-        }
-
-        block = *offs >> inode->i_blkbits;
-        if (*offs + size > inode->i_size) {
-                down(&inode->i_sem);
-                if (*offs + size > inode->i_size)
-                        inode->i_size = *offs + size;
-                if (inode->i_size > EXTN_I(inode)->i_disksize)
-                        EXTN_I(inode)->i_disksize = inode->i_size;
-                up(&inode->i_sem);
-        }
-
-        bh = extN_bread(handle, inode, block, 1, &err);
-        if (!bh) {
-                CERROR("can't read/create block: %d\n", err);
-                goto out;
-        }
-
-        /* This is a hack only needed because extN_get_block_handle() updates
-         * i_disksize after marking the inode dirty in extN_splice_branch().
-         * We will fix that when we get a chance, as extN_mark_inode_dirty()
-         * is not without cost, nor is it even exported.
-         */
-        if (inode->i_size > old_size)
-                mark_inode_dirty(inode);
-
-        boffs = (unsigned)*offs % bh->b_size;
-        if (boffs + size > bh->b_size) {
-                CERROR("request crosses block's border. offset %llu, size %u\n",
-                       *offs, size);
-                err = -EIO;
-                goto out;
-        }
-
-        err = extN_journal_get_write_access(handle, bh);
-        if (err) {
-                CERROR("journal_get_write_access() returned error %d\n", err);
-                goto out;
-        }
-        memcpy(bh->b_data + boffs, buf, size);
-        err = extN_journal_dirty_metadata(handle, bh);
-        if (err) {
-                CERROR("journal_dirty_metadata() returned error %d\n", err);
-                goto out;
-        }
-
-        if (force_sync)
-                handle->h_sync = 1; /* recovery likes this */
-out:
-        if (bh)
-                brelse(bh);
-        journal_stop(handle);
-        if (err == 0)
-                *offs += size;
-        return err;
-}
-
-static int fsfilt_extN_setup(struct super_block *sb)
-{
-#if 0
-        EXTN_SB(sb)->dx_lock = fsfilt_extN_dx_lock;
-        EXTN_SB(sb)->dx_unlock = fsfilt_extN_dx_unlock;
-#endif
-#ifdef S_PDIROPS
-        CWARN("Enabling PDIROPS\n");
-        set_opt(EXTN_SB(sb)->s_mount_opt, PDIROPS);
-        sb->s_flags |= S_PDIROPS;
-#endif
-        return 0;
-}
-
-static struct fsfilt_operations fsfilt_extN_ops = {
-        fs_type:                "extN",
-        fs_owner:               THIS_MODULE,
-        fs_start:               fsfilt_extN_start,
-        fs_brw_start:           fsfilt_extN_brw_start,
-        fs_commit:              fsfilt_extN_commit,
-        fs_commit_async:        fsfilt_extN_commit_async,
-        fs_commit_wait:         fsfilt_extN_commit_wait,
-        fs_setattr:             fsfilt_extN_setattr,
-        fs_iocontrol:           fsfilt_extN_iocontrol,
-        fs_set_md:              fsfilt_extN_set_md,
-        fs_get_md:              fsfilt_extN_get_md,
-        fs_readpage:            fsfilt_extN_readpage,
-        fs_add_journal_cb:      fsfilt_extN_add_journal_cb,
-        fs_statfs:              fsfilt_extN_statfs,
-        fs_sync:                fsfilt_extN_sync,
-        fs_map_inode_page:      fsfilt_extN_map_inode_page,
-        fs_prep_san_write:      fsfilt_extN_prep_san_write,
-        fs_write_record:        fsfilt_extN_write_record,
-        fs_read_record:         fsfilt_extN_read_record,
-        fs_setup:               fsfilt_extN_setup,
-};
-
-static int __init fsfilt_extN_init(void)
-{
-        int rc;
-
-        //rc = extN_xattr_register();
-        fcb_cache = kmem_cache_create("fsfilt_extN_fcb",
-                                      sizeof(struct fsfilt_cb_data), 0,
-                                      0, NULL, NULL);
-        if (!fcb_cache) {
-                CERROR("error allocating fsfilt journal callback cache\n");
-                GOTO(out, rc = -ENOMEM);
-        }
-
-        rc = fsfilt_register_ops(&fsfilt_extN_ops);
-
-        if (rc)
-                kmem_cache_destroy(fcb_cache);
-out:
-        return rc;
-}
-
-static void __exit fsfilt_extN_exit(void)
-{
-        int rc;
-
-        fsfilt_unregister_ops(&fsfilt_extN_ops);
-        rc = kmem_cache_destroy(fcb_cache);
-
-        if (rc || atomic_read(&fcb_cache_count)) {
-                CERROR("can't free fsfilt callback cache: count %d, rc = %d\n",
-                       atomic_read(&fcb_cache_count), rc);
-        }
-
-        //rc = extN_xattr_unregister();
-}
-
-module_init(fsfilt_extN_init);
-module_exit(fsfilt_extN_exit);
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre extN Filesystem Helper v0.1");
-MODULE_LICENSE("GPL");
diff --git a/lustre/lvfs/fsfilt_reiserfs.c b/lustre/lvfs/fsfilt_reiserfs.c
index 9864eda7a78385ce9e08f4b10f3c308d04071629..b38ba4aa88d37a4b31607f3c55d826710a252ccb 100644
--- a/lustre/lvfs/fsfilt_reiserfs.c
+++ b/lustre/lvfs/fsfilt_reiserfs.c
@@ -33,7 +33,6 @@
 #define DEBUG_SUBSYSTEM S_FILTER
 
 #include <linux/fs.h>
-#include <linux/jbd.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
@@ -49,15 +48,22 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
+/* XXX We cannot include linux/reiserfs_fs.h here, because of symbols clash,
+   but we need MAX_HEIGHT definition for proper reserve calculations
+#include <linux/reiserfs_fs.h>
+*/
+#define MAX_HEIGHT 5 /* maximal height of a tree. don't change this without
+                        changing JOURNAL_PER_BALANCE_CNT */
+
 static void *fsfilt_reiserfs_start(struct inode *inode, int op,
-                                   void *desc_private)
+                                   void *desc_private, int logs)
 {
         return (void *)0xf00f00be;
 }
 
 static void *fsfilt_reiserfs_brw_start(int objcount, struct fsfilt_objinfo *fso,
                                        int niocount, struct niobuf_local *nb,
-                                       void *desc_private)
+                                       void *desc_private, int logs)
 {
         return (void *)0xf00f00be;
 }
@@ -177,6 +183,35 @@ static int fsfilt_reiserfs_sync(struct super_block *sb)
         return fsync_dev(sb->s_dev);
 }
 
+/* If fso is NULL, op is FSFILT operation, otherwise op is number of fso
+   objects. Logs is number of logfiles to update */
+static int fsfilt_reiserfs_get_op_len(int op, struct fsfilt_objinfo *fso,
+                                      int logs)
+{
+        if ( !fso ) {
+                switch(op) {
+                case FSFILT_OP_CREATE:
+                                 /* directory leaf, index & indirect & EA*/
+                        return MAX_HEIGHT + logs;
+                case FSFILT_OP_UNLINK:
+                        return MAX_HEIGHT + logs;
+                }
+
+        } else {
+                int i;
+                int needed = MAX_HEIGHT;
+                struct super_block *sb = fso->fso_dentry->d_inode->i_sb;
+                int blockpp = 1 << (PAGE_CACHE_SHIFT - sb->s_blocksize_bits);
+                for (i = 0; i < op; i++, fso++) {
+                        int nblocks = fso->fso_bufcnt * blockpp;
+
+                        needed += nblocks;
+                }
+                return needed + logs;
+        }
+
+        return 0;
+}
 static struct fsfilt_operations fsfilt_reiserfs_ops = {
         fs_type:                "reiserfs",
         fs_owner:               THIS_MODULE,
@@ -190,6 +225,7 @@ static struct fsfilt_operations fsfilt_reiserfs_ops = {
         fs_add_journal_cb:      fsfilt_reiserfs_add_journal_cb,
         fs_statfs:              fsfilt_reiserfs_statfs,
         fs_sync:                fsfilt_reiserfs_sync,
+        fs_get_op_len:          fsfilt_reiserfs_get_op_len,
 };
 
 static int __init fsfilt_reiserfs_init(void)
diff --git a/lustre/mds/mds_fs.c b/lustre/mds/mds_fs.c
index df159ac82fbc5fb42c1488f50d24112edb049582..ee9ed2d9fee30e4526a5e81339a41ecfafc404b2 100644
--- a/lustre/mds/mds_fs.c
+++ b/lustre/mds/mds_fs.c
@@ -138,6 +138,7 @@ int mds_client_free(struct obd_export *exp, int clear_client)
                med->med_idx, med->med_off, med->med_mcd->mcd_uuid);
 
         LASSERT(bitmap);
+
         /* Clear the bit _after_ zeroing out the client so we don't
            race with mds_client_add and zero out new clients.*/
         if (!test_bit(med->med_idx, bitmap)) {
@@ -402,11 +403,16 @@ int mds_fs_setup(struct obd_device *obd, struct vfsmount *mnt)
 
         dentry = lookup_one_len("__iopen__", current->fs->pwd,
                                 strlen("__iopen__"));
-        if (IS_ERR(dentry) || !dentry->d_inode) {
-                rc = (IS_ERR(dentry)) ? PTR_ERR(dentry): -ENOENT;
-                CERROR("cannot open iopen FH directory: rc = %d\n", rc);
+        if (IS_ERR(dentry)) {
+                rc = PTR_ERR(dentry);
+                CERROR("cannot lookup __iopen__ directory: rc = %d\n", rc);
                 GOTO(err_pop, rc);
         }
+        if (!dentry->d_inode) {
+                rc = -ENOENT;
+                CERROR("__iopen__ directory has no inode? rc = %d\n", rc);
+                GOTO(err_fid, rc);
+        }
         mds->mds_fid_de = dentry;
 
         dentry = simple_mkdir(current->fs->pwd, "PENDING", 0777, 1);
@@ -589,9 +595,9 @@ int mds_obd_create(struct obd_export *exp, struct obdo *oa,
 
         handle = fsfilt_start(exp->exp_obd, mds->mds_objects_dir->d_inode,
                               FSFILT_OP_RENAME, NULL);
-        if (IS_ERR(handle)) 
+        if (IS_ERR(handle))
                 GOTO(out_dput, rc = PTR_ERR(handle));
-        
+
         lock_kernel();
         rc = vfs_rename(mds->mds_objects_dir->d_inode, filp->f_dentry,
                         mds->mds_objects_dir->d_inode, new_child);
@@ -646,8 +652,10 @@ int mds_obd_destroy(struct obd_export *exp, struct obdo *oa,
                 GOTO(out_dput, rc = IS_ERR(de) ? PTR_ERR(de) : -ENOENT);
         }
 
-        handle = fsfilt_start(obd, mds->mds_objects_dir->d_inode,
-                              FSFILT_OP_UNLINK_LOG, oti);
+        /* Stripe count is 1 here since this is some MDS specific stuff
+           that is unlinked, not spanned across multiple OSTs */
+        handle = fsfilt_start_log(obd, mds->mds_objects_dir->d_inode,
+                                  FSFILT_OP_UNLINK, oti, 1);
         if (IS_ERR(handle)) {
                 GOTO(out_dput, rc = PTR_ERR(handle));
         }
diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c
index e959402a94dab511d160a24bd7fc033c8a14dcb9..8b8bae03f65fdbc8c97465ee179a2558b0cb954c 100644
--- a/lustre/mds/mds_open.c
+++ b/lustre/mds/mds_open.c
@@ -791,14 +791,14 @@ int mds_open(struct mds_update_record *rec, int offset,
          * opened this file and is only replaying the RPC, so we open the
          * inode by fid (at some large expense in security). */
         if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) {
-                DEBUG_REQ(D_HA, req, "open replay, disp: "LPX64"\n", 
+                DEBUG_REQ(D_HA, req, "open replay, disp: "LPX64"\n",
                           rep->lock_policy_res1);
 
                 LASSERT(rec->ur_fid2->id);
-                
+
                 rc = mds_open_by_fid(req, rec->ur_fid2, body, rec->ur_flags,
                                      rec, rep);
-                if (rc != -ENOENT) 
+                if (rc != -ENOENT)
                         RETURN(rc);
                 /* We didn't find the correct inode on disk either, so we
                  * need to re-create it via a regular replay. */
@@ -1021,6 +1021,7 @@ int mds_mfd_close(struct ptlrpc_request *req, struct obd_device *obd,
         void *handle = NULL;
         struct mds_body *request_body = NULL, *reply_body = NULL;
         struct dentry_params dp;
+        struct lov_mds_md *lmm;
         ENTRY;
 
         if (req != NULL) {
@@ -1061,8 +1062,10 @@ int mds_mfd_close(struct ptlrpc_request *req, struct obd_device *obd,
                 LASSERT(pending_child->d_inode != NULL);
 
                 cleanup_phase = 2; /* dput(pending_child) when finished */
-                handle = fsfilt_start(obd, pending_dir, FSFILT_OP_UNLINK_LOG,
-                                      NULL);
+                lmm = lustre_msg_buf(req->rq_repmsg, 1, 0);
+                handle = fsfilt_start_log(obd, pending_dir,
+                                          FSFILT_OP_UNLINK, NULL,
+                                          le32_to_cpu(lmm->lmm_stripe_count));
                 if (IS_ERR(handle)) {
                         rc = PTR_ERR(handle);
                         handle = NULL;
@@ -1072,10 +1075,10 @@ int mds_mfd_close(struct ptlrpc_request *req, struct obd_device *obd,
                 if (req != NULL &&
                     (reply_body->valid & OBD_MD_FLEASIZE) &&
                     mds_log_op_unlink(obd, pending_child->d_inode,
-                                lustre_msg_buf(req->rq_repmsg, 1, 0),
-                                req->rq_repmsg->buflens[1],
-                                lustre_msg_buf(req->rq_repmsg, 2, 0),
-                                req->rq_repmsg->buflens[2]) > 0) {
+                                      lustre_msg_buf(req->rq_repmsg, 1, 0),
+                                      req->rq_repmsg->buflens[1],
+                                      lustre_msg_buf(req->rq_repmsg, 2, 0),
+                                      req->rq_repmsg->buflens[2]) > 0) {
                         reply_body->valid |= OBD_MD_FLCOOKIE;
                 }
 
diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c
index 9e5f9720716cb9f993a298065b71c6bb85413f01..96ea3a725702ec2e54872f5e4a3531ce92fa613c 100644
--- a/lustre/mds/mds_reint.c
+++ b/lustre/mds/mds_reint.c
@@ -1198,8 +1198,11 @@ static int mds_reint_unlink(struct mds_update_record *rec, int offset,
                 rc = vfs_rmdir(dparent->d_inode, dchild);
                 break;
         case S_IFREG: {
-                handle = fsfilt_start(obd, dparent->d_inode,
-                                      FSFILT_OP_UNLINK_LOG, NULL);
+                struct lov_mds_md *lmm = lustre_msg_buf(req->rq_repmsg,
+                                                        offset + 1, 0);
+                handle = fsfilt_start_log(obd, dparent->d_inode,
+                                          FSFILT_OP_UNLINK, NULL,
+                                          le32_to_cpu(lmm->lmm_stripe_count));
                 if (IS_ERR(handle))
                         GOTO(cleanup, rc = PTR_ERR(handle));
 
diff --git a/lustre/mds/mds_unlink_open.c b/lustre/mds/mds_unlink_open.c
index 330be73a29a38756f072fb768572f83f8a37434b..87e9a2731b4bc3fd65e1d5ab4c31668b846765ac 100644
--- a/lustre/mds/mds_unlink_open.c
+++ b/lustre/mds/mds_unlink_open.c
@@ -180,7 +180,8 @@ static int mds_unlink_orphan(struct obd_device *obd, struct dentry *dchild,
                 rc = 0;
         }
 
-        handle = fsfilt_start(obd, pending_dir, FSFILT_OP_UNLINK_LOG, NULL);
+        handle = fsfilt_start_log(obd, pending_dir, FSFILT_OP_UNLINK, NULL,
+                                  le32_to_cpu(lmm->lmm_stripe_count));
         if (IS_ERR(handle)) {
                 rc = PTR_ERR(handle);
                 CERROR("error fsfilt_start: %d\n", rc);
diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c
index e3351a6b956063183a72057787469340eb82af06..83a6563c8d37865d9b56c6b8277bae5791089302 100644
--- a/lustre/obdclass/class_obd.c
+++ b/lustre/obdclass/class_obd.c
@@ -650,7 +650,7 @@ static void cleanup_obdclass(void)
 #ifdef __KERNEL__
 #include <linux/lustre_version.h>
 #define LUSTRE_MIN_VERSION 28
-#define LUSTRE_MAX_VERSION 33
+#define LUSTRE_MAX_VERSION 34
 #if (LUSTRE_KERNEL_VERSION < LUSTRE_MIN_VERSION)
 # error Cannot continue: Your Lustre kernel patch is older than the sources
 #elif (LUSTRE_KERNEL_VERSION > LUSTRE_MAX_VERSION)
diff --git a/lustre/obdclass/llog_lvfs.c b/lustre/obdclass/llog_lvfs.c
index 168a0048db8d261c586b0cc311ae1090340864cc..28503f26af125ff9bb6cfb2f06b813e64f985a01 100644
--- a/lustre/obdclass/llog_lvfs.c
+++ b/lustre/obdclass/llog_lvfs.c
@@ -163,25 +163,30 @@ static int llog_lvfs_read_header(struct llog_handle *handle)
         rc = llog_lvfs_read_blob(obd, handle->lgh_file, handle->lgh_hdr,
                                  LLOG_CHUNK_SIZE, 0);
         if (rc) {
-                CERROR("error reading log header\n");
+                CERROR("error reading log header from %*s\n",
+                       handle->lgh_file->f_dentry->d_name.len,
+                       handle->lgh_file->f_dentry->d_name.name);
         } else {
                 struct llog_rec_hdr *llh_hdr = &handle->lgh_hdr->llh_hdr;
                 /*
                  * These need to be fixed for bug 1987
                  */
                 if (llh_hdr->lrh_type != LLOG_HDR_MAGIC) {
-                        CERROR("bad log header magic: %#x (expecting %#x)\n",
+                        CERROR("bad log %*s header magic: %#x (expected %#x)\n",
+                               handle->lgh_file->f_dentry->d_name.len,
+                               handle->lgh_file->f_dentry->d_name.name,
                                llh_hdr->lrh_type, LLOG_HDR_MAGIC);
                         rc = -EIO;
                 } else if (llh_hdr->lrh_len != LLOG_CHUNK_SIZE) {
-                        CERROR("incorrectly sized log header: %#x "
-                               "(expecting %#x)\n",
+                        CERROR("incorrectly sized log %*s header: %#x "
+                               "(expected %#x)\n",
+                               handle->lgh_file->f_dentry->d_name.len,
+                               handle->lgh_file->f_dentry->d_name.name,
                                llh_hdr->lrh_len, LLOG_CHUNK_SIZE);
                         CERROR("you may need to re-run lconf --write_conf.\n");
                         rc = -EIO;
                 }
         }
-        
 
         handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index;
         handle->lgh_file->f_pos = handle->lgh_file->f_dentry->d_inode->i_size;
@@ -555,17 +560,25 @@ static int llog_lvfs_destroy(struct llog_handle *handle)
         int rc;
         ENTRY;
 
-        fdentry = handle->lgh_file->f_dentry; 
+        fdentry = handle->lgh_file->f_dentry;
         if (!strcmp(fdentry->d_parent->d_name.name, "LOGS")) {
+                struct obd_device *obd = handle->lgh_ctxt->loc_exp->exp_obd;
                 struct inode *inode = fdentry->d_parent->d_inode;
+                struct obd_run_ctxt saved;
+
+                push_ctxt(&saved, &obd->obd_ctxt, NULL);
+                dget(fdentry);
                 rc = llog_lvfs_close(handle);
-                if (rc)
-                        RETURN(rc);
 
-                down(&inode->i_sem);
-                rc = vfs_unlink(inode, fdentry);
-                up(&inode->i_sem);
-                RETURN(rc); 
+                if (rc == 0) {
+                        down(&inode->i_sem);
+                        rc = vfs_unlink(inode, fdentry);
+                        up(&inode->i_sem);
+                }
+
+                dput(fdentry);
+                pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+                RETURN(rc);
         }
 
         oa = obdo_alloc();
diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c
index d2f6369ced9cd5da0bf2d474ad1fd7dcfcc83ef9..e36921a9cc559051c5666d998bfae6b2aa9aba68 100644
--- a/lustre/obdfilter/filter.c
+++ b/lustre/obdfilter/filter.c
@@ -1881,13 +1881,13 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa,
                         } else {
                                 CERROR("Serious error: objid %*s already "
                                        "exists; is this filesystem corrupt?\n",
-                                        dchild->d_name.len, dchild->d_name.name);
+                                       dchild->d_name.len, dchild->d_name.name);
                         }
                         GOTO(cleanup, rc = -EEXIST);
                 }
 
-                handle = fsfilt_start(obd, dparent->d_inode,
-                                      FSFILT_OP_CREATE_LOG, NULL);
+                handle = fsfilt_start_log(obd, dparent->d_inode,
+                                          FSFILT_OP_CREATE, NULL, 1);
                 if (IS_ERR(handle))
                         GOTO(cleanup, rc = PTR_ERR(handle));
                 cleanup_phase = 3;
@@ -2053,7 +2053,7 @@ static int filter_destroy(struct obd_export *exp, struct obdo *oa,
                 goto acquire_locks;
         }
 
-        handle = fsfilt_start(obd, dparent->d_inode, FSFILT_OP_UNLINK_LOG, oti);
+        handle = fsfilt_start_log(obd, dparent->d_inode,FSFILT_OP_UNLINK,oti,1);
         if (IS_ERR(handle))
                 GOTO(cleanup, rc = PTR_ERR(handle));
         cleanup_phase = 3;
diff --git a/lustre/obdfilter/filter_io.c b/lustre/obdfilter/filter_io.c
index 7e305f5200ab3bd855984c7929b64e788c00974a..773baf4abad664f9a34a6fc60759751ffc13e5c9 100644
--- a/lustre/obdfilter/filter_io.c
+++ b/lustre/obdfilter/filter_io.c
@@ -151,7 +151,7 @@ static void filter_grant_incoming(struct obd_export *exp, struct obdo *oa)
         EXIT;
 }
 
-#define GRANT_FOR_LLOG 16
+#define GRANT_FOR_LLOG(obd) 16
 
 /* Figure out how much space is available between what we've granted
  * and what remains in the filesystem.  Compensate for ext3 indirect
@@ -177,8 +177,8 @@ restat:
 
         avail = obd->obd_osfs.os_bavail;
         left = avail - (avail >> (blockbits - 3)); /* (d)indirect */
-        if (left > GRANT_FOR_LLOG) {
-                left = (left - GRANT_FOR_LLOG) << blockbits;
+        if (left > GRANT_FOR_LLOG(obd)) {
+                left = (left - GRANT_FOR_LLOG(obd)) << blockbits;
         } else {
                 left = 0 /* << blockbits */;
         }
@@ -235,10 +235,13 @@ long filter_grant(struct obd_export *exp, obd_size current_grant,
          * avoid overgranting in face of multiple RPCs in flight).  This
          * essentially will be able to control the OSC_MAX_RIF for a client.
          *
-         * If we do have a large disparity and multiple RPCs in flight we
-         * might grant "too much" but that's OK because it means we are
-         * dirtying a lot on the client and will likely use it up quickly. */
+         * If we do have a large disparity between what the client thinks it
+         * has and what we think it has, don't grant very much and let the
+         * client consume its grant first.  Either it just has lots of RPCs
+         * in flight, or it was evicted and its grants will soon be used up. */
         if (current_grant < want) {
+                if (current_grant > fed->fed_grant + FILTER_GRANT_CHUNK)
+                        want = 65536;
                 grant = min((want >> blockbits) / 2,
                             (fs_space_left >> blockbits) / 8);
                 grant <<= blockbits;
diff --git a/lustre/obdfilter/filter_lvb.c b/lustre/obdfilter/filter_lvb.c
index acfba4c7ed646492ba190abc0528ab6b86511030..f664e70fde49361be35625bd7065fbca8bf69560 100644
--- a/lustre/obdfilter/filter_lvb.c
+++ b/lustre/obdfilter/filter_lvb.c
@@ -174,14 +174,14 @@ static int filter_lvbo_update(struct ldlm_resource *res, struct lustre_msg *m,
 
         if (dentry->d_inode->i_size > lvb->lvb_size || !increase) {
                 CDEBUG(D_DLMTRACE, "res: "LPU64" updating lvb size from disk: "
-                       LPU64" -> "LPU64"\n", res->lr_name.name[0],
+                       LPU64" -> %llu\n", res->lr_name.name[0],
                        lvb->lvb_size, dentry->d_inode->i_size);
                 lvb->lvb_size = dentry->d_inode->i_size;
         }
         if (dentry->d_inode->i_mtime > lvb->lvb_mtime || !increase) {
                 CDEBUG(D_DLMTRACE, "res: "LPU64" updating lvb mtime from disk: "
-                       LPU64" -> "LPU64"\n", res->lr_name.name[0],
-                       lvb->lvb_mtime,(__u64)LTIME_S(dentry->d_inode->i_mtime));
+                       LPU64" -> %lu\n", res->lr_name.name[0],
+                       lvb->lvb_mtime, LTIME_S(dentry->d_inode->i_mtime));
                 lvb->lvb_mtime = LTIME_S(dentry->d_inode->i_mtime);
         }
         f_dput(dentry);
diff --git a/lustre/ptlrpc/llog_server.c b/lustre/ptlrpc/llog_server.c
index 423651955df065f6a66acfe9ce5d343af0639236..fa53b3caf99cf9590a09533670584a59b395c655 100644
--- a/lustre/ptlrpc/llog_server.c
+++ b/lustre/ptlrpc/llog_server.c
@@ -272,8 +272,8 @@ int llog_origin_handle_cancel(struct ptlrpc_request *req)
                 LASSERT(cathandle != NULL);
                 inode = cathandle->lgh_file->f_dentry->d_inode;
 
-                handle = fsfilt_start(disk_obd, inode,
-                                      FSFILT_OP_CANCEL_UNLINK_LOG, NULL);
+                handle = fsfilt_start_log(disk_obd, inode,
+                                          FSFILT_OP_CANCEL_UNLINK, NULL, 1);
                 if (IS_ERR(handle)) {
                         CERROR("fsfilt_start failed: %ld\n", PTR_ERR(handle));
                         GOTO(pop_ctxt, rc = PTR_ERR(handle));
diff --git a/lustre/ptlrpc/recover.c b/lustre/ptlrpc/recover.c
index 613cb4828e60e5690d951c96c30b04594f98f544..18bc6f4c891c4289077bf8167a7ccea0b787dcc4 100644
--- a/lustre/ptlrpc/recover.c
+++ b/lustre/ptlrpc/recover.c
@@ -347,28 +347,26 @@ static int ptlrpc_recover_import_no_retry(struct obd_import *imp,
         spin_lock_irqsave(&imp->imp_lock, flags);
         if (imp->imp_state != LUSTRE_IMP_DISCON) {
                 in_recovery = 1;
-        } 
+        }
         spin_unlock_irqrestore(&imp->imp_lock, flags);
 
         if (in_recovery == 1)
                 RETURN(-EALREADY);
 
-        
         rc = ptlrpc_connect_import(imp, new_uuid);
         if (rc)
                 RETURN(rc);
 
-        CDEBUG(D_ERROR, "%s: recovery started, waiting\n", 
+        CDEBUG(D_ERROR, "%s: recovery started, waiting\n",
                imp->imp_target_uuid.uuid);
 
         lwi = LWI_TIMEOUT(MAX(obd_timeout * HZ, 1), NULL, NULL);
-        rc = l_wait_event(imp->imp_recovery_waitq, 
+        rc = l_wait_event(imp->imp_recovery_waitq,
                           !ptlrpc_import_in_recovery(imp), &lwi);
-        CDEBUG(D_ERROR, "%s: recovery finished\n", 
+        CDEBUG(D_ERROR, "%s: recovery finished\n",
                imp->imp_target_uuid.uuid);
 
         RETURN(rc);
-        
 }
 
 void ptlrpc_fail_export(struct obd_export *exp)
diff --git a/lustre/tests/replay-ost-single.sh b/lustre/tests/replay-ost-single.sh
index d0e534f530ce23427cc7bc9c4345f3009f28a6a3..4cb51313134c2f876951ae0c5676509818aeb381 100755
--- a/lustre/tests/replay-ost-single.sh
+++ b/lustre/tests/replay-ost-single.sh
@@ -137,24 +137,28 @@ kbytesfree() {
 
 test_6() {
     f=$DIR/$tfile
-    sync
+    rm $f 2>/dev/null && sync && sleep 2 && sync	# wait for delete thread
+    grep [0-9] /proc/fs/lustre/osc/OSC*MNT*/kbytes*
     before=`kbytesfree`
     dd if=/dev/urandom bs=1024 count=5120 of=$f
 #define OBD_FAIL_MDS_REINT_NET_REP       0x119
     do_facet mds "sysctl -w lustre.fail_loc=0x80000119"
     sync
+    sleep 1					# ensure we have a fresh statfs
+    grep [0-9] /proc/fs/lustre/osc/OSC*MNT*/kbytes*
     after_dd=`kbytesfree`
     echo "before: $before after_dd: $after_dd"
-    (( before > after_dd )) || return 1
+    (( $before > $after_dd )) || return 1
     rm -f $f
     fail ost
     $CHECKSTAT -t file $f && return 2 || true
     sync
     # let the delete happen
     sleep 2
+    grep [0-9] /proc/fs/lustre/osc/OSC*MNT*/kbytes*
     after=`kbytesfree`
     echo "before: $before after: $after"
-    (( before == after ))  || return 3
+    (( $before <= $after + 40 )) || return 3	# take OST logs into account
 }
 run_test 6 "Fail OST before obd_destroy"
 
diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh
index 538d819509735b9b2a3f68355d7b38710a34895f..7495312aaefddce51206e01cccb2fe55e99c82da 100644
--- a/lustre/tests/sanity.sh
+++ b/lustre/tests/sanity.sh
@@ -7,8 +7,8 @@
 set -e
 
 ONLY=${ONLY:-"$*"}
-# bug number for skipped test: 
-ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-""}
+# bug number for skipped test: 2399 (temporarily until new kernels arrive)
+ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"48"}
 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
 
 [ "$ALWAYS_EXCEPT$EXCEPT" ] && echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
@@ -1474,14 +1474,36 @@ test_47() {
 }
 run_test 47 "Device nodes check ================================"
 
-test_48() {
-        mkdir $DIR/d48
-        cd $DIR/d48
-        mv $DIR/d48 $DIR/d48.new || error "move directory failed"
-        mkdir $DIR/d48 || error "recreate diectory failed"
-        ls || error "can't list after recreate directory"
-}
-run_test 48 "Access renamed current working directory =========="
+test_48a() {
+	mkdir $DIR/d48a
+	cd $DIR/d48a
+	mv $DIR/d48a $DIR/d48.new || error "move directory failed"
+	mkdir $DIR/d48a || error "recreate directory failed"
+	touch foo || error "'touch foo' failed after recreating cwd"
+	mkdir bar || error "'mkdir foo' failed after recreating cwd"
+	ls . || error "'ls .' failed after recreating cwd"
+	ls .. || error "'ls ..' failed after removing cwd"
+	cd . || error "'cd .' failed after recreating cwd"
+	mkdir . && error "'mkdir .' worked after recreating cwd"
+	rmdir . && error "'rmdir .' worked after recreating cwd"
+	ln -s . baz || error "'ln -s .' failed after recreating cwd"
+}
+run_test 48a "Access renamed working dir (should return errors)="
+
+test_48b() {
+	mkdir $DIR/d48b
+	cd $DIR/d48b
+	rmdir $DIR/d48b || error "remove cwd $DIR/d48b failed"
+	touch foo && error "'touch foo' worked after removing cwd"
+	mkdir foo && error "'mkdir foo' worked after removing cwd"
+	ls . && error "'ls .' worked after removing cwd"
+	ls .. || error "'ls ..' failed after removing cwd"
+	cd . && error "'cd .' worked after recreate cwd"
+	mkdir . && error "'mkdir .' worked after removing cwd"
+	rmdir . && error "'rmdir .' worked after removing cwd"
+	ln -s . foo && error "'ln -s .' worked after removing cwd" || true
+}
+run_test 48b "Access removed working dir (should return errors)="
 
 test_50() {
 	# bug 1485