Whamcloud - gitweb
Land b1_2 onto HEAD (20040317_2319)
authoradilger <adilger>
Thu, 18 Mar 2004 07:19:06 +0000 (07:19 +0000)
committeradilger <adilger>
Thu, 18 Mar 2004 07:19:06 +0000 (07:19 +0000)
b=2939, b=2325, b=2059 (partial), b=2925, b=2399, b=2517

47 files changed:
lustre/ChangeLog
lustre/include/linux/lustre_fsfilt.h
lustre/include/linux/obd.h
lustre/kernel_patches/patches/dcache_refcount_debug.patch [new file with mode: 0644]
lustre/kernel_patches/patches/ext3-pdirops-2.4.20-chaos.patch [new file with mode: 0644]
lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch [new file with mode: 0644]
lustre/kernel_patches/patches/iopen-2.4.20.patch
lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch
lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch
lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch
lustre/kernel_patches/patches/lustre_version.patch
lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch
lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch
lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch
lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch
lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch
lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch
lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch
lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch
lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch
lustre/kernel_patches/series/chaos-2.4.21
lustre/kernel_patches/series/hp-pnnl-2.4.20
lustre/kernel_patches/series/rh-2.4.20
lustre/kernel_patches/series/vanilla-2.4.24
lustre/liblustre/namei.c
lustre/llite/Makefile.am
lustre/llite/Makefile.mk
lustre/llite/file.c
lustre/llite/sysctl.c [deleted file]
lustre/lvfs/.cvsignore
lustre/lvfs/Makefile.am
lustre/lvfs/fsfilt_ext3.c
lustre/lvfs/fsfilt_extN.c [deleted file]
lustre/lvfs/fsfilt_reiserfs.c
lustre/mds/mds_fs.c
lustre/mds/mds_open.c
lustre/mds/mds_reint.c
lustre/mds/mds_unlink_open.c
lustre/obdclass/class_obd.c
lustre/obdclass/llog_lvfs.c
lustre/obdfilter/filter.c
lustre/obdfilter/filter_io.c
lustre/obdfilter/filter_lvb.c
lustre/ptlrpc/llog_server.c
lustre/ptlrpc/recover.c
lustre/tests/replay-ost-single.sh
lustre/tests/sanity.sh

index c80989f..0eb3b7f 100644 (file)
@@ -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
index 3f3421a..40e9914 100644 (file)
@@ -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 */
index 9da934f..fb2da73 100644 (file)
@@ -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 (file)
index 0000000..0eddc23
--- /dev/null
@@ -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 (file)
index 0000000..28badd6
--- /dev/null
@@ -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 (file)
index 0000000..9203859
--- /dev/null
@@ -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 {
index 8800e1f..f409533 100644 (file)
@@ -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 */
index 16bde95..62bd8e1 100644 (file)
@@ -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 */
index 79b1f17..5500320 100644 (file)
@@ -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);
index 16e191b..726957c 100644 (file)
@@ -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 $
 + *
 + */
 +
index 86f514b..7ebb838 100644 (file)
@@ -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
 
 _
index e29ae29..41c2772 100644 (file)
 +                                                &dentry->d_name, 0, NULL);
 +                              d_invalidate(dentry);
 +                              dput(dentry);
-+                              if (IS_ERR(new)) { 
++                              if (IS_ERR(new)) {
 +                                      err = PTR_ERR(new);
 +                                      break;
 +                              }
index 5fbd0fc..7c4ea56 100644 (file)
@@ -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;
 +                              }
index 6b6027a..7741be4 100644 (file)
@@ -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;
 +                              }
index 082b8b7..8585701 100644 (file)
  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;
                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.
   */
   
  }
  
  #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;
        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);
        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;
  
        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);
        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;
        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 */
        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);
        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;
        int error;
  
        if (!capable(CAP_SYS_ADMIN))
-@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha
+@@ -908,14 +920,14 @@
  
        lock_kernel();
  
        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);
        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...
   */
  /* 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
   */
        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
   */
        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();
                        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);
                }
        }
        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. 
   */
  {
        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);
        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);
  }
  
                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)
  {
  }
   
  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;
        }
                ;
  }
  
-@@ -447,7 +499,8 @@ static inline void follow_dotdot(struct 
+@@ -447,7 +499,8 @@
   *
   * We expect 'base' to be positive and a directory.
   */
  {
        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.. */
                        ;
  
                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) {
                        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; 
                        break;
                continue;
                /* here ends the main loop */
-@@ -583,19 +636,19 @@ last_component:
+@@ -583,19 +636,19 @@
                        if (err < 0)
                                break;
                }
                        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; 
                                break;
                }
                goto return_base;
-@@ -633,6 +687,25 @@ return_reval:
+@@ -633,6 +687,27 @@
                 * Check the cached dentry for staleness.
                 */
                dentry = nd->dentry;
 +                                                &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;
        }
  }
  
  /* SMP-safe */
-@@ -739,6 +825,17 @@ walk_init_root(const char *name, struct 
+@@ -739,6 +827,17 @@
  }
  
  /* SMP-safe */
  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;
        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.
   */
  {
        struct dentry * dentry;
        struct inode *inode;
-@@ -790,13 +889,16 @@ struct dentry * lookup_hash(struct qstr 
+@@ -790,13 +891,16 @@
                        goto out;
        }
  
                dentry = inode->i_op->lookup(inode, new);
                unlock_kernel();
                if (!dentry)
-@@ -808,6 +910,12 @@ out:
+@@ -808,6 +912,12 @@
        return dentry;
  }
  
  /* 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);
  
  access:
        return ERR_PTR(-EACCES);
  }
-@@ -860,6 +968,23 @@ int __user_walk(const char *name, unsign
+@@ -860,6 +970,23 @@
        return err;
  }
  
  /*
   * 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;
  }
  
  {
        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? */
        unlock_kernel();
  exit_lock:
        up(&dir->i_zombie);
-@@ -982,6 +1111,11 @@ exit_lock:
+@@ -982,6 +1113,11 @@
        return error;
  }
  
  /*
   *    open_namei()
   *
-@@ -996,7 +1130,8 @@ exit_lock:
+@@ -996,7 +1132,8 @@
   * for symlinks (where the permissions are checked later).
   * SMP-safe
   */
  {
        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);
  
                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.
         */
        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);
  
  do_last:
        error = PTR_ERR(dentry);
-@@ -1044,11 +1186,12 @@ do_last:
+@@ -1044,11 +1188,12 @@
                goto exit;
        }
  
                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;
        }
        error = -ENOENT;
        if (!dentry->d_inode)
-@@ -1152,7 +1295,7 @@ ok:
+@@ -1152,7 +1297,7 @@
                if (!error) {
                        DQUOT_INIT(inode);
                        
                }
                put_write_access(inode);
                if (error)
-@@ -1164,8 +1307,10 @@ ok:
+@@ -1164,8 +1309,10 @@
        return 0;
  
  exit_dput:
        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);
        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);
  {
        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;
        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);
        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);
        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);
                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);
                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;
        }
        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;
        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);
                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);
                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,
  {
        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,
  {
        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;
  
        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;
        }
        dput(new_dentry);
  exit4:
        dput(old_dentry);
-@@ -1954,20 +2172,28 @@ out:
+@@ -1954,20 +2190,28 @@
  }
  
  static inline int
  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)
  {
  }
  
  /* 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);
        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>
  
  
  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);
  }
  
        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;
        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;
        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);
        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)
  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;
  
        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;
        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;
  
        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;
                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;
  
        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;
  
                path_release(&nd);
        }
  
-@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f
+@@ -385,8 +430,9 @@
  {
        int error;
        struct nameidata nd;
        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:
        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;
        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:
        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;
        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;
        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;
  
        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;
  
  {
        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) {
        return f;
  
  cleanup_all:
-@@ -713,11 +781,17 @@ cleanup_all:
+@@ -713,11 +781,17 @@
  cleanup_file:
        put_filp(f);
  cleanup_dentry:
  /*
   * 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
  {
        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;
                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;
                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;
                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;
                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;
  
                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;
  
                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 &&
                        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;
                path_release(&nd);
        }
        return error;
-@@ -348,12 +362,14 @@ asmlinkage long sys_lstat64(char * filen
+@@ -348,12 +360,14 @@
  {
        struct nameidata nd;
        int error;
                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;
  
                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;
  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>
  
  /*
   * 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 *);
  /* 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. */
  
  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
  
  #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
  
  /*
   * 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;
  
        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;
  
        /* 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;
  };
  
  /*
-@@ -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 *);
  
  /*
   * File types
-@@ -877,21 +885,32 @@ struct file_operations {
+@@ -877,21 +885,32 @@
  
  struct inode_operations {
        int (*create) (struct inode *,struct dentry *,int);
        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 */
  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 *));
  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)
 +#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 *);
  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;
                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;
                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);
  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);
                        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)) {
                        dput(fs->altroot);
                        mntput(fs->altrootmnt);
                }
-
-_
index f9096db..409c8f0 100644 (file)
  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.
   */
   
  }
  
  #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) {
                                if (!IS_ERR(file)) {
                                        err = deny_write_access(file);
                                        if (err) {
-@@ -407,6 +413,7 @@ out:
+@@ -407,6 +413,7 @@
                                return file;
                        }
                }
                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;
                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...
   */
  /* 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
   */
        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
   */
        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();
                        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);
                }
        }
        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. 
   */
  {
        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);
        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);
  }
  
                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)
  {
  }
   
  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;
        }
                ;
  }
  
-@@ -449,7 +501,8 @@ static inline void follow_dotdot(struct 
+@@ -449,7 +501,8 @@
   *
   * We expect 'base' to be positive and a directory.
   */
  {
        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.. */
  
                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) {
                        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; 
                        break;
                continue;
                /* here ends the main loop */
-@@ -592,22 +644,22 @@ last_component:
+@@ -592,22 +644,22 @@
                        if (err < 0)
                                break;
                }
                        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; 
                                break;
                }
                goto return_base;
-@@ -645,6 +698,25 @@ return_reval:
+@@ -645,6 +698,27 @@
                 * Check the cached dentry for staleness.
                 */
                dentry = nd->dentry;
 +                              }
 +                              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;
        }
  }
  
  /* SMP-safe */
-@@ -751,6 +836,17 @@ walk_init_root(const char *name, struct 
+@@ -751,6 +838,17 @@
  }
  
  /* SMP-safe */
  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;
        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.
   */
  {
        struct dentry * dentry;
        struct inode *inode;
-@@ -802,13 +900,16 @@ struct dentry * lookup_hash(struct qstr 
+@@ -802,13 +902,16 @@
                        goto out;
        }
  
                dentry = inode->i_op->lookup(inode, new);
                unlock_kernel();
                if (!dentry)
-@@ -820,6 +921,12 @@ out:
+@@ -820,6 +923,12 @@
        return dentry;
  }
  
  /* 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);
  
  access:
        return ERR_PTR(-EACCES);
  }
-@@ -872,6 +979,23 @@ int __user_walk(const char *name, unsign
+@@ -872,6 +981,23 @@
        return err;
  }
  
  /*
   * 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;
  }
  
  {
        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? */
        unlock_kernel();
  exit_lock:
        up(&dir->i_zombie);
-@@ -996,6 +1124,11 @@ exit_lock:
+@@ -996,6 +1126,11 @@
        return error;
  }
  
  /*
   *    open_namei()
   *
-@@ -1010,7 +1143,8 @@ exit_lock:
+@@ -1010,7 +1145,8 @@
   * for symlinks (where the permissions are checked later).
   * SMP-safe
   */
  {
        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);
  
                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.
         */
        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);
  
  do_last:
        error = PTR_ERR(dentry);
-@@ -1058,10 +1199,11 @@ do_last:
+@@ -1058,10 +1201,11 @@
                goto exit;
        }
  
                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;
        }
        error = -ENOENT;
        if (!dentry->d_inode)
-@@ -1165,7 +1307,7 @@ ok:
+@@ -1165,7 +1309,7 @@
                if (!error) {
                        DQUOT_INIT(inode);
                        
                }
                put_write_access(inode);
                if (error)
-@@ -1177,8 +1319,10 @@ ok:
+@@ -1177,8 +1321,10 @@
        return 0;
  
  exit_dput:
        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);
        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);
  {
        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;
        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);
        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);
        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);
                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);
                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;
        }
        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;
        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);
                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);
                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,
  {
        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,
  {
        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;
  
        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;
        }
        dput(new_dentry);
  exit4:
        dput(old_dentry);
-@@ -1965,20 +2182,28 @@ out:
+@@ -1965,20 +2200,28 @@
  }
  
  static inline int
  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)
  {
  }
  
  /* 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);
        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;
        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);
        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;
  
        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);
        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;
        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 */
        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);
        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;
        int error;
  
        if (!capable(CAP_SYS_ADMIN))
-@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha
+@@ -908,14 +920,14 @@
  
        lock_kernel();
  
        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);
        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>
  
  
  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);
  }
  
        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;
        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;
        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);
        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)
  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;
  
        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;
        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;
  
        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;
                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;
  
        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;
  
                path_release(&nd);
        }
  
-@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f
+@@ -385,8 +430,9 @@
  {
        int error;
        struct nameidata nd;
        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:
        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;
        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:
        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;
        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;
        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;
  
        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;
  
  {
        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) {
        return f;
  
  cleanup_all:
-@@ -715,11 +783,17 @@ cleanup_all:
+@@ -715,11 +783,17 @@
  cleanup_file:
        put_filp(f);
  cleanup_dentry:
  /*
   * 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;
  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
  {
        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;
  }
  
        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;
                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;
                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) {
                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 &&
                        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>
  
  /*
   * 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 *);
  /* 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. */
  
  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
  
  #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
  
  /*
   * 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;
  
        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;
  
        /* 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;
  };
  
  /*
-@@ -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 *);
  
  /*
   * File types
-@@ -882,21 +890,32 @@ struct file_operations {
+@@ -882,21 +890,32 @@
  
  struct inode_operations {
        int (*create) (struct inode *,struct dentry *,int);
        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 */
  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 *));
  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)
  
  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 *);
  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;
                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;
                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);
  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);
                        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)) {
                        dput(fs->altroot);
                        mntput(fs->altrootmnt);
                }
-
-_
index 7d83b5e..1ef0b01 100644 (file)
  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;
                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;
  }
  
  #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;
        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;
  
        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);
        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;
        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 */
        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);
        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;
        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();
  
        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);
        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...
   */
                                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;
 +                                                &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;
        }
  }
  
  /* 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 */
  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;
        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.
   */
  {
        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;
        }
  
                dentry = inode->i_op->lookup(inode, new);
                unlock_kernel();
                if (!dentry)
-@@ -808,6 +893,12 @@ out:
+@@ -810,6 +897,12 @@ out:
        return dentry;
  }
  
  /* 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);
  
  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;
  }
  
  /*
   * 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;
  }
  
  {
        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? */
        unlock_kernel();
  exit_lock:
        up(&dir->i_zombie);
-@@ -982,6 +1094,11 @@ exit_lock:
+@@ -984,6 +1098,11 @@ exit_lock:
        return error;
  }
  
  /*
   *    open_namei()
   *
-@@ -996,7 +1113,8 @@ exit_lock:
+@@ -998,7 +1117,8 @@ exit_lock:
   * for symlinks (where the permissions are checked later).
   * SMP-safe
   */
  {
        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);
  
                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.
         */
        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);
  
  do_last:
        error = PTR_ERR(dentry);
-@@ -1044,10 +1169,11 @@ do_last:
+@@ -1046,10 +1173,11 @@ do_last:
                goto exit;
        }
  
                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);
                        
                }
                put_write_access(inode);
                if (error)
-@@ -1163,8 +1289,10 @@ ok:
+@@ -1165,8 +1293,10 @@ ok:
        return 0;
  
  exit_dput:
        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);
        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);
  {
        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;
        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);
        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);
        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);
                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);
                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;
        }
        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;
        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);
                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);
                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,
  {
        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,
  {
        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;
  
        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;
        }
        dput(new_dentry);
  exit4:
        dput(old_dentry);
-@@ -1951,20 +2146,26 @@ out:
+@@ -1953,20 +2166,26 @@ out:
  }
  
  static inline int
  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)
  {
  }
  
  /* 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);
        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>
  
        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;
 +      } 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;
        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);
        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)
  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;
  
        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;
        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;
  
        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;
                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;
  
        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;
  
                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;
        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:
        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;
        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:
        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;
        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;
        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;
  
        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;
  
  {
        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) {
        return f;
  
  cleanup_all:
-@@ -713,11 +781,17 @@ cleanup_all:
+@@ -715,11 +783,17 @@ cleanup_all:
  cleanup_file:
        put_filp(f);
  cleanup_dentry:
  /*
   * 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
  {
        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;
                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;
                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;
                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;
                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;
  
                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;
  
                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 &&
                        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;
                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;
                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;
  
                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>
  
  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
  
  #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
  
  /*
   * 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;
  
        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;
  
        /* 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 *);
  
  /*
   * 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);
        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 */
  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 *));
  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 *);
  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;
                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);
                        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 */
                        dput(fs->altroot);
                        mntput(fs->altrootmnt);
                }
-
-_
index 7587ad2..09ef2f9 100644 (file)
  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);
index 492e32a..25d147d 100644 (file)
@@ -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;
 +                              }
index ff5ef61..29ad74f 100644 (file)
 +                                              &dentry->d_name, 0, NULL);
 +                              d_invalidate(dentry);
 +                              dput(dentry);
-+                              if (IS_ERR(new)) { 
++                              if (IS_ERR(new)) {
 +                                      err = PTR_ERR(new);
 +                                      break;
 +                              }
index 8e20c51..bdcae1e 100644 (file)
@@ -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
index 6cfe667..cb9c74c 100644 (file)
@@ -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
index d9c6f39..06b2642 100644 (file)
@@ -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
index 220d3bc..76ee9fa 100644 (file)
@@ -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
index 1f23df9..3929e2c 100644 (file)
@@ -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;
                 }
index 493d95c..18c3a3a 100644 (file)
@@ -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
index 0cc6697..40345b6 100644 (file)
@@ -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
index c786211..60c8304 100644 (file)
@@ -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 (file)
index b626046..0000000
+++ /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
-}
index 49c6100..f686b81 100644 (file)
@@ -7,3 +7,4 @@ Makefile.in
 .deps
 TAGS
 .*.cmd
+fsfilt_extN.c
index 1569d3b..9e91de3 100644 (file)
@@ -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
index 76a5088..25eb31c 100644 (file)
@@ -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) {
@@ -84,30 +86,26 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private)
         }
 
         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 (file)
index 8756f9a..0000000
+++ /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");
index 9864eda..b38ba4a 100644 (file)
@@ -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>
 #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)
index df159ac..ee9ed2d 100644 (file)
@@ -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));
         }
index e959402..8b8bae0 100644 (file)
@@ -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;
                 }
 
index 9e5f972..96ea3a7 100644 (file)
@@ -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));
 
index 330be73..87e9a27 100644 (file)
@@ -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);
index e3351a6..83a6563 100644 (file)
@@ -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)
index 168a004..28503f2 100644 (file)
@@ -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();
index d2f6369..e36921a 100644 (file)
@@ -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;
index 7e305f5..773baf4 100644 (file)
@@ -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;
index acfba4c..f664e70 100644 (file)
@@ -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);
index 4236519..fa53b3c 100644 (file)
@@ -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));
index 613cb48..18bc6f4 100644 (file)
@@ -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)
index d0e534f..4cb5131 100755 (executable)
@@ -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"
 
index 538d819..7495312 100644 (file)
@@ -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