Whamcloud - gitweb
- outdated patches have been removed
authoralex <alex>
Thu, 19 Aug 2004 09:32:26 +0000 (09:32 +0000)
committeralex <alex>
Thu, 19 Aug 2004 09:32:26 +0000 (09:32 +0000)
25 files changed:
lustre/kernel_patches/patches/dynamic-locks-2.4.18-chaos.patch [deleted file]
lustre/kernel_patches/patches/ext3-2.4.18-ino_sb_macro-2.patch [deleted file]
lustre/kernel_patches/patches/ext3-2.4.18-ino_sb_macro.patch [deleted file]
lustre/kernel_patches/patches/ext3-compat-2.4.18-chaos.patch [deleted file]
lustre/kernel_patches/patches/ext3-delete_thread-2.4.18-2.patch [deleted file]
lustre/kernel_patches/patches/ext3-delete_thread-2.4.18.patch [deleted file]
lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.18-chaos.patch [deleted file]
lustre/kernel_patches/patches/ext3-extents-2.4.18-chaos-pdirops.patch [deleted file]
lustre/kernel_patches/patches/ext3-extents-2.4.18-chaos.patch [deleted file]
lustre/kernel_patches/patches/ext3-extents-oflag-2.4.18-chaos.patch [deleted file]
lustre/kernel_patches/patches/ext3-inode-reuse-2.4.18.patch [deleted file]
lustre/kernel_patches/patches/ext3-trusted_ea-2.4.18.patch [deleted file]
lustre/kernel_patches/patches/gfp_memalloc-2.4.18-chaos.patch [deleted file]
lustre/kernel_patches/patches/htree-ext3-2.4.18.patch [deleted file]
lustre/kernel_patches/patches/iopen-2.4.18-2.patch [deleted file]
lustre/kernel_patches/patches/iopen-2.4.18.patch [deleted file]
lustre/kernel_patches/patches/linux-2.4.18ea-0.8.26-2.patch [deleted file]
lustre/kernel_patches/patches/linux-2.4.18ea-0.8.26.patch [deleted file]
lustre/kernel_patches/patches/listman-2.4.18.patch [deleted file]
lustre/kernel_patches/patches/loop-sync-2.4.21-suse.patch
lustre/kernel_patches/patches/nfs_export_kernel-2.4.18.patch [deleted file]
lustre/kernel_patches/patches/vfs-pdirops-2.4.18-chaos.patch [deleted file]
lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch [deleted file]
lustre/kernel_patches/series/chaos-2.4.18 [deleted file]
lustre/kernel_patches/series/chaos-2.4.18-pdirops [deleted file]

diff --git a/lustre/kernel_patches/patches/dynamic-locks-2.4.18-chaos.patch b/lustre/kernel_patches/patches/dynamic-locks-2.4.18-chaos.patch
deleted file mode 100644 (file)
index a1cef3e..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
- include/linux/dynlocks.h |   33 ++++++++++
- lib/Makefile             |    4 -
- lib/dynlocks.c           |  152 +++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 187 insertions(+), 2 deletions(-)
-
---- /dev/null  2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.18-alexey/include/linux/dynlocks.h       2003-09-01 16:33:25.000000000 +0400
-@@ -0,0 +1,33 @@
-+#ifndef _LINUX_DYNLOCKS_H
-+#define _LINUX_DYNLOCKS_H
-+
-+#include <linux/list.h>
-+#include <linux/wait.h>
-+
-+struct dynlock_member {
-+      struct list_head        dl_list;
-+      unsigned long           dl_value;       /* lock value */
-+      int                     dl_refcount;    /* number of users */
-+      int                     dl_readers;
-+      int                     dl_writers;
-+      int                     dl_pid;         /* holder of the lock */
-+      wait_queue_head_t       dl_wait;
-+};
-+
-+/*
-+ * lock's namespace:
-+ *   - list of locks
-+ *   - lock to protect this list
-+ */
-+struct dynlock {
-+      struct list_head dl_list;
-+      spinlock_t dl_list_lock;
-+};
-+
-+void dynlock_init(struct dynlock *dl);
-+void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp);
-+void dynlock_unlock(struct dynlock *dl, void *lock);
-+
-+
-+#endif
-+
---- /dev/null  2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.18-alexey/lib/dynlocks.c 2003-09-01 16:36:00.000000000 +0400
-@@ -0,0 +1,152 @@
-+/*
-+ * Dynamic Locks
-+ *
-+ * struct dynlock is lockspace
-+ * one may request lock (exclusive or shared) for some value
-+ * in that lockspace
-+ *
-+ */
-+
-+#include <linux/dynlocks.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+
-+/*
-+ * dynlock_init
-+ *
-+ * initialize lockspace
-+ *
-+ */
-+void dynlock_init(struct dynlock *dl)
-+{
-+      spin_lock_init(&dl->dl_list_lock);
-+      INIT_LIST_HEAD(&dl->dl_list);
-+}
-+
-+/*
-+ * dynlock_lock
-+ *
-+ * acquires lock (exclusive or shared) in specified lockspace
-+ * each lock in lockspace is allocated separately, so user have
-+ * to specify GFP flags.
-+ * routine returns pointer to lock. this pointer is intended to
-+ * be passed to dynlock_unlock
-+ *
-+ */
-+void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp)
-+{
-+      struct dynlock_member *nhl = NULL; 
-+      struct dynlock_member *hl; 
-+      struct list_head *cur;
-+
-+repeat:
-+      /* find requested lock in lockspace */
-+      spin_lock(&dl->dl_list_lock);
-+      list_for_each(cur, &dl->dl_list) {
-+              hl = list_entry(cur, struct dynlock_member, dl_list);
-+              if (hl->dl_value == value) {
-+                      /* lock is found */
-+                      if (nhl) {
-+                              /* someone else just allocated
-+                               * lock we didn't find and just created
-+                               * so, we drop our lock
-+                               */
-+                              kfree(nhl);
-+                              nhl = NULL;
-+                      }
-+                      hl->dl_refcount++;
-+                      goto found;
-+              }
-+      }
-+      /* lock not found */
-+      if (nhl) {
-+              /* we already have allocated lock. use it */
-+              hl = nhl;
-+              nhl = NULL;
-+              list_add(&hl->dl_list, &dl->dl_list);
-+              goto found;
-+      }
-+      spin_unlock(&dl->dl_list_lock);
-+      
-+      /* lock not found and we haven't allocated lock yet. allocate it */
-+      nhl = kmalloc(sizeof(struct dynlock_member), gfp);
-+      if (nhl == NULL)
-+              return NULL;
-+      nhl->dl_refcount = 1;
-+      nhl->dl_value = value;
-+      nhl->dl_readers = 0;
-+      nhl->dl_writers = 0;
-+      init_waitqueue_head(&nhl->dl_wait);
-+
-+      /* while lock is being allocated, someone else may allocate it
-+       * and put onto to list. check this situation
-+       */
-+      goto repeat;
-+
-+found:
-+      if (rw) {
-+              /* exclusive lock: user don't want to share lock at all
-+               * NOTE: one process may take the same lock several times
-+               * this functionaly is useful for rename operations */
-+              while ((hl->dl_writers && hl->dl_pid != current->pid) ||
-+                              hl->dl_readers) {
-+                      spin_unlock(&dl->dl_list_lock);
-+                      wait_event(hl->dl_wait,
-+                              hl->dl_writers == 0 && hl->dl_readers == 0);
-+                      spin_lock(&dl->dl_list_lock);
-+              }
-+              hl->dl_writers++;
-+      } else {
-+              /* shared lock: user do not want to share lock with writer */
-+              while (hl->dl_writers) {
-+                      spin_unlock(&dl->dl_list_lock);
-+                      wait_event(hl->dl_wait, hl->dl_writers == 0);
-+                      spin_lock(&dl->dl_list_lock);
-+              }
-+              hl->dl_readers++;
-+      }
-+      hl->dl_pid = current->pid;
-+      spin_unlock(&dl->dl_list_lock);
-+
-+      return hl;
-+}
-+
-+
-+/*
-+ * dynlock_unlock
-+ *
-+ * user have to specify lockspace (dl) and pointer to lock structure
-+ * returned by dynlock_lock()
-+ *
-+ */
-+void dynlock_unlock(struct dynlock *dl, void *lock)
-+{
-+      struct dynlock_member *hl = lock;
-+      int wakeup = 0;
-+      
-+      spin_lock(&dl->dl_list_lock);
-+      if (hl->dl_writers) {
-+              hl->dl_writers--;
-+              if (hl->dl_writers == 0)
-+                      wakeup = 1;
-+      } else {
-+              hl->dl_readers--;
-+              if (hl->dl_readers == 0)
-+                      wakeup = 1;
-+      }
-+      if (wakeup) {
-+              hl->dl_pid = 0;
-+              wake_up(&hl->dl_wait);
-+      }
-+      if (--(hl->dl_refcount) == 0) 
-+              list_del(&hl->dl_list);
-+      spin_unlock(&dl->dl_list_lock);
-+      if (hl->dl_refcount == 0)
-+              kfree(hl);
-+}
-+
-+EXPORT_SYMBOL(dynlock_init);
-+EXPORT_SYMBOL(dynlock_lock);
-+EXPORT_SYMBOL(dynlock_unlock);
-+
---- linux-2.4.18/lib/Makefile~dynamic-locks-2.4.18-chaos       2003-08-29 11:57:40.000000000 +0400
-+++ linux-2.4.18-alexey/lib/Makefile   2003-09-01 16:35:23.000000000 +0400
-@@ -8,9 +8,9 @@
- L_TARGET := lib.a
--export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o rbtree.o
-+export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o rbtree.o dynlocks.o
--obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o bust_spinlocks.o rbtree.o
-+obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o bust_spinlocks.o rbtree.o dynlocks.o
- obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
- obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
-
-_
diff --git a/lustre/kernel_patches/patches/ext3-2.4.18-ino_sb_macro-2.patch b/lustre/kernel_patches/patches/ext3-2.4.18-ino_sb_macro-2.patch
deleted file mode 100644 (file)
index bbfe6a9..0000000
+++ /dev/null
@@ -1,1478 +0,0 @@
- fs/ext3/balloc.c              |  134 +-
- fs/ext3/dir.c                 |    2 
- fs/ext3/ialloc.c              |  102 -
- fs/ext3/inode.c               |  202 +--
- fs/ext3/ioctl.c               |   13 
- fs/ext3/namei.c               |    9 
- fs/ext3/super.c               |   22 
- fs/ext3/symlink.c             |    8 
- include/linux/ext3_fs.h       |   64 
- include/linux/ext3_jbd.h      |    2 
- 19 files changed, 5574 insertions(+), 290 deletions(-)
-
---- linux-2.4.18-chaos/fs/ext3/balloc.c~ext3-2.4.18-ino_sb_macro-2     2003-07-28 17:52:04.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/balloc.c 2003-09-16 23:34:40.000000000 +0400
-@@ -46,18 +46,18 @@ struct ext3_group_desc * ext3_get_group_
-       unsigned long desc;
-       struct ext3_group_desc * gdp;
--      if (block_group >= sb->u.ext3_sb.s_groups_count) {
-+      if (block_group >= EXT3_SB(sb)->s_groups_count) {
-               ext3_error (sb, "ext3_get_group_desc",
-                           "block_group >= groups_count - "
-                           "block_group = %d, groups_count = %lu",
--                          block_group, sb->u.ext3_sb.s_groups_count);
-+                          block_group, EXT3_SB(sb)->s_groups_count);
-               return NULL;
-       }
-       
-       group_desc = block_group / EXT3_DESC_PER_BLOCK(sb);
-       desc = block_group % EXT3_DESC_PER_BLOCK(sb);
--      if (!sb->u.ext3_sb.s_group_desc[group_desc]) {
-+      if (!EXT3_SB(sb)->s_group_desc[group_desc]) {
-               ext3_error (sb, "ext3_get_group_desc",
-                           "Group descriptor not loaded - "
-                           "block_group = %d, group_desc = %lu, desc = %lu",
-@@ -66,9 +66,9 @@ struct ext3_group_desc * ext3_get_group_
-       }
-       
-       gdp = (struct ext3_group_desc *) 
--            sb->u.ext3_sb.s_group_desc[group_desc]->b_data;
-+            EXT3_SB(sb)->s_group_desc[group_desc]->b_data;
-       if (bh)
--              *bh = sb->u.ext3_sb.s_group_desc[group_desc];
-+              *bh = EXT3_SB(sb)->s_group_desc[group_desc];
-       return gdp + desc;
- }
-@@ -104,8 +104,8 @@ static int read_block_bitmap (struct sup
-        * this group.  The IO will be retried next time.
-        */
- error_out:
--      sb->u.ext3_sb.s_block_bitmap_number[bitmap_nr] = block_group;
--      sb->u.ext3_sb.s_block_bitmap[bitmap_nr] = bh;
-+      EXT3_SB(sb)->s_block_bitmap_number[bitmap_nr] = block_group;
-+      EXT3_SB(sb)->s_block_bitmap[bitmap_nr] = bh;
-       return retval;
- }
-@@ -128,16 +128,17 @@ static int __load_block_bitmap (struct s
-       int i, j, retval = 0;
-       unsigned long block_bitmap_number;
-       struct buffer_head * block_bitmap;
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
--      if (block_group >= sb->u.ext3_sb.s_groups_count)
-+      if (block_group >= sbi->s_groups_count)
-               ext3_panic (sb, "load_block_bitmap",
-                           "block_group >= groups_count - "
-                           "block_group = %d, groups_count = %lu",
--                          block_group, sb->u.ext3_sb.s_groups_count);
-+                          block_group, EXT3_SB(sb)->s_groups_count);
--      if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED) {
--              if (sb->u.ext3_sb.s_block_bitmap[block_group]) {
--                      if (sb->u.ext3_sb.s_block_bitmap_number[block_group] ==
-+      if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED) {
-+              if (sbi->s_block_bitmap[block_group]) {
-+                      if (sbi->s_block_bitmap_number[block_group] ==
-                           block_group)
-                               return block_group;
-                       ext3_error (sb, "__load_block_bitmap",
-@@ -149,21 +150,20 @@ static int __load_block_bitmap (struct s
-               return block_group;
-       }
--      for (i = 0; i < sb->u.ext3_sb.s_loaded_block_bitmaps &&
--                  sb->u.ext3_sb.s_block_bitmap_number[i] != block_group; i++)
-+      for (i = 0; i < sbi->s_loaded_block_bitmaps &&
-+                  sbi->s_block_bitmap_number[i] != block_group; i++)
-               ;
--      if (i < sb->u.ext3_sb.s_loaded_block_bitmaps &&
--          sb->u.ext3_sb.s_block_bitmap_number[i] == block_group) {
--              block_bitmap_number = sb->u.ext3_sb.s_block_bitmap_number[i];
--              block_bitmap = sb->u.ext3_sb.s_block_bitmap[i];
-+      if (i < sbi->s_loaded_block_bitmaps &&
-+          sbi->s_block_bitmap_number[i] == block_group) {
-+              block_bitmap_number = sbi->s_block_bitmap_number[i];
-+              block_bitmap = sbi->s_block_bitmap[i];
-               for (j = i; j > 0; j--) {
--                      sb->u.ext3_sb.s_block_bitmap_number[j] =
--                              sb->u.ext3_sb.s_block_bitmap_number[j - 1];
--                      sb->u.ext3_sb.s_block_bitmap[j] =
--                              sb->u.ext3_sb.s_block_bitmap[j - 1];
-+                      sbi->s_block_bitmap_number[j] =
-+                              sbi->s_block_bitmap_number[j - 1];
-+                      sbi->s_block_bitmap[j] = sbi->s_block_bitmap[j - 1];
-               }
--              sb->u.ext3_sb.s_block_bitmap_number[0] = block_bitmap_number;
--              sb->u.ext3_sb.s_block_bitmap[0] = block_bitmap;
-+              sbi->s_block_bitmap_number[0] = block_bitmap_number;
-+              sbi->s_block_bitmap[0] = block_bitmap;
-               /*
-                * There's still one special case here --- if block_bitmap == 0
-@@ -173,17 +173,14 @@ static int __load_block_bitmap (struct s
-               if (!block_bitmap)
-                       retval = read_block_bitmap (sb, block_group, 0);
-       } else {
--              if (sb->u.ext3_sb.s_loaded_block_bitmaps<EXT3_MAX_GROUP_LOADED)
--                      sb->u.ext3_sb.s_loaded_block_bitmaps++;
-+              if (sbi->s_loaded_block_bitmaps<EXT3_MAX_GROUP_LOADED)
-+                      sbi->s_loaded_block_bitmaps++;
-               else
--                      brelse (sb->u.ext3_sb.s_block_bitmap
--                                      [EXT3_MAX_GROUP_LOADED - 1]);
--              for (j = sb->u.ext3_sb.s_loaded_block_bitmaps - 1;
--                                      j > 0;  j--) {
--                      sb->u.ext3_sb.s_block_bitmap_number[j] =
--                              sb->u.ext3_sb.s_block_bitmap_number[j - 1];
--                      sb->u.ext3_sb.s_block_bitmap[j] =
--                              sb->u.ext3_sb.s_block_bitmap[j - 1];
-+                      brelse(sbi->s_block_bitmap[EXT3_MAX_GROUP_LOADED - 1]);
-+              for (j = sbi->s_loaded_block_bitmaps - 1; j > 0;  j--) {
-+                      sbi->s_block_bitmap_number[j] =
-+                              sbi->s_block_bitmap_number[j - 1];
-+                      sbi->s_block_bitmap[j] = sbi->s_block_bitmap[j - 1];
-               }
-               retval = read_block_bitmap (sb, block_group, 0);
-       }
-@@ -206,24 +203,25 @@ static int __load_block_bitmap (struct s
- static inline int load_block_bitmap (struct super_block * sb,
-                                    unsigned int block_group)
- {
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-       int slot;
--      
-+
-       /*
-        * Do the lookup for the slot.  First of all, check if we're asking
-        * for the same slot as last time, and did we succeed that last time?
-        */
--      if (sb->u.ext3_sb.s_loaded_block_bitmaps > 0 &&
--          sb->u.ext3_sb.s_block_bitmap_number[0] == block_group &&
--          sb->u.ext3_sb.s_block_bitmap[0]) {
-+      if (sbi->s_loaded_block_bitmaps > 0 &&
-+          sbi->s_block_bitmap_number[0] == block_group &&
-+          sbi->s_block_bitmap[0]) {
-               return 0;
-       }
-       /*
-        * Or can we do a fast lookup based on a loaded group on a filesystem
-        * small enough to be mapped directly into the superblock?
-        */
--      else if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED && 
--               sb->u.ext3_sb.s_block_bitmap_number[block_group]==block_group
--                      && sb->u.ext3_sb.s_block_bitmap[block_group]) {
-+      else if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED &&
-+               sbi->s_block_bitmap_number[block_group] == block_group
-+                      && sbi->s_block_bitmap[block_group]) {
-               slot = block_group;
-       }
-       /*
-@@ -243,7 +241,7 @@ static inline int load_block_bitmap (str
-        * If it's a valid slot, we may still have cached a previous IO error,
-        * in which case the bh in the superblock cache will be zero.
-        */
--      if (!sb->u.ext3_sb.s_block_bitmap[slot])
-+      if (!sbi->s_block_bitmap[slot])
-               return -EIO;
-       
-       /*
-@@ -275,7 +273,7 @@ void ext3_free_blocks (handle_t *handle,
-               return;
-       }
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       if (block < le32_to_cpu(es->s_first_data_block) ||
-           block + count < block ||
-           (block + count) > le32_to_cpu(es->s_blocks_count)) {
-@@ -305,7 +303,7 @@ do_more:
-       if (bitmap_nr < 0)
-               goto error_return;
-       
--      bitmap_bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+      bitmap_bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-       gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
-       if (!gdp)
-               goto error_return;
-@@ -330,8 +328,8 @@ do_more:
-       if (err)
-               goto error_return;
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
--      err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-       if (err)
-               goto error_return;
-@@ -339,7 +337,7 @@ do_more:
-               if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
-                   block == le32_to_cpu(gdp->bg_inode_bitmap) ||
-                   in_range(block, le32_to_cpu(gdp->bg_inode_table),
--                           sb->u.ext2_sb.s_itb_per_group)) {
-+                           EXT3_SB(sb)->s_itb_per_group)) {
-                       ext3_error(sb, __FUNCTION__,
-                                  "Freeing block in system zone - block = %lu",
-                                  block);
-@@ -412,8 +410,8 @@ do_more:
-       if (!err) err = ret;
-       /* And the superblock */
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "dirtied superblock");
--      ret = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "dirtied superblock");
-+      ret = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       if (!err) err = ret;
-       if (overflow && !err) {
-@@ -566,12 +564,12 @@ int ext3_new_block (handle_t *handle, st
-       }
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       if (le32_to_cpu(es->s_free_blocks_count) <=
-                       le32_to_cpu(es->s_r_blocks_count) &&
--          ((sb->u.ext3_sb.s_resuid != current->fsuid) &&
--           (sb->u.ext3_sb.s_resgid == 0 ||
--            !in_group_p (sb->u.ext3_sb.s_resgid)) && 
-+          ((EXT3_SB(sb)->s_resuid != current->fsuid) &&
-+           (EXT3_SB(sb)->s_resgid == 0 ||
-+            !in_group_p (EXT3_SB(sb)->s_resgid)) &&
-            !capable(CAP_SYS_RESOURCE)))
-               goto out;
-@@ -601,7 +599,7 @@ repeat:
-               if (bitmap_nr < 0)
-                       goto io_error;
-               
--              bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+              bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-               ext3_debug ("goal is at %d:%d.\n", i, j);
-@@ -624,9 +622,9 @@ repeat:
-        * Now search the rest of the groups.  We assume that 
-        * i and gdp correctly point to the last group visited.
-        */
--      for (k = 0; k < sb->u.ext3_sb.s_groups_count; k++) {
-+      for (k = 0; k < EXT3_SB(sb)->s_groups_count; k++) {
-               i++;
--              if (i >= sb->u.ext3_sb.s_groups_count)
-+              if (i >= EXT3_SB(sb)->s_groups_count)
-                       i = 0;
-               gdp = ext3_get_group_desc (sb, i, &bh2);
-               if (!gdp) {
-@@ -638,7 +636,7 @@ repeat:
-                       if (bitmap_nr < 0)
-                               goto io_error;
-       
--                      bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+                      bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-                       j = find_next_usable_block(-1, bh, 
-                                                  EXT3_BLOCKS_PER_GROUP(sb));
-                       if (j >= 0) 
-@@ -676,8 +674,8 @@ got_block:
-       fatal = ext3_journal_get_write_access(handle, bh2);
-       if (fatal) goto out;
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
--      fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+      fatal = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-       if (fatal) goto out;
-       tmp = j + i * EXT3_BLOCKS_PER_GROUP(sb)
-@@ -810,7 +808,7 @@ got_block:
-       if (!fatal) fatal = err;
-       
-       BUFFER_TRACE(bh, "journal_dirty_metadata for superblock");
--      err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+      err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       if (!fatal) fatal = err;
-       sb->s_dirt = 1;
-@@ -848,11 +846,11 @@ unsigned long ext3_count_free_blocks (st
-       int i;
-       
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       desc_count = 0;
-       bitmap_count = 0;
-       gdp = NULL;
--      for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+      for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
-               gdp = ext3_get_group_desc (sb, i, NULL);
-               if (!gdp)
-                       continue;
-@@ -861,7 +859,7 @@ unsigned long ext3_count_free_blocks (st
-               if (bitmap_nr < 0)
-                       continue;
-               
--              x = ext3_count_free (sb->u.ext3_sb.s_block_bitmap[bitmap_nr],
-+              x = ext3_count_free (EXT3_SB(sb)->s_block_bitmap[bitmap_nr],
-                                    sb->s_blocksize);
-               printk ("group %d: stored = %d, counted = %lu\n",
-                       i, le16_to_cpu(gdp->bg_free_blocks_count), x);
-@@ -872,7 +870,7 @@ unsigned long ext3_count_free_blocks (st
-       unlock_super (sb);
-       return bitmap_count;
- #else
--      return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_blocks_count);
-+      return le32_to_cpu(EXT3_SB(sb)->s_es->s_free_blocks_count);
- #endif
- }
-@@ -881,7 +879,7 @@ static inline int block_in_use (unsigned
-                               unsigned char * map)
- {
-       return ext3_test_bit ((block -
--              le32_to_cpu(sb->u.ext3_sb.s_es->s_first_data_block)) %
-+              le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
-                        EXT3_BLOCKS_PER_GROUP(sb), map);
- }
-@@ -949,11 +947,11 @@ void ext3_check_blocks_bitmap (struct su
-       struct ext3_group_desc * gdp;
-       int i;
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       desc_count = 0;
-       bitmap_count = 0;
-       gdp = NULL;
--      for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+      for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
-               gdp = ext3_get_group_desc (sb, i, NULL);
-               if (!gdp)
-                       continue;
-@@ -987,7 +985,7 @@ void ext3_check_blocks_bitmap (struct su
-                                   "Inode bitmap for group %d is marked free",
-                                   i);
--              for (j = 0; j < sb->u.ext3_sb.s_itb_per_group; j++)
-+              for (j = 0; j < EXT3_SB(sb)->s_itb_per_group; j++)
-                       if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j,
-                                                       sb, bh->b_data))
-                               ext3_error (sb, "ext3_check_blocks_bitmap",
---- linux-2.4.18-chaos/fs/ext3/dir.c~ext3-2.4.18-ino_sb_macro-2        2003-09-16 23:34:14.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/dir.c    2003-09-16 23:34:40.000000000 +0400
-@@ -67,7 +67,7 @@ int ext3_check_dir_entry (const char * f
-       else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
-               error_msg = "directory entry across blocks";
-       else if (le32_to_cpu(de->inode) >
--                      le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count))
-+                      le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
-               error_msg = "inode out of bounds";
-       if (error_msg != NULL)
---- linux-2.4.18-chaos/fs/ext3/ialloc.c~ext3-2.4.18-ino_sb_macro-2     2003-09-16 23:34:33.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/ialloc.c 2003-09-16 23:34:40.000000000 +0400
-@@ -74,8 +74,8 @@ static int read_inode_bitmap (struct sup
-        * this group.  The IO will be retried next time.
-        */
- error_out:
--      sb->u.ext3_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
--      sb->u.ext3_sb.s_inode_bitmap[bitmap_nr] = bh;
-+      EXT3_SB(sb)->s_inode_bitmap_number[bitmap_nr] = block_group;
-+      EXT3_SB(sb)->s_inode_bitmap[bitmap_nr] = bh;
-       return retval;
- }
-@@ -227,7 +227,7 @@ void ext3_free_inode (handle_t *handle, 
-       clear_inode (inode);
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       if (ino < EXT3_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
-               ext3_error (sb, "ext3_free_inode",
-                           "reserved or nonexistent inode %lu", ino);
-@@ -239,7 +239,7 @@ void ext3_free_inode (handle_t *handle, 
-       if (bitmap_nr < 0)
-               goto error_return;
--      bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-+      bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr];
-       BUFFER_TRACE(bh, "get_write_access");
-       fatal = ext3_journal_get_write_access(handle, bh);
-@@ -257,8 +257,8 @@ void ext3_free_inode (handle_t *handle, 
-               fatal = ext3_journal_get_write_access(handle, bh2);
-               if (fatal) goto error_return;
--              BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get write access");
--              fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+              BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get write access");
-+              fatal = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-               if (fatal) goto error_return;
-               if (gdp) {
-@@ -273,9 +273,9 @@ void ext3_free_inode (handle_t *handle, 
-               if (!fatal) fatal = err;
-               es->s_free_inodes_count =
-                       cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
--              BUFFER_TRACE(sb->u.ext3_sb.s_sbh,
-+              BUFFER_TRACE(EXT3_SB(sb)->s_sbh,
-                                       "call ext3_journal_dirty_metadata");
--              err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+              err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-               if (!fatal) fatal = err;
-       }
-       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-@@ -307,6 +307,8 @@ struct inode * ext3_new_inode (handle_t 
-       int i, j, avefreei;
-       struct inode * inode;
-       int bitmap_nr;
-+      struct ext3_inode_info *ei;
-+      struct ext3_sb_info *sbi;
-       struct ext3_group_desc * gdp;
-       struct ext3_group_desc * tmp;
-       struct ext3_super_block * es;
-@@ -320,7 +322,9 @@ struct inode * ext3_new_inode (handle_t 
-       inode = new_inode(sb);
-       if (!inode)
-               return ERR_PTR(-ENOMEM);
--      init_rwsem(&inode->u.ext3_i.truncate_sem);
-+      sbi = EXT3_SB(sb);
-+      ei = EXT3_I(inode);
-+      init_rwsem(&ei->truncate_sem);
-       lock_super (sb);
-       es = sb->u.ext3_sb.s_es;
-@@ -330,9 +334,9 @@ repeat:
-       if (S_ISDIR(mode)) {
-               avefreei = le32_to_cpu(es->s_free_inodes_count) /
--                      sb->u.ext3_sb.s_groups_count;
-+                      sbi->s_groups_count;
-               if (!gdp) {
--                      for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) {
-+                      for (j = 0; j < sbi->s_groups_count; j++) {
-                               struct buffer_head *temp_buffer;
-                               tmp = ext3_get_group_desc (sb, j, &temp_buffer);
-                               if (tmp &&
-@@ -352,7 +356,7 @@ repeat:
-               /*
-                * Try to place the inode in its parent directory
-                */
--              i = dir->u.ext3_i.i_block_group;
-+              i = EXT3_I(dir)->i_block_group;
-               tmp = ext3_get_group_desc (sb, i, &bh2);
-               if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
-                       gdp = tmp;
-@@ -362,10 +366,10 @@ repeat:
-                        * Use a quadratic hash to find a group with a
-                        * free inode
-                        */
--                      for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) {
-+                      for (j = 1; j < sbi->s_groups_count; j <<= 1) {
-                               i += j;
--                              if (i >= sb->u.ext3_sb.s_groups_count)
--                                      i -= sb->u.ext3_sb.s_groups_count;
-+                              if (i >= sbi->s_groups_count)
-+                                      i -= sbi->s_groups_count;
-                               tmp = ext3_get_group_desc (sb, i, &bh2);
-                               if (tmp &&
-                                   le16_to_cpu(tmp->bg_free_inodes_count)) {
-@@ -378,9 +382,9 @@ repeat:
-                       /*
-                        * That failed: try linear search for a free inode
-                        */
--                      i = dir->u.ext3_i.i_block_group + 1;
--                      for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) {
--                              if (++i >= sb->u.ext3_sb.s_groups_count)
-+                      i = EXT3_I(dir)->i_block_group + 1;
-+                      for (j = 2; j < sbi->s_groups_count; j++) {
-+                              if (++i >= sbi->s_groups_count)
-                                       i = 0;
-                               tmp = ext3_get_group_desc (sb, i, &bh2);
-                               if (tmp &&
-@@ -401,11 +405,11 @@ repeat:
-       if (bitmap_nr < 0)
-               goto fail;
--      bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-+      bh = sbi->s_inode_bitmap[bitmap_nr];
-       if ((j = ext3_find_first_zero_bit ((unsigned long *) bh->b_data,
--                                    EXT3_INODES_PER_GROUP(sb))) <
--          EXT3_INODES_PER_GROUP(sb)) {
-+                                    sbi->s_inodes_per_group)) <
-+          sbi->s_inodes_per_group) {
-               BUFFER_TRACE(bh, "get_write_access");
-               err = ext3_journal_get_write_access(handle, bh);
-               if (err) goto fail;
-@@ -459,13 +463,13 @@ repeat:
-       err = ext3_journal_dirty_metadata(handle, bh2);
-       if (err) goto fail;
-       
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
--      err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(sbi->s_sbh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, sbi->s_sbh);
-       if (err) goto fail;
-       es->s_free_inodes_count =
-               cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "call ext3_journal_dirty_metadata");
--      err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(sbi->s_sbh, "call ext3_journal_dirty_metadata");
-+      err = ext3_journal_dirty_metadata(handle, sbi->s_sbh);
-       sb->s_dirt = 1;
-       if (err) goto fail;
-@@ -485,31 +489,31 @@ repeat:
-       inode->i_blksize = PAGE_SIZE;
-       inode->i_blocks = 0;
-       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
--      inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL;
-+      ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL;
-       if (S_ISLNK(mode))
--              inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
-+              ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
- #ifdef EXT3_FRAGMENTS
--      inode->u.ext3_i.i_faddr = 0;
--      inode->u.ext3_i.i_frag_no = 0;
--      inode->u.ext3_i.i_frag_size = 0;
-+      ei->i_faddr = 0;
-+      ei->i_frag_no = 0;
-+      ei->i_frag_size = 0;
- #endif
--      inode->u.ext3_i.i_file_acl = 0;
--      inode->u.ext3_i.i_dir_acl = 0;
--      inode->u.ext3_i.i_dtime = 0;
--      INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+      ei->i_file_acl = 0;
-+      ei->i_dir_acl = 0;
-+      ei->i_dtime = 0;
-+      INIT_LIST_HEAD(&ei->i_orphan);
- #ifdef EXT3_PREALLOCATE
--      inode->u.ext3_i.i_prealloc_count = 0;
-+      ei->i_prealloc_count = 0;
- #endif
--      inode->u.ext3_i.i_block_group = i;
-+      ei->i_block_group = i;
-       
--      if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL)
-+      if (ei->i_flags & EXT3_SYNC_FL)
-               inode->i_flags |= S_SYNC;
-       if (IS_SYNC(inode))
-               handle->h_sync = 1;
-       insert_inode_hash(inode);
--      inode->i_generation = sb->u.ext3_sb.s_next_generation++;
-+      inode->i_generation = sbi->s_next_generation++;
--      inode->u.ext3_i.i_state = EXT3_STATE_NEW;
-+      ei->i_state = EXT3_STATE_NEW;
-       err = ext3_mark_inode_dirty(handle, inode);
-       if (err) goto fail;
-       
-@@ -588,19 +592,19 @@ struct inode *ext3_orphan_get(struct sup
- unsigned long ext3_count_free_inodes (struct super_block * sb)
- {
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      struct ext3_super_block *es = sbi->s_es;
- #ifdef EXT3FS_DEBUG
--      struct ext3_super_block * es;
-       unsigned long desc_count, bitmap_count, x;
-       int bitmap_nr;
-       struct ext3_group_desc * gdp;
-       int i;
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-       desc_count = 0;
-       bitmap_count = 0;
-       gdp = NULL;
--      for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+      for (i = 0; i < sbi->s_groups_count; i++) {
-               gdp = ext3_get_group_desc (sb, i, NULL);
-               if (!gdp)
-                       continue;
-@@ -609,8 +613,8 @@ unsigned long ext3_count_free_inodes (st
-               if (bitmap_nr < 0)
-                       continue;
--              x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr],
--                                   EXT3_INODES_PER_GROUP(sb) / 8);
-+              x = ext3_count_free(sbi->s_inode_bitmap[bitmap_nr],
-+                                  sbi->s_inodes_per_group / 8);
-               printk ("group %d: stored = %d, counted = %lu\n",
-                       i, le16_to_cpu(gdp->bg_free_inodes_count), x);
-               bitmap_count += x;
-@@ -620,7 +624,7 @@ unsigned long ext3_count_free_inodes (st
-       unlock_super (sb);
-       return desc_count;
- #else
--      return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_inodes_count);
-+      return le32_to_cpu(es->s_free_inodes_count);
- #endif
- }
-@@ -629,16 +633,18 @@ unsigned long ext3_count_free_inodes (st
- void ext3_check_inodes_bitmap (struct super_block * sb)
- {
-       struct ext3_super_block * es;
-+      struct ext3_sb_info *sbi;
-       unsigned long desc_count, bitmap_count, x;
-       int bitmap_nr;
-       struct ext3_group_desc * gdp;
-       int i;
--      es = sb->u.ext3_sb.s_es;
-+      sbi = EXT3_SB(sb);
-+      es = sbi->s_es;
-       desc_count = 0;
-       bitmap_count = 0;
-       gdp = NULL;
--      for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+      for (i = 0; i < sbi->s_groups_count; i++) {
-               gdp = ext3_get_group_desc (sb, i, NULL);
-               if (!gdp)
-                       continue;
-@@ -647,7 +653,7 @@ void ext3_check_inodes_bitmap (struct su
-               if (bitmap_nr < 0)
-                       continue;
--              x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr],
-+              x = ext3_count_free (sbi->s_inode_bitmap[bitmap_nr],
-                                    EXT3_INODES_PER_GROUP(sb) / 8);
-               if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
-                       ext3_error (sb, "ext3_check_inodes_bitmap",
---- linux-2.4.18-chaos/fs/ext3/inode.c~ext3-2.4.18-ino_sb_macro-2      2003-09-16 23:34:16.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/inode.c  2003-09-16 23:34:40.000000000 +0400
-@@ -206,7 +206,7 @@ void ext3_delete_inode (struct inode * i
-        * (Well, we could do this if we need to, but heck - it works)
-        */
-       ext3_orphan_del(handle, inode);
--      inode->u.ext3_i.i_dtime = CURRENT_TIME;
-+      EXT3_I(inode)->i_dtime = CURRENT_TIME;
-       /* 
-        * One subtle ordering requirement: if anything has gone wrong
-@@ -230,13 +230,14 @@ no_delete:
- void ext3_discard_prealloc (struct inode * inode)
- {
- #ifdef EXT3_PREALLOCATE
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       lock_kernel();
-       /* Writer: ->i_prealloc* */
--      if (inode->u.ext3_i.i_prealloc_count) {
--              unsigned short total = inode->u.ext3_i.i_prealloc_count;
--              unsigned long block = inode->u.ext3_i.i_prealloc_block;
--              inode->u.ext3_i.i_prealloc_count = 0;
--              inode->u.ext3_i.i_prealloc_block = 0;
-+      if (ei->i_prealloc_count) {
-+              unsigned short total = ei->i_prealloc_count;
-+              unsigned long block = ei->i_prealloc_block;
-+              ei->i_prealloc_count = 0;
-+              ei->i_prealloc_block = 0;
-               /* Writer: end */
-               ext3_free_blocks (inode, block, total);
-       }
-@@ -253,13 +254,15 @@ static int ext3_alloc_block (handle_t *h
-       unsigned long result;
- #ifdef EXT3_PREALLOCATE
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+
-       /* Writer: ->i_prealloc* */
--      if (inode->u.ext3_i.i_prealloc_count &&
--          (goal == inode->u.ext3_i.i_prealloc_block ||
--           goal + 1 == inode->u.ext3_i.i_prealloc_block))
-+      if (ei->i_prealloc_count &&
-+          (goal == ei->i_prealloc_block ||
-+           goal + 1 == ei->i_prealloc_block))
-       {
--              result = inode->u.ext3_i.i_prealloc_block++;
--              inode->u.ext3_i.i_prealloc_count--;
-+              result = ei->i_prealloc_block++;
-+              ei->i_prealloc_count--;
-               /* Writer: end */
-               ext3_debug ("preallocation hit (%lu/%lu).\n",
-                           ++alloc_hits, ++alloc_attempts);
-@@ -269,8 +272,8 @@ static int ext3_alloc_block (handle_t *h
-                           alloc_hits, ++alloc_attempts);
-               if (S_ISREG(inode->i_mode))
-                       result = ext3_new_block (inode, goal, 
--                               &inode->u.ext3_i.i_prealloc_count,
--                               &inode->u.ext3_i.i_prealloc_block, err);
-+                               &ei->i_prealloc_count,
-+                               &ei->i_prealloc_block, err);
-               else
-                       result = ext3_new_block (inode, goal, 0, 0, err);
-               /*
-@@ -404,7 +407,7 @@ static Indirect *ext3_get_branch(struct 
-       *err = 0;
-       /* i_data is not going away, no lock needed */
--      add_chain (chain, NULL, inode->u.ext3_i.i_data + *offsets);
-+      add_chain (chain, NULL, EXT3_I(inode)->i_data + *offsets);
-       if (!p->key)
-               goto no_block;
-       while (--depth) {
-@@ -448,7 +451,8 @@ no_block:
- static inline unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
- {
--      u32 *start = ind->bh ? (u32*) ind->bh->b_data : inode->u.ext3_i.i_data;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      u32 *start = ind->bh ? (u32*) ind->bh->b_data : ei->i_data;
-       u32 *p;
-       /* Try to find previous block */
-@@ -464,9 +468,8 @@ static inline unsigned long ext3_find_ne
-        * It is going to be refered from inode itself? OK, just put it into
-        * the same cylinder group then.
-        */
--      return (inode->u.ext3_i.i_block_group * 
--              EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
--             le32_to_cpu(inode->i_sb->u.ext3_sb.s_es->s_first_data_block);
-+      return (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+             le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
- }
- /**
-@@ -485,14 +488,15 @@ static inline unsigned long ext3_find_ne
- static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4],
-                         Indirect *partial, unsigned long *goal)
- {
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       /* Writer: ->i_next_alloc* */
--      if (block == inode->u.ext3_i.i_next_alloc_block + 1) {
--              inode->u.ext3_i.i_next_alloc_block++;
--              inode->u.ext3_i.i_next_alloc_goal++;
-+      if (block == ei->i_next_alloc_block + 1) {
-+              ei->i_next_alloc_block++;
-+              ei->i_next_alloc_goal++;
-       }
- #ifdef SEARCH_FROM_ZERO
--      inode->u.ext3_i.i_next_alloc_block = 0;
--      inode->u.ext3_i.i_next_alloc_goal = 0;
-+      ei->i_next_alloc_block = 0;
-+      ei->i_next_alloc_goal = 0;
- #endif
-       /* Writer: end */
-       /* Reader: pointers, ->i_next_alloc* */
-@@ -501,8 +505,8 @@ static int ext3_find_goal(struct inode *
-                * try the heuristic for sequential allocation,
-                * failing that at least try to get decent locality.
-                */
--              if (block == inode->u.ext3_i.i_next_alloc_block)
--                      *goal = inode->u.ext3_i.i_next_alloc_goal;
-+              if (block == ei->i_next_alloc_block)
-+                      *goal = ei->i_next_alloc_goal;
-               if (!*goal)
-                       *goal = ext3_find_near(inode, partial);
- #ifdef SEARCH_FROM_ZERO
-@@ -628,6 +632,7 @@ static int ext3_splice_branch(handle_t *
- {
-       int i;
-       int err = 0;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       /*
-        * If we're splicing into a [td]indirect block (as opposed to the
-@@ -650,11 +655,11 @@ static int ext3_splice_branch(handle_t *
-       /* That's it */
-       *where->p = where->key;
--      inode->u.ext3_i.i_next_alloc_block = block;
--      inode->u.ext3_i.i_next_alloc_goal = le32_to_cpu(where[num-1].key);
-+      ei->i_next_alloc_block = block;
-+      ei->i_next_alloc_goal = le32_to_cpu(where[num-1].key);
- #ifdef SEARCH_FROM_ZERO
--      inode->u.ext3_i.i_next_alloc_block = 0;
--      inode->u.ext3_i.i_next_alloc_goal = 0;
-+      ei->i_next_alloc_block = 0;
-+      ei->i_next_alloc_goal = 0;
- #endif
-       /* Writer: end */
-@@ -738,6 +743,7 @@ static int ext3_get_block_handle(handle_
-       unsigned long goal;
-       int left;
-       int depth = ext3_block_to_path(inode, iblock, offsets);
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       loff_t new_size;
-       J_ASSERT(handle != NULL || create == 0);
-@@ -791,7 +797,7 @@ out:
-       /*
-        * Block out ext3_truncate while we alter the tree
-        */
--      down_read(&inode->u.ext3_i.truncate_sem);
-+      down_read(&ei->truncate_sem);
-       err = ext3_alloc_branch(handle, inode, left, goal,
-                                       offsets+(partial-chain), partial);
-@@ -803,7 +809,7 @@ out:
-       if (!err)
-               err = ext3_splice_branch(handle, inode, iblock, chain,
-                                        partial, left);
--      up_read(&inode->u.ext3_i.truncate_sem);
-+      up_read(&ei->truncate_sem);
-       if (err == -EAGAIN)
-               goto changed;
-       if (err)
-@@ -816,8 +822,8 @@ out:
-        * truncate is in progress.  It is racy between multiple parallel
-        * instances of get_block, but we have the BKL.
-        */
--      if (new_size > inode->u.ext3_i.i_disksize)
--              inode->u.ext3_i.i_disksize = new_size;
-+      if (new_size > ei->i_disksize)
-+              ei->i_disksize = new_size;
-       bh_result->b_state |= (1UL << BH_New);
-       goto got_it;
-@@ -932,7 +938,7 @@ struct buffer_head *ext3_bread(handle_t 
-               struct buffer_head *tmp_bh;
-               for (i = 1;
--                   inode->u.ext3_i.i_prealloc_count &&
-+                   EXT3_I(inode)->i_prealloc_count &&
-                    i < EXT3_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
-                    i++) {
-                       /*
-@@ -1152,8 +1158,8 @@ static int ext3_commit_write(struct file
-                       kunmap(page);
-               }
-       }
--      if (inode->i_size > inode->u.ext3_i.i_disksize) {
--              inode->u.ext3_i.i_disksize = inode->i_size;
-+      if (inode->i_size > EXT3_I(inode)->i_disksize) {
-+              EXT3_I(inode)->i_disksize = inode->i_size;
-               ret2 = ext3_mark_inode_dirty(handle, inode);
-               if (!ret) 
-                       ret = ret2;
-@@ -1873,7 +1879,8 @@ static void ext3_free_branches(handle_t 
- void ext3_truncate(struct inode * inode)
- {
-       handle_t *handle;
--      u32 *i_data = inode->u.ext3_i.i_data;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      u32 *i_data = EXT3_I(inode)->i_data;
-       int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
-       int offsets[4];
-       Indirect chain[4];
-@@ -1934,13 +1941,13 @@ void ext3_truncate(struct inode * inode)
-        * on-disk inode. We do this via i_disksize, which is the value which
-        * ext3 *really* writes onto the disk inode.
-        */
--      inode->u.ext3_i.i_disksize = inode->i_size;
-+      ei->i_disksize = inode->i_size;
-       /*
-        * From here we block out all ext3_get_block() callers who want to
-        * modify the block allocation tree.
-        */
--      down_write(&inode->u.ext3_i.truncate_sem);
-+      down_write(&ei->truncate_sem);
-       if (n == 1) {           /* direct blocks */
-               ext3_free_data(handle, inode, NULL, i_data+offsets[0],
-@@ -2004,7 +2011,7 @@ do_indirects:
-               case EXT3_TIND_BLOCK:
-                       ;
-       }
--      up_write(&inode->u.ext3_i.truncate_sem);
-+      up_write(&ei->truncate_sem);
-       inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       ext3_mark_inode_dirty(handle, inode);
-@@ -2041,6 +2048,8 @@ out_unlock:
- int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
- {
-+      struct super_block *sb = inode->i_sb;
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-       struct buffer_head *bh = 0;
-       unsigned long block;
-       unsigned long block_group;
-@@ -2051,25 +2060,21 @@ int ext3_get_inode_loc (struct inode *in
-               
-       if ((inode->i_ino != EXT3_ROOT_INO &&
-               inode->i_ino != EXT3_JOURNAL_INO &&
--              inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
--              inode->i_ino > le32_to_cpu(
--                      inode->i_sb->u.ext3_sb.s_es->s_inodes_count)) {
--              ext3_error (inode->i_sb, "ext3_get_inode_loc",
--                          "bad inode number: %lu", inode->i_ino);
-+              inode->i_ino < EXT3_FIRST_INO(sb)) ||
-+              inode->i_ino > le32_to_cpu(sbi->s_es->s_inodes_count)) {
-+              ext3_error (sb, __FUNCTION__, "bad inode #%lu", inode->i_ino);
-               goto bad_inode;
-       }
--      block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
--      if (block_group >= inode->i_sb->u.ext3_sb.s_groups_count) {
--              ext3_error (inode->i_sb, "ext3_get_inode_loc",
--                          "group >= groups count");
-+      block_group = (inode->i_ino - 1) / sbi->s_inodes_per_group;
-+      if (block_group >= sbi->s_groups_count) {
-+              ext3_error(sb, __FUNCTION__, "group >= groups count");
-               goto bad_inode;
-       }
--      group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
--      desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
--      bh = inode->i_sb->u.ext3_sb.s_group_desc[group_desc];
-+      group_desc = block_group >> sbi->s_desc_per_block_bits;
-+      desc = block_group & (sbi->s_desc_per_block - 1);
-+      bh = sbi->s_group_desc[group_desc];
-       if (!bh) {
--              ext3_error (inode->i_sb, "ext3_get_inode_loc",
--                          "Descriptor not loaded");
-+              ext3_error(sb, __FUNCTION__, "Descriptor not loaded");
-               goto bad_inode;
-       }
-@@ -2077,17 +2082,17 @@ int ext3_get_inode_loc (struct inode *in
-       /*
-        * Figure out the offset within the block group inode table
-        */
--      offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
--              EXT3_INODE_SIZE(inode->i_sb);
-+      offset = ((inode->i_ino - 1) % sbi->s_inodes_per_group) *
-+              sbi->s_inode_size;
-       block = le32_to_cpu(gdp[desc].bg_inode_table) +
--              (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
--      if (!(bh = sb_bread(inode->i_sb, block))) {
--              ext3_error (inode->i_sb, "ext3_get_inode_loc",
-+              (offset >> EXT3_BLOCK_SIZE_BITS(sb));
-+      if (!(bh = sb_bread(sb, block))) {
-+              ext3_error (sb, __FUNCTION__,
-                           "unable to read inode block - "
-                           "inode=%lu, block=%lu", inode->i_ino, block);
-               goto bad_inode;
-       }
--      offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+      offset &= (EXT3_BLOCK_SIZE(sb) - 1);
-       iloc->bh = bh;
-       iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-@@ -2103,6 +2108,7 @@ void ext3_read_inode(struct inode * inod
- {
-       struct ext3_iloc iloc;
-       struct ext3_inode *raw_inode;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       struct buffer_head *bh;
-       int block;
-       
-@@ -2110,7 +2116,7 @@ void ext3_read_inode(struct inode * inod
-               goto bad_inode;
-       bh = iloc.bh;
-       raw_inode = iloc.raw_inode;
--      init_rwsem(&inode->u.ext3_i.truncate_sem);
-+      init_rwsem(&ei->truncate_sem);
-       inode->i_mode = le16_to_cpu(raw_inode->i_mode);
-       inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
-       inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
-@@ -2123,7 +2129,7 @@ void ext3_read_inode(struct inode * inod
-       inode->i_atime = le32_to_cpu(raw_inode->i_atime);
-       inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
-       inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
--      inode->u.ext3_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
-+      ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
-       /* We now have enough fields to check if the inode was active or not.
-        * This is needed because nfsd might try to access dead inodes
-        * the test is that same one that e2fsck uses
-@@ -2131,7 +2137,7 @@ void ext3_read_inode(struct inode * inod
-        */
-       if (inode->i_nlink == 0) {
-               if (inode->i_mode == 0 ||
--                  !(inode->i_sb->u.ext3_sb.s_mount_state & EXT3_ORPHAN_FS)) {
-+                  !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ORPHAN_FS)) {
-                       /* this inode is deleted */
-                       brelse (bh);
-                       goto bad_inode;
-@@ -2146,33 +2152,33 @@ void ext3_read_inode(struct inode * inod
-                                        * size */  
-       inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
-       inode->i_version = ++event;
--      inode->u.ext3_i.i_flags = le32_to_cpu(raw_inode->i_flags);
-+      ei->i_flags = le32_to_cpu(raw_inode->i_flags);
- #ifdef EXT3_FRAGMENTS
--      inode->u.ext3_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
--      inode->u.ext3_i.i_frag_no = raw_inode->i_frag;
--      inode->u.ext3_i.i_frag_size = raw_inode->i_fsize;
-+      ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
-+      ei->i_frag_no = raw_inode->i_frag;
-+      ei->i_frag_size = raw_inode->i_fsize;
- #endif
--      inode->u.ext3_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-+      ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-       if (!S_ISREG(inode->i_mode)) {
--              inode->u.ext3_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
-+              ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
-       } else {
-               inode->i_size |=
-                       ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
-       }
--      inode->u.ext3_i.i_disksize = inode->i_size;
-+      ei->i_disksize = inode->i_size;
-       inode->i_generation = le32_to_cpu(raw_inode->i_generation);
- #ifdef EXT3_PREALLOCATE
--      inode->u.ext3_i.i_prealloc_count = 0;
-+      ei->i_prealloc_count = 0;
- #endif
--      inode->u.ext3_i.i_block_group = iloc.block_group;
-+      ei->i_block_group = iloc.block_group;
-       /*
-        * NOTE! The in-memory inode i_data array is in little-endian order
-        * even on big-endian machines: we do NOT byteswap the block numbers!
-        */
-       for (block = 0; block < EXT3_N_BLOCKS; block++)
--              inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
--      INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+              ei->i_data[block] = iloc.raw_inode->i_block[block];
-+      INIT_LIST_HEAD(&ei->i_orphan);
-       brelse (iloc.bh);
-@@ -2194,19 +2200,19 @@ void ext3_read_inode(struct inode * inod
-               init_special_inode(inode, inode->i_mode,
-                                  le32_to_cpu(iloc.raw_inode->i_block[0]));
-       /* inode->i_attr_flags = 0;                             unused */
--      if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
-+      if (ei->i_flags & EXT3_SYNC_FL) {
-               /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
-               inode->i_flags |= S_SYNC;
-       }
--      if (inode->u.ext3_i.i_flags & EXT3_APPEND_FL) {
-+      if (ei->i_flags & EXT3_APPEND_FL) {
-               /* inode->i_attr_flags |= ATTR_FLAG_APPEND;     unused */
-               inode->i_flags |= S_APPEND;
-       }
--      if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FL) {
-+      if (ei->i_flags & EXT3_IMMUTABLE_FL) {
-               /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;  unused */
-               inode->i_flags |= S_IMMUTABLE;
-       }
--      if (inode->u.ext3_i.i_flags & EXT3_NOATIME_FL) {
-+      if (ei->i_flags & EXT3_NOATIME_FL) {
-               /* inode->i_attr_flags |= ATTR_FLAG_NOATIME;    unused */
-               inode->i_flags |= S_NOATIME;
-       }
-@@ -2228,6 +2234,7 @@ static int ext3_do_update_inode(handle_t
-                               struct ext3_iloc *iloc)
- {
-       struct ext3_inode *raw_inode = iloc->raw_inode;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       struct buffer_head *bh = iloc->bh;
-       int err = 0, rc, block;
-@@ -2245,7 +2252,7 @@ static int ext3_do_update_inode(handle_t
-  * Fix up interoperability with old kernels. Otherwise, old inodes get
-  * re-used with the upper 16 bits of the uid/gid intact
-  */
--              if(!inode->u.ext3_i.i_dtime) {
-+              if(!ei->i_dtime) {
-                       raw_inode->i_uid_high =
-                               cpu_to_le16(high_16_bits(inode->i_uid));
-                       raw_inode->i_gid_high =
-@@ -2263,34 +2270,33 @@ static int ext3_do_update_inode(handle_t
-               raw_inode->i_gid_high = 0;
-       }
-       raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
--      raw_inode->i_size = cpu_to_le32(inode->u.ext3_i.i_disksize);
-+      raw_inode->i_size = cpu_to_le32(ei->i_disksize);
-       raw_inode->i_atime = cpu_to_le32(inode->i_atime);
-       raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);
-       raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);
-       raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
--      raw_inode->i_dtime = cpu_to_le32(inode->u.ext3_i.i_dtime);
--      raw_inode->i_flags = cpu_to_le32(inode->u.ext3_i.i_flags);
-+      raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
-+      raw_inode->i_flags = cpu_to_le32(ei->i_flags);
- #ifdef EXT3_FRAGMENTS
--      raw_inode->i_faddr = cpu_to_le32(inode->u.ext3_i.i_faddr);
--      raw_inode->i_frag = inode->u.ext3_i.i_frag_no;
--      raw_inode->i_fsize = inode->u.ext3_i.i_frag_size;
-+      raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
-+      raw_inode->i_frag = ei->i_frag_no;
-+      raw_inode->i_fsize = ei->i_frag_size;
- #else
-       /* If we are not tracking these fields in the in-memory inode,
-        * then preserve them on disk, but still initialise them to zero
-        * for new inodes. */
--      if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
-+      if (ei->i_state & EXT3_STATE_NEW) {
-               raw_inode->i_faddr = 0;
-               raw_inode->i_frag = 0;
-               raw_inode->i_fsize = 0;
-       }
- #endif
--      raw_inode->i_file_acl = cpu_to_le32(inode->u.ext3_i.i_file_acl);
-+      raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
-       if (!S_ISREG(inode->i_mode)) {
--              raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext3_i.i_dir_acl);
-+              raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
-       } else {
--              raw_inode->i_size_high =
--                      cpu_to_le32(inode->u.ext3_i.i_disksize >> 32);
--              if (inode->u.ext3_i.i_disksize > 0x7fffffffULL) {
-+              raw_inode->i_size_high = cpu_to_le32(ei->i_disksize >> 32);
-+              if (ei->i_disksize > MAX_NON_LFS) {
-                       struct super_block *sb = inode->i_sb;
-                       if (!EXT3_HAS_RO_COMPAT_FEATURE(sb,
-                                       EXT3_FEATURE_RO_COMPAT_LARGE_FILE) ||
-@@ -2300,7 +2306,7 @@ static int ext3_do_update_inode(handle_t
-                               * created, add a flag to the superblock.
-                               */
-                               err = ext3_journal_get_write_access(handle,
--                                              sb->u.ext3_sb.s_sbh);
-+                                              EXT3_SB(sb)->s_sbh);
-                               if (err)
-                                       goto out_brelse;
-                               ext3_update_dynamic_rev(sb);
-@@ -2309,7 +2315,7 @@ static int ext3_do_update_inode(handle_t
-                               sb->s_dirt = 1;
-                               handle->h_sync = 1;
-                               err = ext3_journal_dirty_metadata(handle,
--                                              sb->u.ext3_sb.s_sbh);
-+                                              EXT3_SB(sb)->s_sbh);
-                       }
-               }
-       }
-@@ -2318,13 +2324,13 @@ static int ext3_do_update_inode(handle_t
-               raw_inode->i_block[0] =
-                       cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
-       else for (block = 0; block < EXT3_N_BLOCKS; block++)
--              raw_inode->i_block[block] = inode->u.ext3_i.i_data[block];
-+              raw_inode->i_block[block] = ei->i_data[block];
-       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-       rc = ext3_journal_dirty_metadata(handle, bh);
-       if (!err)
-               err = rc;
--      EXT3_I(inode)->i_state &= ~EXT3_STATE_NEW;
-+      ei->i_state &= ~EXT3_STATE_NEW;
- out_brelse:
-       brelse (bh);
-@@ -2432,7 +2438,7 @@ int ext3_setattr(struct dentry *dentry, 
-               }
-               
-               error = ext3_orphan_add(handle, inode);
--              inode->u.ext3_i.i_disksize = attr->ia_size;
-+              EXT3_I(inode)->i_disksize = attr->ia_size;
-               rc = ext3_mark_inode_dirty(handle, inode);
-               if (!error)
-                       error = rc;
-@@ -2675,9 +2681,9 @@ int ext3_change_inode_journal_flag(struc
-        */
-       if (val)
--              inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;
-+              EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL;
-       else
--              inode->u.ext3_i.i_flags &= ~EXT3_JOURNAL_DATA_FL;
-+              EXT3_I(inode)->i_flags &= ~EXT3_JOURNAL_DATA_FL;
-       journal_unlock_updates(journal);
---- linux-2.4.18-chaos/fs/ext3/ioctl.c~ext3-2.4.18-ino_sb_macro-2      2001-11-10 01:25:04.000000000 +0300
-+++ linux-2.4.18-chaos-alexey/fs/ext3/ioctl.c  2003-09-16 23:34:40.000000000 +0400
-@@ -18,13 +18,14 @@
- int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
-               unsigned long arg)
- {
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       unsigned int flags;
-       ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
-       switch (cmd) {
-       case EXT3_IOC_GETFLAGS:
--              flags = inode->u.ext3_i.i_flags & EXT3_FL_USER_VISIBLE;
-+              flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
-               return put_user(flags, (int *) arg);
-       case EXT3_IOC_SETFLAGS: {
-               handle_t *handle = NULL;
-@@ -42,7 +43,7 @@ int ext3_ioctl (struct inode * inode, st
-               if (get_user(flags, (int *) arg))
-                       return -EFAULT;
--              oldflags = inode->u.ext3_i.i_flags;
-+              oldflags = ei->i_flags;
-               /* The JOURNAL_DATA flag is modifiable only by root */
-               jflag = flags & EXT3_JOURNAL_DATA_FL;
-@@ -79,7 +80,7 @@ int ext3_ioctl (struct inode * inode, st
-               
-               flags = flags & EXT3_FL_USER_MODIFIABLE;
-               flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
--              inode->u.ext3_i.i_flags = flags;
-+              ei->i_flags = flags;
-               if (flags & EXT3_SYNC_FL)
-                       inode->i_flags |= S_SYNC;
-@@ -155,12 +156,12 @@ flags_err:
-                       int ret = 0;
-                       set_current_state(TASK_INTERRUPTIBLE);
--                      add_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait);
--                      if (timer_pending(&sb->u.ext3_sb.turn_ro_timer)) {
-+                      add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
-+                      if (timer_pending(&EXT3_SB(sb)->turn_ro_timer)) {
-                               schedule();
-                               ret = 1;
-                       }
--                      remove_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait);
-+                      remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
-                       return ret;
-               }
- #endif
---- linux-2.4.18-chaos/fs/ext3/namei.c~ext3-2.4.18-ino_sb_macro-2      2003-09-16 23:34:33.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/namei.c  2003-09-16 23:34:40.000000000 +0400
-@@ -1764,8 +1764,8 @@ int ext3_orphan_add(handle_t *handle, st
-       J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-               S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
--      err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-       if (err)
-               goto out_unlock;
-       
-@@ -1776,7 +1776,7 @@ int ext3_orphan_add(handle_t *handle, st
-       /* Insert this inode at the head of the on-disk orphan list... */
-       NEXT_ORPHAN(inode) = le32_to_cpu(EXT3_SB(sb)->s_es->s_last_orphan);
-       EXT3_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
--      err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+      err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       rc = ext3_mark_iloc_dirty(handle, inode, &iloc);
-       if (!err)
-               err = rc;
-@@ -1850,8 +1850,7 @@ int ext3_orphan_del(handle_t *handle, st
-               err = ext3_journal_dirty_metadata(handle, sbi->s_sbh);
-       } else {
-               struct ext3_iloc iloc2;
--              struct inode *i_prev =
--                      list_entry(prev, struct inode, u.ext3_i.i_orphan);
-+              struct inode *i_prev = orphan_list_entry(prev);
-               jbd_debug(4, "orphan inode %lu will point to %lu\n",
-                         i_prev->i_ino, ino_next);
---- linux-2.4.18-chaos/fs/ext3/super.c~ext3-2.4.18-ino_sb_macro-2      2003-09-16 23:34:16.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/super.c  2003-09-16 23:34:40.000000000 +0400
-@@ -124,7 +124,7 @@ static int ext3_error_behaviour(struct s
-       /* If no overrides were specified on the mount, then fall back
-        * to the default behaviour set in the filesystem's superblock
-        * on disk. */
--      switch (le16_to_cpu(sb->u.ext3_sb.s_es->s_errors)) {
-+      switch (le16_to_cpu(EXT3_SB(sb)->s_es->s_errors)) {
-       case EXT3_ERRORS_PANIC:
-               return EXT3_ERRORS_PANIC;
-       case EXT3_ERRORS_RO:
-@@ -272,9 +272,9 @@ void ext3_abort (struct super_block * sb
-               return;
-       
-       printk (KERN_CRIT "Remounting filesystem read-only\n");
--      sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS;
-+      EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
-       sb->s_flags |= MS_RDONLY;
--      sb->u.ext3_sb.s_mount_opt |= EXT3_MOUNT_ABORT;
-+      EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
-       journal_abort(EXT3_SB(sb)->s_journal, -EIO);
- }
-@@ -380,8 +380,6 @@ static int ext3_blkdev_remove(struct ext
-       return ret;
- }
--#define orphan_list_entry(l) list_entry((l), struct inode, u.ext3_i.i_orphan)
--
- static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
- {
-       struct list_head *l;
-@@ -825,7 +823,7 @@ static void ext3_orphan_cleanup (struct 
-               sb->s_flags &= ~MS_RDONLY;
-       }
--      if (sb->u.ext3_sb.s_mount_state & EXT3_ERROR_FS) {
-+      if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
-               if (es->s_last_orphan)
-                       jbd_debug(1, "Errors on filesystem, "
-                                 "clearing orphan list.\n");
-@@ -1474,12 +1472,14 @@ static void ext3_commit_super (struct su
-                              struct ext3_super_block * es,
-                              int sync)
- {
-+      struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;
-+
-       es->s_wtime = cpu_to_le32(CURRENT_TIME);
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "marking dirty");
--      mark_buffer_dirty(sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(sbh, "marking dirty");
-+      mark_buffer_dirty(sbh);
-       if (sync) {
--              ll_rw_block(WRITE, 1, &sb->u.ext3_sb.s_sbh);
--              wait_on_buffer(sb->u.ext3_sb.s_sbh);
-+              ll_rw_block(WRITE, 1, &sbh);
-+              wait_on_buffer(sbh);
-       }
- }
-@@ -1530,7 +1530,7 @@ static void ext3_clear_journal_err(struc
-               ext3_warning(sb, __FUNCTION__, "Marking fs in need of "
-                            "filesystem check.");
-               
--              sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS;
-+              EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
-               es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
-               ext3_commit_super (sb, es, 1);
---- linux-2.4.18-chaos/fs/ext3/symlink.c~ext3-2.4.18-ino_sb_macro-2    2001-11-10 01:25:04.000000000 +0300
-+++ linux-2.4.18-chaos-alexey/fs/ext3/symlink.c        2003-09-16 23:34:40.000000000 +0400
-@@ -23,14 +23,14 @@
- static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
--      char *s = (char *)dentry->d_inode->u.ext3_i.i_data;
--      return vfs_readlink(dentry, buffer, buflen, s);
-+      struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
-+      return vfs_readlink(dentry, buffer, buflen, (char *)ei->i_data);
- }
- static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
- {
--      char *s = (char *)dentry->d_inode->u.ext3_i.i_data;
--      return vfs_follow_link(nd, s);
-+      struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
-+      return vfs_follow_link(nd, (char*)ei->i_data);
- }
- struct inode_operations ext3_fast_symlink_inode_operations = {
---- linux-2.4.18-chaos/include/linux/ext3_fs.h~ext3-2.4.18-ino_sb_macro-2      2003-09-16 23:34:33.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/include/linux/ext3_fs.h  2003-09-16 23:34:40.000000000 +0400
-@@ -87,22 +87,25 @@
- #define EXT3_MIN_BLOCK_SIZE           1024
- #define       EXT3_MAX_BLOCK_SIZE             4096
- #define EXT3_MIN_BLOCK_LOG_SIZE                 10
-+
- #ifdef __KERNEL__
--# define EXT3_BLOCK_SIZE(s)           ((s)->s_blocksize)
--#else
--# define EXT3_BLOCK_SIZE(s)           (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
--#endif
--#define       EXT3_ADDR_PER_BLOCK(s)          (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
--#ifdef __KERNEL__
--# define EXT3_BLOCK_SIZE_BITS(s)      ((s)->s_blocksize_bits)
--#else
--# define EXT3_BLOCK_SIZE_BITS(s)      ((s)->s_log_block_size + 10)
--#endif
--#ifdef __KERNEL__
--#define       EXT3_ADDR_PER_BLOCK_BITS(s)     ((s)->u.ext3_sb.s_addr_per_block_bits)
--#define EXT3_INODE_SIZE(s)            ((s)->u.ext3_sb.s_inode_size)
--#define EXT3_FIRST_INO(s)             ((s)->u.ext3_sb.s_first_ino)
-+#define EXT3_SB(sb)   (&((sb)->u.ext3_sb))
-+#define EXT3_I(inode) (&((inode)->u.ext3_i))
-+
-+#define EXT3_BLOCK_SIZE(s)            ((s)->s_blocksize)
-+#define EXT3_BLOCK_SIZE_BITS(s)               ((s)->s_blocksize_bits)
-+#define       EXT3_ADDR_PER_BLOCK_BITS(s)     (EXT3_SB(s)->s_addr_per_block_bits)
-+#define EXT3_INODE_SIZE(s)            (EXT3_SB(s)->s_inode_size)
-+#define EXT3_FIRST_INO(s)             (EXT3_SB(s)->s_first_ino)
- #else
-+
-+/* Assume that user mode programs are passing in an ext3fs superblock, not
-+ * a kernel struct super_block.  This will allow us to call the feature-test
-+ * macros from user land. */
-+#define EXT3_SB(sb)   (sb)
-+
-+#define EXT3_BLOCK_SIZE(s)    (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
-+#define EXT3_BLOCK_SIZE_BITS(s)       ((s)->s_log_block_size + 10)
- #define EXT3_INODE_SIZE(s)    (((s)->s_rev_level == EXT3_GOOD_OLD_REV) ? \
-                                EXT3_GOOD_OLD_INODE_SIZE : \
-                                (s)->s_inode_size)
-@@ -110,6 +113,7 @@
-                                EXT3_GOOD_OLD_FIRST_INO : \
-                                (s)->s_first_ino)
- #endif
-+#define EXT3_ADDR_PER_BLOCK(s)        (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
- /*
-  * Macro-instructions used to manage fragments
-@@ -118,8 +122,8 @@
- #define       EXT3_MAX_FRAG_SIZE              4096
- #define EXT3_MIN_FRAG_LOG_SIZE                  10
- #ifdef __KERNEL__
--# define EXT3_FRAG_SIZE(s)            ((s)->u.ext3_sb.s_frag_size)
--# define EXT3_FRAGS_PER_BLOCK(s)      ((s)->u.ext3_sb.s_frags_per_block)
-+# define EXT3_FRAG_SIZE(s)            (EXT3_SB(s)->s_frag_size)
-+# define EXT3_FRAGS_PER_BLOCK(s)      (EXT3_SB(s)->s_frags_per_block)
- #else
- # define EXT3_FRAG_SIZE(s)            (EXT3_MIN_FRAG_SIZE << (s)->s_log_frag_size)
- # define EXT3_FRAGS_PER_BLOCK(s)      (EXT3_BLOCK_SIZE(s) / EXT3_FRAG_SIZE(s))
-@@ -143,15 +147,13 @@ struct ext3_group_desc
- /*
-  * Macro-instructions used to manage group descriptors
-  */
-+# define EXT3_BLOCKS_PER_GROUP(s)     (EXT3_SB(s)->s_blocks_per_group)
-+# define EXT3_INODES_PER_GROUP(s)     (EXT3_SB(s)->s_inodes_per_group)
- #ifdef __KERNEL__
--# define EXT3_BLOCKS_PER_GROUP(s)     ((s)->u.ext3_sb.s_blocks_per_group)
--# define EXT3_DESC_PER_BLOCK(s)               ((s)->u.ext3_sb.s_desc_per_block)
--# define EXT3_INODES_PER_GROUP(s)     ((s)->u.ext3_sb.s_inodes_per_group)
--# define EXT3_DESC_PER_BLOCK_BITS(s)  ((s)->u.ext3_sb.s_desc_per_block_bits)
-+# define EXT3_DESC_PER_BLOCK(s)               (EXT3_SB(s)->s_desc_per_block)
-+# define EXT3_DESC_PER_BLOCK_BITS(s)  (EXT3_SB(s)->s_desc_per_block_bits)
- #else
--# define EXT3_BLOCKS_PER_GROUP(s)     ((s)->s_blocks_per_group)
- # define EXT3_DESC_PER_BLOCK(s)               (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_group_desc))
--# define EXT3_INODES_PER_GROUP(s)     ((s)->s_inodes_per_group)
- #endif
- /*
-@@ -325,7 +327,7 @@ struct ext3_inode {
- #ifndef _LINUX_EXT2_FS_H
- #define clear_opt(o, opt)             o &= ~EXT3_MOUNT_##opt
- #define set_opt(o, opt)                       o |= EXT3_MOUNT_##opt
--#define test_opt(sb, opt)             ((sb)->u.ext3_sb.s_mount_opt & \
-+#define test_opt(sb, opt)             (EXT3_SB(sb)->s_mount_opt & \
-                                        EXT3_MOUNT_##opt)
- #else
- #define EXT2_MOUNT_NOLOAD             EXT3_MOUNT_NOLOAD
-@@ -425,17 +427,11 @@ struct ext3_super_block {
-       __u32   s_reserved[192];        /* Padding to the end of the block */
- };
--#ifdef __KERNEL__
--#define EXT3_SB(sb)   (&((sb)->u.ext3_sb))
--#define EXT3_I(inode) (&((inode)->u.ext3_i))
--#else
--/* Assume that user mode programs are passing in an ext3fs superblock, not
-- * a kernel struct super_block.  This will allow us to call the feature-test
-- * macros from user land. */
--#define EXT3_SB(sb)   (sb)
--#endif
--
--#define NEXT_ORPHAN(inode) (inode)->u.ext3_i.i_dtime
-+#define NEXT_ORPHAN(inode) EXT3_I(inode)->i_dtime
-+static inline struct inode *orphan_list_entry(struct list_head *l)
-+{
-+      return list_entry(l, struct inode, u.ext3_i.i_orphan);
-+}
- /*
-  * Codes for operating systems
---- linux-2.4.18-chaos/include/linux/ext3_jbd.h~ext3-2.4.18-ino_sb_macro-2     2003-09-16 23:34:16.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/include/linux/ext3_jbd.h 2003-09-16 23:34:40.000000000 +0400
-@@ -297,7 +297,7 @@ static inline int ext3_should_journal_da
-               return 1;
-       if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
-               return 1;
--      if (inode->u.ext3_i.i_flags & EXT3_JOURNAL_DATA_FL)
-+      if (EXT3_I(inode)->i_flags & EXT3_JOURNAL_DATA_FL)
-               return 1;
-       return 0;
- }
diff --git a/lustre/kernel_patches/patches/ext3-2.4.18-ino_sb_macro.patch b/lustre/kernel_patches/patches/ext3-2.4.18-ino_sb_macro.patch
deleted file mode 100644 (file)
index 2ddff7d..0000000
+++ /dev/null
@@ -1,1540 +0,0 @@
---- ./fs/ext3/balloc.c.orig    Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/balloc.c Tue May  7 15:35:59 2002
-@@ -46,18 +46,18 @@ struct ext3_group_desc * ext3_get_group_
-       unsigned long desc;
-       struct ext3_group_desc * gdp;
--      if (block_group >= sb->u.ext3_sb.s_groups_count) {
-+      if (block_group >= EXT3_SB(sb)->s_groups_count) {
-               ext3_error (sb, "ext3_get_group_desc",
-                           "block_group >= groups_count - "
-                           "block_group = %d, groups_count = %lu",
--                          block_group, sb->u.ext3_sb.s_groups_count);
-+                          block_group, EXT3_SB(sb)->s_groups_count);
-               return NULL;
-       }
-       
-       group_desc = block_group / EXT3_DESC_PER_BLOCK(sb);
-       desc = block_group % EXT3_DESC_PER_BLOCK(sb);
--      if (!sb->u.ext3_sb.s_group_desc[group_desc]) {
-+      if (!EXT3_SB(sb)->s_group_desc[group_desc]) {
-               ext3_error (sb, "ext3_get_group_desc",
-                           "Group descriptor not loaded - "
-                           "block_group = %d, group_desc = %lu, desc = %lu",
-@@ -66,9 +66,9 @@ struct ext3_group_desc * ext3_get_group_
-       }
-       
-       gdp = (struct ext3_group_desc *) 
--            sb->u.ext3_sb.s_group_desc[group_desc]->b_data;
-+            EXT3_SB(sb)->s_group_desc[group_desc]->b_data;
-       if (bh)
--              *bh = sb->u.ext3_sb.s_group_desc[group_desc];
-+              *bh = EXT3_SB(sb)->s_group_desc[group_desc];
-       return gdp + desc;
- }
-@@ -104,8 +104,8 @@ static int read_block_bitmap (struct sup
-        * this group.  The IO will be retried next time.
-        */
- error_out:
--      sb->u.ext3_sb.s_block_bitmap_number[bitmap_nr] = block_group;
--      sb->u.ext3_sb.s_block_bitmap[bitmap_nr] = bh;
-+      EXT3_SB(sb)->s_block_bitmap_number[bitmap_nr] = block_group;
-+      EXT3_SB(sb)->s_block_bitmap[bitmap_nr] = bh;
-       return retval;
- }
-@@ -128,16 +128,17 @@ static int __load_block_bitmap (struct s
-       int i, j, retval = 0;
-       unsigned long block_bitmap_number;
-       struct buffer_head * block_bitmap;
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
--      if (block_group >= sb->u.ext3_sb.s_groups_count)
-+      if (block_group >= sbi->s_groups_count)
-               ext3_panic (sb, "load_block_bitmap",
-                           "block_group >= groups_count - "
-                           "block_group = %d, groups_count = %lu",
--                          block_group, sb->u.ext3_sb.s_groups_count);
-+                          block_group, EXT3_SB(sb)->s_groups_count);
--      if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED) {
--              if (sb->u.ext3_sb.s_block_bitmap[block_group]) {
--                      if (sb->u.ext3_sb.s_block_bitmap_number[block_group] ==
-+      if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED) {
-+              if (sbi->s_block_bitmap[block_group]) {
-+                      if (sbi->s_block_bitmap_number[block_group] ==
-                           block_group)
-                               return block_group;
-                       ext3_error (sb, "__load_block_bitmap",
-@@ -149,21 +150,20 @@ static int __load_block_bitmap (struct s
-               return block_group;
-       }
--      for (i = 0; i < sb->u.ext3_sb.s_loaded_block_bitmaps &&
--                  sb->u.ext3_sb.s_block_bitmap_number[i] != block_group; i++)
-+      for (i = 0; i < sbi->s_loaded_block_bitmaps &&
-+                  sbi->s_block_bitmap_number[i] != block_group; i++)
-               ;
--      if (i < sb->u.ext3_sb.s_loaded_block_bitmaps &&
--          sb->u.ext3_sb.s_block_bitmap_number[i] == block_group) {
--              block_bitmap_number = sb->u.ext3_sb.s_block_bitmap_number[i];
--              block_bitmap = sb->u.ext3_sb.s_block_bitmap[i];
-+      if (i < sbi->s_loaded_block_bitmaps &&
-+          sbi->s_block_bitmap_number[i] == block_group) {
-+              block_bitmap_number = sbi->s_block_bitmap_number[i];
-+              block_bitmap = sbi->s_block_bitmap[i];
-               for (j = i; j > 0; j--) {
--                      sb->u.ext3_sb.s_block_bitmap_number[j] =
--                              sb->u.ext3_sb.s_block_bitmap_number[j - 1];
--                      sb->u.ext3_sb.s_block_bitmap[j] =
--                              sb->u.ext3_sb.s_block_bitmap[j - 1];
-+                      sbi->s_block_bitmap_number[j] =
-+                              sbi->s_block_bitmap_number[j - 1];
-+                      sbi->s_block_bitmap[j] = sbi->s_block_bitmap[j - 1];
-               }
--              sb->u.ext3_sb.s_block_bitmap_number[0] = block_bitmap_number;
--              sb->u.ext3_sb.s_block_bitmap[0] = block_bitmap;
-+              sbi->s_block_bitmap_number[0] = block_bitmap_number;
-+              sbi->s_block_bitmap[0] = block_bitmap;
-               /*
-                * There's still one special case here --- if block_bitmap == 0
-@@ -173,17 +173,14 @@ static int __load_block_bitmap (struct s
-               if (!block_bitmap)
-                       retval = read_block_bitmap (sb, block_group, 0);
-       } else {
--              if (sb->u.ext3_sb.s_loaded_block_bitmaps<EXT3_MAX_GROUP_LOADED)
--                      sb->u.ext3_sb.s_loaded_block_bitmaps++;
-+              if (sbi->s_loaded_block_bitmaps<EXT3_MAX_GROUP_LOADED)
-+                      sbi->s_loaded_block_bitmaps++;
-               else
--                      brelse (sb->u.ext3_sb.s_block_bitmap
--                                      [EXT3_MAX_GROUP_LOADED - 1]);
--              for (j = sb->u.ext3_sb.s_loaded_block_bitmaps - 1;
--                                      j > 0;  j--) {
--                      sb->u.ext3_sb.s_block_bitmap_number[j] =
--                              sb->u.ext3_sb.s_block_bitmap_number[j - 1];
--                      sb->u.ext3_sb.s_block_bitmap[j] =
--                              sb->u.ext3_sb.s_block_bitmap[j - 1];
-+                      brelse(sbi->s_block_bitmap[EXT3_MAX_GROUP_LOADED - 1]);
-+              for (j = sbi->s_loaded_block_bitmaps - 1; j > 0;  j--) {
-+                      sbi->s_block_bitmap_number[j] =
-+                              sbi->s_block_bitmap_number[j - 1];
-+                      sbi->s_block_bitmap[j] = sbi->s_block_bitmap[j - 1];
-               }
-               retval = read_block_bitmap (sb, block_group, 0);
-       }
-@@ -206,24 +203,25 @@ static int __load_block_bitmap (struct s
- static inline int load_block_bitmap (struct super_block * sb,
-                                    unsigned int block_group)
- {
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-       int slot;
--      
-+
-       /*
-        * Do the lookup for the slot.  First of all, check if we're asking
-        * for the same slot as last time, and did we succeed that last time?
-        */
--      if (sb->u.ext3_sb.s_loaded_block_bitmaps > 0 &&
--          sb->u.ext3_sb.s_block_bitmap_number[0] == block_group &&
--          sb->u.ext3_sb.s_block_bitmap[0]) {
-+      if (sbi->s_loaded_block_bitmaps > 0 &&
-+          sbi->s_block_bitmap_number[0] == block_group &&
-+          sbi->s_block_bitmap[0]) {
-               return 0;
-       }
-       /*
-        * Or can we do a fast lookup based on a loaded group on a filesystem
-        * small enough to be mapped directly into the superblock?
-        */
--      else if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED && 
--               sb->u.ext3_sb.s_block_bitmap_number[block_group]==block_group
--                      && sb->u.ext3_sb.s_block_bitmap[block_group]) {
-+      else if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED &&
-+               sbi->s_block_bitmap_number[block_group] == block_group
-+                      && sbi->s_block_bitmap[block_group]) {
-               slot = block_group;
-       }
-       /*
-@@ -243,7 +241,7 @@ static inline int load_block_bitmap (str
-        * If it's a valid slot, we may still have cached a previous IO error,
-        * in which case the bh in the superblock cache will be zero.
-        */
--      if (!sb->u.ext3_sb.s_block_bitmap[slot])
-+      if (!sbi->s_block_bitmap[slot])
-               return -EIO;
-       
-       /*
-@@ -275,7 +273,7 @@ void ext3_free_blocks (handle_t *handle,
-               return;
-       }
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       if (block < le32_to_cpu(es->s_first_data_block) ||
-           block + count < block ||
-           (block + count) > le32_to_cpu(es->s_blocks_count)) {
-@@ -304,7 +302,7 @@ do_more:
-       if (bitmap_nr < 0)
-               goto error_return;
-       
--      bitmap_bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+      bitmap_bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-       gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
-       if (!gdp)
-               goto error_return;
-@@ -330,8 +328,8 @@ do_more:
-       if (err)
-               goto error_return;
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
--      err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-       if (err)
-               goto error_return;
-@@ -341,7 +339,7 @@
-               if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
-                   block == le32_to_cpu(gdp->bg_inode_bitmap) ||
-                   in_range(block, le32_to_cpu(gdp->bg_inode_table),
--                           sb->u.ext2_sb.s_itb_per_group)) {
-+                           EXT3_SB(sb)->s_itb_per_group)) {
-                       ext3_error(sb, __FUNCTION__,
-                                  "Freeing block in system zone - block = %lu",
-                                  block);
-@@ -410,8 +407,8 @@ do_more:
-       if (!err) err = ret;
-       /* And the superblock */
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "dirtied superblock");
--      ret = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "dirtied superblock");
-+      ret = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       if (!err) err = ret;
-       if (overflow && !err) {
-@@ -564,12 +560,12 @@ int ext3_new_block (handle_t *handle, st
-       }
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       if (le32_to_cpu(es->s_free_blocks_count) <=
-                       le32_to_cpu(es->s_r_blocks_count) &&
--          ((sb->u.ext3_sb.s_resuid != current->fsuid) &&
--           (sb->u.ext3_sb.s_resgid == 0 ||
--            !in_group_p (sb->u.ext3_sb.s_resgid)) && 
-+          ((EXT3_SB(sb)->s_resuid != current->fsuid) &&
-+           (EXT3_SB(sb)->s_resgid == 0 ||
-+            !in_group_p (EXT3_SB(sb)->s_resgid)) &&
-            !capable(CAP_SYS_RESOURCE)))
-               goto out;
-@@ -598,7 +595,7 @@ int ext3_new_block (handle_t *handle, st
-               if (bitmap_nr < 0)
-                       goto io_error;
-               
--              bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+              bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-               ext3_debug ("goal is at %d:%d.\n", i, j);
-@@ -621,9 +618,9 @@ int ext3_new_block (handle_t *handle, st
-        * Now search the rest of the groups.  We assume that 
-        * i and gdp correctly point to the last group visited.
-        */
--      for (k = 0; k < sb->u.ext3_sb.s_groups_count; k++) {
-+      for (k = 0; k < EXT3_SB(sb)->s_groups_count; k++) {
-               i++;
--              if (i >= sb->u.ext3_sb.s_groups_count)
-+              if (i >= EXT3_SB(sb)->s_groups_count)
-                       i = 0;
-               gdp = ext3_get_group_desc (sb, i, &bh2);
-               if (!gdp) {
-@@ -635,7 +632,7 @@ int ext3_new_block (handle_t *handle, st
-                       if (bitmap_nr < 0)
-                               goto io_error;
-       
--                      bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+                      bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-                       j = find_next_usable_block(-1, bh, 
-                                                  EXT3_BLOCKS_PER_GROUP(sb));
-                       if (j >= 0) 
-@@ -674,8 +671,8 @@ got_block:
-       fatal = ext3_journal_get_write_access(handle, bh2);
-       if (fatal) goto out;
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
--      fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+      fatal = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-       if (fatal) goto out;
-       tmp = j + i * EXT3_BLOCKS_PER_GROUP(sb)
-@@ -796,7 +804,7 @@ got_block:
-       if (!fatal) fatal = err;
-       
-       BUFFER_TRACE(bh, "journal_dirty_metadata for superblock");
--      err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+      err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       if (!fatal) fatal = err;
-       sb->s_dirt = 1;
-@@ -829,11 +837,11 @@ unsigned long ext3_count_free_blocks (st
-       int i;
-       
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       desc_count = 0;
-       bitmap_count = 0;
-       gdp = NULL;
--      for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+      for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
-               gdp = ext3_get_group_desc (sb, i, NULL);
-               if (!gdp)
-                       continue;
-@@ -842,7 +850,7 @@ unsigned long ext3_count_free_blocks (st
-               if (bitmap_nr < 0)
-                       continue;
-               
--              x = ext3_count_free (sb->u.ext3_sb.s_block_bitmap[bitmap_nr],
-+              x = ext3_count_free (EXT3_SB(sb)->s_block_bitmap[bitmap_nr],
-                                    sb->s_blocksize);
-               printk ("group %d: stored = %d, counted = %lu\n",
-                       i, le16_to_cpu(gdp->bg_free_blocks_count), x);
-@@ -853,7 +861,7 @@ unsigned long ext3_count_free_blocks (st
-       unlock_super (sb);
-       return bitmap_count;
- #else
--      return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_blocks_count);
-+      return le32_to_cpu(EXT3_SB(sb)->s_es->s_free_blocks_count);
- #endif
- }
-@@ -862,7 +870,7 @@ static inline int block_in_use (unsigned
-                               unsigned char * map)
- {
-       return ext3_test_bit ((block -
--              le32_to_cpu(sb->u.ext3_sb.s_es->s_first_data_block)) %
-+              le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
-                        EXT3_BLOCKS_PER_GROUP(sb), map);
- }
-@@ -930,11 +938,11 @@ void ext3_check_blocks_bitmap (struct su
-       struct ext3_group_desc * gdp;
-       int i;
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       desc_count = 0;
-       bitmap_count = 0;
-       gdp = NULL;
--      for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+      for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
-               gdp = ext3_get_group_desc (sb, i, NULL);
-               if (!gdp)
-                       continue;
-@@ -968,7 +976,7 @@ void ext3_check_blocks_bitmap (struct su
-                                   "Inode bitmap for group %d is marked free",
-                                   i);
--              for (j = 0; j < sb->u.ext3_sb.s_itb_per_group; j++)
-+              for (j = 0; j < EXT3_SB(sb)->s_itb_per_group; j++)
-                       if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j,
-                                                       sb, bh->b_data))
-                               ext3_error (sb, "ext3_check_blocks_bitmap",
---- ./fs/ext3/dir.c.orig       Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/dir.c    Tue May  7 14:54:13 2002
-@@ -52,7 +52,7 @@ int ext3_check_dir_entry (const char * f
-       else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
-               error_msg = "directory entry across blocks";
-       else if (le32_to_cpu(de->inode) >
--                      le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count))
-+                      le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
-               error_msg = "inode out of bounds";
-       if (error_msg != NULL)
---- ./fs/ext3/ialloc.c.orig    Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/ialloc.c Tue May  7 15:39:26 2002
-@@ -73,8 +73,8 @@ static int read_inode_bitmap (struct sup
-        * this group.  The IO will be retried next time.
-        */
- error_out:
--      sb->u.ext3_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
--      sb->u.ext3_sb.s_inode_bitmap[bitmap_nr] = bh;
-+      EXT3_SB(sb)->s_inode_bitmap_number[bitmap_nr] = block_group;
-+      EXT3_SB(sb)->s_inode_bitmap[bitmap_nr] = bh;
-       return retval;
- }
-@@ -225,7 +225,7 @@ void ext3_free_inode (handle_t *handle, 
-       clear_inode (inode);
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-+      es = EXT3_SB(sb)->s_es;
-       if (ino < EXT3_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
-               ext3_error (sb, "ext3_free_inode",
-                           "reserved or nonexistent inode %lu", ino);
-@@ -237,7 +237,7 @@ void ext3_free_inode (handle_t *handle, 
-       if (bitmap_nr < 0)
-               goto error_return;
--      bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-+      bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr];
-       BUFFER_TRACE(bh, "get_write_access");
-       fatal = ext3_journal_get_write_access(handle, bh);
-@@ -255,8 +255,8 @@ void ext3_free_inode (handle_t *handle, 
-               fatal = ext3_journal_get_write_access(handle, bh2);
-               if (fatal) goto error_return;
--              BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get write access");
--              fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+              BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get write access");
-+              fatal = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-               if (fatal) goto error_return;
-               if (gdp) {
-@@ -271,9 +271,9 @@ void ext3_free_inode (handle_t *handle, 
-               if (!fatal) fatal = err;
-               es->s_free_inodes_count =
-                       cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
--              BUFFER_TRACE(sb->u.ext3_sb.s_sbh,
-+              BUFFER_TRACE(EXT3_SB(sb)->s_sbh,
-                                       "call ext3_journal_dirty_metadata");
--              err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+              err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-               if (!fatal) fatal = err;
-       }
-       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-@@ -305,6 +305,8 @@ struct inode * ext3_new_inode (handle_t 
-       int i, j, avefreei;
-       struct inode * inode;
-       int bitmap_nr;
-+      struct ext3_inode_info *ei;
-+      struct ext3_sb_info *sbi;
-       struct ext3_group_desc * gdp;
-       struct ext3_group_desc * tmp;
-       struct ext3_super_block * es;
-@@ -318,7 +320,9 @@ struct inode * ext3_new_inode (handle_t 
-       inode = new_inode(sb);
-       if (!inode)
-               return ERR_PTR(-ENOMEM);
--      init_rwsem(&inode->u.ext3_i.truncate_sem);
-+      sbi = EXT3_SB(sb);
-+      ei = EXT3_I(inode);
-+      init_rwsem(&ei->truncate_sem);
-       lock_super (sb);
-       es = sb->u.ext3_sb.s_es;
-@@ -328,9 +332,9 @@ struct inode * ext3_new_inode (handle_t 
-       if (S_ISDIR(mode)) {
-               avefreei = le32_to_cpu(es->s_free_inodes_count) /
--                      sb->u.ext3_sb.s_groups_count;
-+                      sbi->s_groups_count;
-               if (!gdp) {
--                      for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) {
-+                      for (j = 0; j < sbi->s_groups_count; j++) {
-                               struct buffer_head *temp_buffer;
-                               tmp = ext3_get_group_desc (sb, j, &temp_buffer);
-                               if (tmp &&
-@@ -350,7 +354,7 @@ repeat:
-               /*
-                * Try to place the inode in its parent directory
-                */
--              i = dir->u.ext3_i.i_block_group;
-+              i = EXT3_I(dir)->i_block_group;
-               tmp = ext3_get_group_desc (sb, i, &bh2);
-               if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
-                       gdp = tmp;
-@@ -360,10 +364,10 @@ repeat:
-                        * Use a quadratic hash to find a group with a
-                        * free inode
-                        */
--                      for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) {
-+                      for (j = 1; j < sbi->s_groups_count; j <<= 1) {
-                               i += j;
--                              if (i >= sb->u.ext3_sb.s_groups_count)
--                                      i -= sb->u.ext3_sb.s_groups_count;
-+                              if (i >= sbi->s_groups_count)
-+                                      i -= sbi->s_groups_count;
-                               tmp = ext3_get_group_desc (sb, i, &bh2);
-                               if (tmp &&
-                                   le16_to_cpu(tmp->bg_free_inodes_count)) {
-@@ -376,9 +380,9 @@ repeat:
-                       /*
-                        * That failed: try linear search for a free inode
-                        */
--                      i = dir->u.ext3_i.i_block_group + 1;
--                      for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) {
--                              if (++i >= sb->u.ext3_sb.s_groups_count)
-+                      i = EXT3_I(dir)->i_block_group + 1;
-+                      for (j = 2; j < sbi->s_groups_count; j++) {
-+                              if (++i >= sbi->s_groups_count)
-                                       i = 0;
-                               tmp = ext3_get_group_desc (sb, i, &bh2);
-                               if (tmp &&
-@@ -399,11 +403,11 @@ repeat:
-       if (bitmap_nr < 0)
-               goto fail;
--      bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-+      bh = sbi->s_inode_bitmap[bitmap_nr];
-       if ((j = ext3_find_first_zero_bit ((unsigned long *) bh->b_data,
--                                    EXT3_INODES_PER_GROUP(sb))) <
--          EXT3_INODES_PER_GROUP(sb)) {
-+                                    sbi->s_inodes_per_group)) <
-+          sbi->s_inodes_per_group) {
-               BUFFER_TRACE(bh, "get_write_access");
-               err = ext3_journal_get_write_access(handle, bh);
-               if (err) goto fail;
-@@ -457,13 +461,13 @@ repeat:
-       err = ext3_journal_dirty_metadata(handle, bh2);
-       if (err) goto fail;
-       
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
--      err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(sbi->s_sbh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, sbi->s_sbh);
-       if (err) goto fail;
-       es->s_free_inodes_count =
-               cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "call ext3_journal_dirty_metadata");
--      err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(sbi->s_sbh, "call ext3_journal_dirty_metadata");
-+      err = ext3_journal_dirty_metadata(handle, sbi->s_sbh);
-       sb->s_dirt = 1;
-       if (err) goto fail;
-@@ -483,31 +487,31 @@ repeat:
-       inode->i_blksize = PAGE_SIZE;
-       inode->i_blocks = 0;
-       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
--      inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL;
-+      ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL;
-       if (S_ISLNK(mode))
--              inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
-+              ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
- #ifdef EXT3_FRAGMENTS
--      inode->u.ext3_i.i_faddr = 0;
--      inode->u.ext3_i.i_frag_no = 0;
--      inode->u.ext3_i.i_frag_size = 0;
-+      ei->i_faddr = 0;
-+      ei->i_frag_no = 0;
-+      ei->i_frag_size = 0;
- #endif
--      inode->u.ext3_i.i_file_acl = 0;
--      inode->u.ext3_i.i_dir_acl = 0;
--      inode->u.ext3_i.i_dtime = 0;
--      INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+      ei->i_file_acl = 0;
-+      ei->i_dir_acl = 0;
-+      ei->i_dtime = 0;
-+      INIT_LIST_HEAD(&ei->i_orphan);
- #ifdef EXT3_PREALLOCATE
--      inode->u.ext3_i.i_prealloc_count = 0;
-+      ei->i_prealloc_count = 0;
- #endif
--      inode->u.ext3_i.i_block_group = i;
-+      ei->i_block_group = i;
-       
--      if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL)
-+      if (ei->i_flags & EXT3_SYNC_FL)
-               inode->i_flags |= S_SYNC;
-       if (IS_SYNC(inode))
-               handle->h_sync = 1;
-       insert_inode_hash(inode);
--      inode->i_generation = sb->u.ext3_sb.s_next_generation++;
-+      inode->i_generation = sbi->s_next_generation++;
--      inode->u.ext3_i.i_state = EXT3_STATE_NEW;
-+      ei->i_state = EXT3_STATE_NEW;
-       err = ext3_mark_inode_dirty(handle, inode);
-       if (err) goto fail;
-       
-@@ -585,19 +589,19 @@ struct inode *ext3_orphan_get (struct su
- unsigned long ext3_count_free_inodes (struct super_block * sb)
- {
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      struct ext3_super_block *es = sbi->s_es;
- #ifdef EXT3FS_DEBUG
--      struct ext3_super_block * es;
-       unsigned long desc_count, bitmap_count, x;
-       int bitmap_nr;
-       struct ext3_group_desc * gdp;
-       int i;
-       lock_super (sb);
--      es = sb->u.ext3_sb.s_es;
-       desc_count = 0;
-       bitmap_count = 0;
-       gdp = NULL;
--      for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+      for (i = 0; i < sbi->s_groups_count; i++) {
-               gdp = ext3_get_group_desc (sb, i, NULL);
-               if (!gdp)
-                       continue;
-@@ -606,8 +610,8 @@ unsigned long ext3_count_free_inodes (st
-               if (bitmap_nr < 0)
-                       continue;
--              x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr],
--                                   EXT3_INODES_PER_GROUP(sb) / 8);
-+              x = ext3_count_free(sbi->s_inode_bitmap[bitmap_nr],
-+                                  sbi->s_inodes_per_group / 8);
-               printk ("group %d: stored = %d, counted = %lu\n",
-                       i, le16_to_cpu(gdp->bg_free_inodes_count), x);
-               bitmap_count += x;
-@@ -617,7 +621,7 @@ unsigned long ext3_count_free_inodes (st
-       unlock_super (sb);
-       return desc_count;
- #else
--      return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_inodes_count);
-+      return le32_to_cpu(es->s_free_inodes_count);
- #endif
- }
-@@ -626,16 +630,18 @@ unsigned long ext3_count_free_inodes (st
- void ext3_check_inodes_bitmap (struct super_block * sb)
- {
-       struct ext3_super_block * es;
-+      struct ext3_sb_info *sbi;
-       unsigned long desc_count, bitmap_count, x;
-       int bitmap_nr;
-       struct ext3_group_desc * gdp;
-       int i;
--      es = sb->u.ext3_sb.s_es;
-+      sbi = EXT3_SB(sb);
-+      es = sbi->s_es;
-       desc_count = 0;
-       bitmap_count = 0;
-       gdp = NULL;
--      for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+      for (i = 0; i < sbi->s_groups_count; i++) {
-               gdp = ext3_get_group_desc (sb, i, NULL);
-               if (!gdp)
-                       continue;
-@@ -644,7 +650,7 @@ void ext3_check_inodes_bitmap (struct su
-               if (bitmap_nr < 0)
-                       continue;
--              x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr],
-+              x = ext3_count_free (sbi->s_inode_bitmap[bitmap_nr],
-                                    EXT3_INODES_PER_GROUP(sb) / 8);
-               if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
-                       ext3_error (sb, "ext3_check_inodes_bitmap",
---- ./fs/ext3/inode.c.orig     Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/inode.c  Tue May  7 15:41:23 2002
-@@ -196,7 +196,7 @@ void ext3_delete_inode (struct inode * i
-        * (Well, we could do this if we need to, but heck - it works)
-        */
-       ext3_orphan_del(handle, inode);
--      inode->u.ext3_i.i_dtime = CURRENT_TIME;
-+      EXT3_I(inode)->i_dtime = CURRENT_TIME;
-       /* 
-        * One subtle ordering requirement: if anything has gone wrong
-@@ -220,13 +220,14 @@ no_delete:
- void ext3_discard_prealloc (struct inode * inode)
- {
- #ifdef EXT3_PREALLOCATE
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       lock_kernel();
-       /* Writer: ->i_prealloc* */
--      if (inode->u.ext3_i.i_prealloc_count) {
--              unsigned short total = inode->u.ext3_i.i_prealloc_count;
--              unsigned long block = inode->u.ext3_i.i_prealloc_block;
--              inode->u.ext3_i.i_prealloc_count = 0;
--              inode->u.ext3_i.i_prealloc_block = 0;
-+      if (ei->i_prealloc_count) {
-+              unsigned short total = ei->i_prealloc_count;
-+              unsigned long block = ei->i_prealloc_block;
-+              ei->i_prealloc_count = 0;
-+              ei->i_prealloc_block = 0;
-               /* Writer: end */
-               ext3_free_blocks (inode, block, total);
-       }
-@@ -243,13 +244,15 @@ static int ext3_alloc_block (handle_t *h
-       unsigned long result;
- #ifdef EXT3_PREALLOCATE
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+
-       /* Writer: ->i_prealloc* */
--      if (inode->u.ext3_i.i_prealloc_count &&
--          (goal == inode->u.ext3_i.i_prealloc_block ||
--           goal + 1 == inode->u.ext3_i.i_prealloc_block))
-+      if (ei->i_prealloc_count &&
-+          (goal == ei->i_prealloc_block ||
-+           goal + 1 == ei->i_prealloc_block))
-       {
--              result = inode->u.ext3_i.i_prealloc_block++;
--              inode->u.ext3_i.i_prealloc_count--;
-+              result = ei->i_prealloc_block++;
-+              ei->i_prealloc_count--;
-               /* Writer: end */
-               ext3_debug ("preallocation hit (%lu/%lu).\n",
-                           ++alloc_hits, ++alloc_attempts);
-@@ -259,8 +262,8 @@ static int ext3_alloc_block (handle_t *h
-                           alloc_hits, ++alloc_attempts);
-               if (S_ISREG(inode->i_mode))
-                       result = ext3_new_block (inode, goal, 
--                               &inode->u.ext3_i.i_prealloc_count,
--                               &inode->u.ext3_i.i_prealloc_block, err);
-+                               &ei->i_prealloc_count,
-+                               &ei->i_prealloc_block, err);
-               else
-                       result = ext3_new_block (inode, goal, 0, 0, err);
-               /*
-@@ -394,7 +397,7 @@ static Indirect *ext3_get_branch(struct 
-       *err = 0;
-       /* i_data is not going away, no lock needed */
--      add_chain (chain, NULL, inode->u.ext3_i.i_data + *offsets);
-+      add_chain (chain, NULL, EXT3_I(inode)->i_data + *offsets);
-       if (!p->key)
-               goto no_block;
-       while (--depth) {
-@@ -437,7 +440,8 @@ no_block:
- static inline unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
- {
--      u32 *start = ind->bh ? (u32*) ind->bh->b_data : inode->u.ext3_i.i_data;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      u32 *start = ind->bh ? (u32*) ind->bh->b_data : ei->i_data;
-       u32 *p;
-       /* Try to find previous block */
-@@ -453,9 +456,8 @@ static inline unsigned long ext3_find_ne
-        * It is going to be refered from inode itself? OK, just put it into
-        * the same cylinder group then.
-        */
--      return (inode->u.ext3_i.i_block_group * 
--              EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
--             le32_to_cpu(inode->i_sb->u.ext3_sb.s_es->s_first_data_block);
-+      return (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+             le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
- }
- /**
-@@ -474,14 +477,15 @@
- static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4],
-                         Indirect *partial, unsigned long *goal)
- {
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       /* Writer: ->i_next_alloc* */
--      if (block == inode->u.ext3_i.i_next_alloc_block + 1) {
--              inode->u.ext3_i.i_next_alloc_block++;
--              inode->u.ext3_i.i_next_alloc_goal++;
-+      if (block == ei->i_next_alloc_block + 1) {
-+              ei->i_next_alloc_block++;
-+              ei->i_next_alloc_goal++;
-       }
- #ifdef SEARCH_FROM_ZERO
--      inode->u.ext3_i.i_next_alloc_block = 0;
--      inode->u.ext3_i.i_next_alloc_goal = 0;
-+      ei->i_next_alloc_block = 0;
-+      ei->i_next_alloc_goal = 0;
- #endif
-       /* Writer: end */
-       /* Reader: pointers, ->i_next_alloc* */
-@@ -490,8 +493,8 @@ static int ext3_find_goal(struct inode *
-                * try the heuristic for sequential allocation,
-                * failing that at least try to get decent locality.
-                */
--              if (block == inode->u.ext3_i.i_next_alloc_block)
--                      *goal = inode->u.ext3_i.i_next_alloc_goal;
-+              if (block == ei->i_next_alloc_block)
-+                      *goal = ei->i_next_alloc_goal;
-               if (!*goal)
-                       *goal = ext3_find_near(inode, partial);
- #ifdef SEARCH_FROM_ZERO
-@@ -619,6 +621,7 @@
- {
-       int i;
-       int err = 0;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       /*
-        * If we're splicing into a [td]indirect block (as opposed to the
-@@ -641,11 +644,11 @@ static int ext3_splice_branch(handle_t *
-       /* That's it */
-       *where->p = where->key;
--      inode->u.ext3_i.i_next_alloc_block = block;
--      inode->u.ext3_i.i_next_alloc_goal = le32_to_cpu(where[num-1].key);
-+      ei->i_next_alloc_block = block;
-+      ei->i_next_alloc_goal = le32_to_cpu(where[num-1].key);
- #ifdef SEARCH_FROM_ZERO
--      inode->u.ext3_i.i_next_alloc_block = 0;
--      inode->u.ext3_i.i_next_alloc_goal = 0;
-+      ei->i_next_alloc_block = 0;
-+      ei->i_next_alloc_goal = 0;
- #endif
-       /* Writer: end */
-@@ -729,6 +732,7 @@
-       unsigned long goal;
-       int left;
-       int depth = ext3_block_to_path(inode, iblock, offsets);
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       loff_t new_size;
-       J_ASSERT(handle != NULL || create == 0);
-@@ -782,7 +785,7 @@ out:
-       /*
-        * Block out ext3_truncate while we alter the tree
-        */
--      down_read(&inode->u.ext3_i.truncate_sem);
-+      down_read(&ei->truncate_sem);
-       err = ext3_alloc_branch(handle, inode, left, goal,
-                                       offsets+(partial-chain), partial);
-@@ -794,7 +797,7 @@ out:
-       if (!err)
-               err = ext3_splice_branch(handle, inode, iblock, chain,
-                                        partial, left);
--      up_read(&inode->u.ext3_i.truncate_sem);
-+      up_read(&ei->truncate_sem);
-       if (err == -EAGAIN)
-               goto changed;
-       if (err)
-@@ -807,8 +810,8 @@ out:
-        * truncate is in progress.  It is racy between multiple parallel
-        * instances of get_block, but we have the BKL.
-        */
--      if (new_size > inode->u.ext3_i.i_disksize)
--              inode->u.ext3_i.i_disksize = new_size;
-+      if (new_size > ei->i_disksize)
-+              ei->i_disksize = new_size;
-       bh_result->b_state |= (1UL << BH_New);
-       goto got_it;
-@@ -921,7 +924,7 @@ struct buffer_head *ext3_bread(handle_t 
-               struct buffer_head *tmp_bh;
-               for (i = 1;
--                   inode->u.ext3_i.i_prealloc_count &&
-+                   EXT3_I(inode)->i_prealloc_count &&
-                    i < EXT3_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
-                    i++) {
-                       /*
-@@ -1131,8 +1134,8 @@ static int ext3_commit_write(struct file
-                       kunmap(page);
-               }
-       }
--      if (inode->i_size > inode->u.ext3_i.i_disksize) {
--              inode->u.ext3_i.i_disksize = inode->i_size;
-+      if (inode->i_size > EXT3_I(inode)->i_disksize) {
-+              EXT3_I(inode)->i_disksize = inode->i_size;
-               ret2 = ext3_mark_inode_dirty(handle, inode);
-               if (!ret) 
-                       ret = ret2;
-@@ -1832,7 +1835,8 @@ static void ext3_free_branches(handle_t 
- void ext3_truncate(struct inode * inode)
- {
-       handle_t *handle;
--      u32 *i_data = inode->u.ext3_i.i_data;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      u32 *i_data = EXT3_I(inode)->i_data;
-       int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
-       int offsets[4];
-       Indirect chain[4];
-@@ -1884,13 +1887,13 @@ void ext3_truncate(struct inode * inode)
-        * on-disk inode. We do this via i_disksize, which is the value which
-        * ext3 *really* writes onto the disk inode.
-        */
--      inode->u.ext3_i.i_disksize = inode->i_size;
-+      ei->i_disksize = inode->i_size;
-       /*
-        * From here we block out all ext3_get_block() callers who want to
-        * modify the block allocation tree.
-        */
--      down_write(&inode->u.ext3_i.truncate_sem);
-+      down_write(&ei->truncate_sem);
-       if (n == 1) {           /* direct blocks */
-               ext3_free_data(handle, inode, NULL, i_data+offsets[0],
-@@ -1954,7 +1957,7 @@ do_indirects:
-               case EXT3_TIND_BLOCK:
-                       ;
-       }
--      up_write(&inode->u.ext3_i.truncate_sem);
-+      up_write(&ei->truncate_sem);
-       inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       ext3_mark_inode_dirty(handle, inode);
-@@ -1983,6 +1986,8 @@ out_stop:
- int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
- {
-+      struct super_block *sb = inode->i_sb;
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-       struct buffer_head *bh = 0;
-       unsigned long block;
-       unsigned long block_group;
-@@ -1997,23 +2010,19 @@ int ext3_get_inode_loc (struct inode *in
-               inode->i_ino != EXT3_JOURNAL_INO &&
--              inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
--              inode->i_ino > le32_to_cpu(
--                      inode->i_sb->u.ext3_sb.s_es->s_inodes_count)) {
--              ext3_error (inode->i_sb, "ext3_get_inode_loc",
--                          "bad inode number: %lu", inode->i_ino);
-+              inode->i_ino < EXT3_FIRST_INO(sb)) ||
-+              inode->i_ino > le32_to_cpu(sbi->s_es->s_inodes_count)) {
-+              ext3_error (sb, __FUNCTION__, "bad inode #%lu", inode->i_ino);
-               goto bad_inode;
-       }
--      block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
--      if (block_group >= inode->i_sb->u.ext3_sb.s_groups_count) {
--              ext3_error (inode->i_sb, "ext3_get_inode_loc",
--                          "group >= groups count");
-+      block_group = (inode->i_ino - 1) / sbi->s_inodes_per_group;
-+      if (block_group >= sbi->s_groups_count) {
-+              ext3_error(sb, __FUNCTION__, "group >= groups count");
-               goto bad_inode;
-       }
--      group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
--      desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
--      bh = inode->i_sb->u.ext3_sb.s_group_desc[group_desc];
-+      group_desc = block_group >> sbi->s_desc_per_block_bits;
-+      desc = block_group & (sbi->s_desc_per_block - 1);
-+      bh = sbi->s_group_desc[group_desc];
-       if (!bh) {
--              ext3_error (inode->i_sb, "ext3_get_inode_loc",
--                          "Descriptor not loaded");
-+              ext3_error(sb, __FUNCTION__, "Descriptor not loaded");
-               goto bad_inode;
-       }
-@@ -2021,17 +2022,17 @@ int ext3_get_inode_loc (struct inode *in
-       /*
-        * Figure out the offset within the block group inode table
-        */
--      offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
--              EXT3_INODE_SIZE(inode->i_sb);
-+      offset = ((inode->i_ino - 1) % sbi->s_inodes_per_group) *
-+              sbi->s_inode_size;
-       block = le32_to_cpu(gdp[desc].bg_inode_table) +
--              (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
--      if (!(bh = sb_bread(inode->i_sb, block))) {
--              ext3_error (inode->i_sb, "ext3_get_inode_loc",
-+              (offset >> EXT3_BLOCK_SIZE_BITS(sb));
-+      if (!(bh = sb_bread(sb, block))) {
-+              ext3_error (sb, __FUNCTION__,
-                           "unable to read inode block - "
-                           "inode=%lu, block=%lu", inode->i_ino, block);
-               goto bad_inode;
-       }
--      offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+      offset &= (EXT3_BLOCK_SIZE(sb) - 1);
-       iloc->bh = bh;
-       iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-@@ -2047,6 +2048,7 @@ void ext3_read_inode(struct inode * inod
- {
-       struct ext3_iloc iloc;
-       struct ext3_inode *raw_inode;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       struct buffer_head *bh;
-       int block;
-       
-@@ -2054,7 +2056,7 @@ void ext3_read_inode(struct inode * inod
-               goto bad_inode;
-       bh = iloc.bh;
-       raw_inode = iloc.raw_inode;
--      init_rwsem(&inode->u.ext3_i.truncate_sem);
-+      init_rwsem(&ei->truncate_sem);
-       inode->i_mode = le16_to_cpu(raw_inode->i_mode);
-       inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
-       inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
-@@ -2067,7 +2069,7 @@ void ext3_read_inode(struct inode * inod
-       inode->i_atime = le32_to_cpu(raw_inode->i_atime);
-       inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
-       inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
--      inode->u.ext3_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
-+      ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
-       /* We now have enough fields to check if the inode was active or not.
-        * This is needed because nfsd might try to access dead inodes
-        * the test is that same one that e2fsck uses
-@@ -2075,7 +2077,7 @@ void ext3_read_inode(struct inode * inod
-        */
-       if (inode->i_nlink == 0) {
-               if (inode->i_mode == 0 ||
--                  !(inode->i_sb->u.ext3_sb.s_mount_state & EXT3_ORPHAN_FS)) {
-+                  !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ORPHAN_FS)) {
-                       /* this inode is deleted */
-                       brelse (bh);
-                       goto bad_inode;
-@@ -2090,33 +2092,33 @@ void ext3_read_inode(struct inode * inod
-                                        * size */  
-       inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
-       inode->i_version = ++event;
--      inode->u.ext3_i.i_flags = le32_to_cpu(raw_inode->i_flags);
-+      ei->i_flags = le32_to_cpu(raw_inode->i_flags);
- #ifdef EXT3_FRAGMENTS
--      inode->u.ext3_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
--      inode->u.ext3_i.i_frag_no = raw_inode->i_frag;
--      inode->u.ext3_i.i_frag_size = raw_inode->i_fsize;
-+      ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
-+      ei->i_frag_no = raw_inode->i_frag;
-+      ei->i_frag_size = raw_inode->i_fsize;
- #endif
--      inode->u.ext3_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-+      ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-       if (!S_ISREG(inode->i_mode)) {
--              inode->u.ext3_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
-+              ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
-       } else {
-               inode->i_size |=
-                       ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
-       }
--      inode->u.ext3_i.i_disksize = inode->i_size;
-+      ei->i_disksize = inode->i_size;
-       inode->i_generation = le32_to_cpu(raw_inode->i_generation);
- #ifdef EXT3_PREALLOCATE
--      inode->u.ext3_i.i_prealloc_count = 0;
-+      ei->i_prealloc_count = 0;
- #endif
--      inode->u.ext3_i.i_block_group = iloc.block_group;
-+      ei->i_block_group = iloc.block_group;
-       /*
-        * NOTE! The in-memory inode i_data array is in little-endian order
-        * even on big-endian machines: we do NOT byteswap the block numbers!
-        */
-       for (block = 0; block < EXT3_N_BLOCKS; block++)
--              inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
--      INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+              ei->i_data[block] = iloc.raw_inode->i_block[block];
-+      INIT_LIST_HEAD(&ei->i_orphan);
-       brelse (iloc.bh);
-@@ -2143,17 +2145,17 @@ void ext3_read_inode(struct inode * inod
-       /* inode->i_attr_flags = 0;                             unused */
--      if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
-+      if (ei->i_flags & EXT3_SYNC_FL) {
-               /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
-               inode->i_flags |= S_SYNC;
-       }
--      if (inode->u.ext3_i.i_flags & EXT3_APPEND_FL) {
-+      if (ei->i_flags & EXT3_APPEND_FL) {
-               /* inode->i_attr_flags |= ATTR_FLAG_APPEND;     unused */
-               inode->i_flags |= S_APPEND;
-       }
--      if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FL) {
-+      if (ei->i_flags & EXT3_IMMUTABLE_FL) {
-               /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;  unused */
-               inode->i_flags |= S_IMMUTABLE;
-       }
--      if (inode->u.ext3_i.i_flags & EXT3_NOATIME_FL) {
-+      if (ei->i_flags & EXT3_NOATIME_FL) {
-               /* inode->i_attr_flags |= ATTR_FLAG_NOATIME;    unused */
-               inode->i_flags |= S_NOATIME;
-       }
-@@ -2175,6 +2177,7 @@ static int ext3_do_update_inode(handle_t
-                               struct ext3_iloc *iloc)
- {
-       struct ext3_inode *raw_inode = iloc->raw_inode;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       struct buffer_head *bh = iloc->bh;
-       int err = 0, rc, block;
-@@ -2192,7 +2195,7 @@ static int ext3_do_update_inode(handle_t
-  * Fix up interoperability with old kernels. Otherwise, old inodes get
-  * re-used with the upper 16 bits of the uid/gid intact
-  */
--              if(!inode->u.ext3_i.i_dtime) {
-+              if(!ei->i_dtime) {
-                       raw_inode->i_uid_high =
-                               cpu_to_le16(high_16_bits(inode->i_uid));
-                       raw_inode->i_gid_high =
-@@ -2210,34 +2213,33 @@ static int ext3_do_update_inode(handle_t
-               raw_inode->i_gid_high = 0;
-       }
-       raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
--      raw_inode->i_size = cpu_to_le32(inode->u.ext3_i.i_disksize);
-+      raw_inode->i_size = cpu_to_le32(ei->i_disksize);
-       raw_inode->i_atime = cpu_to_le32(inode->i_atime);
-       raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);
-       raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);
-       raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
--      raw_inode->i_dtime = cpu_to_le32(inode->u.ext3_i.i_dtime);
--      raw_inode->i_flags = cpu_to_le32(inode->u.ext3_i.i_flags);
-+      raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
-+      raw_inode->i_flags = cpu_to_le32(ei->i_flags);
- #ifdef EXT3_FRAGMENTS
--      raw_inode->i_faddr = cpu_to_le32(inode->u.ext3_i.i_faddr);
--      raw_inode->i_frag = inode->u.ext3_i.i_frag_no;
--      raw_inode->i_fsize = inode->u.ext3_i.i_frag_size;
-+      raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
-+      raw_inode->i_frag = ei->i_frag_no;
-+      raw_inode->i_fsize = ei->i_frag_size;
- #else
-       /* If we are not tracking these fields in the in-memory inode,
-        * then preserve them on disk, but still initialise them to zero
-        * for new inodes. */
--      if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
-+      if (ei->i_state & EXT3_STATE_NEW) {
-               raw_inode->i_faddr = 0;
-               raw_inode->i_frag = 0;
-               raw_inode->i_fsize = 0;
-       }
- #endif
--      raw_inode->i_file_acl = cpu_to_le32(inode->u.ext3_i.i_file_acl);
-+      raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
-       if (!S_ISREG(inode->i_mode)) {
--              raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext3_i.i_dir_acl);
-+              raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
-       } else {
--              raw_inode->i_size_high =
--                      cpu_to_le32(inode->u.ext3_i.i_disksize >> 32);
--              if (inode->u.ext3_i.i_disksize > 0x7fffffffULL) {
-+              raw_inode->i_size_high = cpu_to_le32(ei->i_disksize >> 32);
-+              if (ei->i_disksize > MAX_NON_LFS) {
-                       struct super_block *sb = inode->i_sb;
-                       if (!EXT3_HAS_RO_COMPAT_FEATURE(sb,
-                                       EXT3_FEATURE_RO_COMPAT_LARGE_FILE) ||
-@@ -2247,7 +2249,7 @@ static int ext3_do_update_inode(handle_t
-                               * created, add a flag to the superblock.
-                               */
-                               err = ext3_journal_get_write_access(handle,
--                                              sb->u.ext3_sb.s_sbh);
-+                                              EXT3_SB(sb)->s_sbh);
-                               if (err)
-                                       goto out_brelse;
-                               ext3_update_dynamic_rev(sb);
-@@ -2256,7 +2258,7 @@ static int ext3_do_update_inode(handle_t
-                               sb->s_dirt = 1;
-                               handle->h_sync = 1;
-                               err = ext3_journal_dirty_metadata(handle,
--                                              sb->u.ext3_sb.s_sbh);
-+                                              EXT3_SB(sb)->s_sbh);
-                       }
-               }
-       }
-@@ -2265,13 +2267,13 @@ static int ext3_do_update_inode(handle_t
-               raw_inode->i_block[0] =
-                       cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
-       else for (block = 0; block < EXT3_N_BLOCKS; block++)
--              raw_inode->i_block[block] = inode->u.ext3_i.i_data[block];
-+              raw_inode->i_block[block] = ei->i_data[block];
-       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-       rc = ext3_journal_dirty_metadata(handle, bh);
-       if (!err)
-               err = rc;
--      EXT3_I(inode)->i_state &= ~EXT3_STATE_NEW;
-+      ei->i_state &= ~EXT3_STATE_NEW;
- out_brelse:
-       brelse (bh);
-@@ -2379,7 +2381,7 @@ int ext3_setattr(struct dentry *dentry, 
-               }
-               
-               error = ext3_orphan_add(handle, inode);
--              inode->u.ext3_i.i_disksize = attr->ia_size;
-+              EXT3_I(inode)->i_disksize = attr->ia_size;
-               rc = ext3_mark_inode_dirty(handle, inode);
-               if (!error)
-                       error = rc;
-@@ -2622,9 +2624,9 @@ int ext3_change_inode_journal_flag(struc
-        */
-       if (val)
--              inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;
-+              EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL;
-       else
--              inode->u.ext3_i.i_flags &= ~EXT3_JOURNAL_DATA_FL;
-+              EXT3_I(inode)->i_flags &= ~EXT3_JOURNAL_DATA_FL;
-       journal_unlock_updates(journal);
---- ./fs/ext3/ioctl.c.orig     Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/ioctl.c  Tue May  7 15:20:52 2002
-@@ -18,13 +18,14 @@
- int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
-               unsigned long arg)
- {
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       unsigned int flags;
-       ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
-       switch (cmd) {
-       case EXT3_IOC_GETFLAGS:
--              flags = inode->u.ext3_i.i_flags & EXT3_FL_USER_VISIBLE;
-+              flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
-               return put_user(flags, (int *) arg);
-       case EXT3_IOC_SETFLAGS: {
-               handle_t *handle = NULL;
-@@ -42,7 +42,7 @@ int ext3_ioctl (struct inode * inode, st
-               if (get_user(flags, (int *) arg))
-                       return -EFAULT;
--              oldflags = inode->u.ext3_i.i_flags;
-+              oldflags = ei->i_flags;
-               /* The JOURNAL_DATA flag is modifiable only by root */
-               jflag = flags & EXT3_JOURNAL_DATA_FL;
-@@ -79,7 +79,7 @@ int ext3_ioctl (struct inode * inode, st
-               
-               flags = flags & EXT3_FL_USER_MODIFIABLE;
-               flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
--              inode->u.ext3_i.i_flags = flags;
-+              ei->i_flags = flags;
-               if (flags & EXT3_SYNC_FL)
-                       inode->i_flags |= S_SYNC;
-@@ -155,12 +155,12 @@ flags_err:
-                       int ret = 0;
-                       set_current_state(TASK_INTERRUPTIBLE);
--                      add_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait);
--                      if (timer_pending(&sb->u.ext3_sb.turn_ro_timer)) {
-+                      add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
-+                      if (timer_pending(&EXT3_SB(sb)->turn_ro_timer)) {
-                               schedule();
-                               ret = 1;
-                       }
--                      remove_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait);
-+                      remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
-                       return ret;
-               }
- #endif
---- ./fs/ext3/namei.c.orig     Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/namei.c  Tue May  7 16:05:51 2002
-@@ -636,7 +636,7 @@ static struct buffer_head * ext3_find_en
-       }
-       
-       nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
--      start = dir->u.ext3_i.i_dir_start_lookup;
-+      start = EXT3_I(dir)->i_dir_start_lookup;
-       if (start >= nblocks)
-               start = 0;
-       block = start;
-@@ -677,7 +677,7 @@ restart:
-               i = search_dirblock(bh, dir, dentry,
-                           block << EXT3_BLOCK_SIZE_BITS(sb), res_dir);
-               if (i == 1) {
--                      dir->u.ext3_i.i_dir_start_lookup = block;
-+                      EXT3_I(dir)->i_dir_start_lookup = block;
-                       ret = bh;
-                       goto cleanup_and_exit;
-               } else {
-@@ -1419,7 +1419,7 @@ int ext3_orphan_add(handle_t *handle, st
-       int err = 0, rc;
-       
-       lock_super(sb);
--      if (!list_empty(&inode->u.ext3_i.i_orphan))
-+      if (!list_empty(&EXT3_I(inode)->i_orphan))
-               goto out_unlock;
-       /* Orphan handling is only valid for files with data blocks
-@@ -1430,8 +1430,8 @@ int ext3_orphan_add(handle_t *handle, st
-       J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-               S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
--      err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-       if (err)
-               goto out_unlock;
-       
-@@ -1442,7 +1442,7 @@ int ext3_orphan_add(handle_t *handle, st
-       /* Insert this inode at the head of the on-disk orphan list... */
-       NEXT_ORPHAN(inode) = le32_to_cpu(EXT3_SB(sb)->s_es->s_last_orphan);
-       EXT3_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
--      err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+      err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-       rc = ext3_mark_iloc_dirty(handle, inode, &iloc);
-       if (!err)
-               err = rc;
-@@ -1456,7 +1456,7 @@ int ext3_orphan_add(handle_t *handle, st
-        * This is safe: on error we're going to ignore the orphan list
-        * anyway on the next recovery. */
-       if (!err)
--              list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan);
-+              list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
-       jbd_debug(4, "superblock will point to %ld\n", inode->i_ino);
-       jbd_debug(4, "orphan inode %ld will point to %d\n",
-@@ -714,25 +770,25 @@
- int ext3_orphan_del(handle_t *handle, struct inode *inode)
- {
-       struct list_head *prev;
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-       struct ext3_sb_info *sbi;
-       unsigned long ino_next;
-       struct ext3_iloc iloc;
-       int err = 0;
-       lock_super(inode->i_sb);
--      if (list_empty(&inode->u.ext3_i.i_orphan)) {
-+      if (list_empty(&ei->i_orphan)) {
-               unlock_super(inode->i_sb);
-               return 0;
-       }
-       ino_next = NEXT_ORPHAN(inode);
--      prev = inode->u.ext3_i.i_orphan.prev;
-+      prev = ei->i_orphan.prev;
-       sbi = EXT3_SB(inode->i_sb);
-       jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
--      list_del(&inode->u.ext3_i.i_orphan);
--      INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+      list_del_init(&ei->i_orphan);
-       /* If we're on an error path, we may not have a valid
-        * transaction handle with which to update the orphan list on
-@@ -1520,8 +1520,7 @@ int ext3_orphan_del(handle_t *handle, st
-               err = ext3_journal_dirty_metadata(handle, sbi->s_sbh);
-       } else {
-               struct ext3_iloc iloc2;
--              struct inode *i_prev =
--                      list_entry(prev, struct inode, u.ext3_i.i_orphan);
-+              struct inode *i_prev = orphan_list_entry(prev);
-               jbd_debug(4, "orphan inode %lu will point to %lu\n",
-                         i_prev->i_ino, ino_next);
-@@ -1695,10 +1695,10 @@ static int ext3_symlink (struct inode * 
-                       goto out_no_entry;
-       } else {
-               inode->i_op = &ext3_fast_symlink_inode_operations;
--              memcpy((char*)&inode->u.ext3_i.i_data,symname,l);
-+              memcpy((char*)&EXT3_I(inode)->i_data,symname,l);
-               inode->i_size = l-1;
-       }
--      inode->u.ext3_i.i_disksize = inode->i_size;
-+      EXT3_I(inode)->i_disksize = inode->i_size;
-       err = ext3_add_nondir(handle, dentry, inode);
-       ext3_mark_inode_dirty(handle, inode);
- out_stop:
---- ./fs/ext3/super.c.orig     Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/super.c  Tue May  7 16:05:44 2002
-@@ -121,7 +121,7 @@ static int ext3_error_behaviour(struct s
-       /* If no overrides were specified on the mount, then fall back
-        * to the default behaviour set in the filesystem's superblock
-        * on disk. */
--      switch (le16_to_cpu(sb->u.ext3_sb.s_es->s_errors)) {
-+      switch (le16_to_cpu(EXT3_SB(sb)->s_es->s_errors)) {
-       case EXT3_ERRORS_PANIC:
-               return EXT3_ERRORS_PANIC;
-       case EXT3_ERRORS_RO:
-@@ -269,9 +269,9 @@ void ext3_abort (struct super_block * sb
-               return;
-       
-       printk (KERN_CRIT "Remounting filesystem read-only\n");
--      sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS;
-+      EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
-       sb->s_flags |= MS_RDONLY;
--      sb->u.ext3_sb.s_mount_opt |= EXT3_MOUNT_ABORT;
-+      EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
-       journal_abort(EXT3_SB(sb)->s_journal, -EIO);
- }
-@@ -377,8 +377,6 @@ static int ext3_blkdev_remove(struct ext3
-       return ret;
- }
--#define orphan_list_entry(l) list_entry((l), struct inode, u.ext3_i.i_orphan)
--
- static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
- {
-       struct list_head *l;
-@@ -818,7 +818,7 @@ static void ext3_orphan_cleanup (struct 
-               sb->s_flags &= ~MS_RDONLY;
-       }
--      if (sb->u.ext3_sb.s_mount_state & EXT3_ERROR_FS) {
-+      if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
-               if (es->s_last_orphan)
-                       jbd_debug(1, "Errors on filesystem, "
-                                 "clearing orphan list.\n");
-@@ -1463,12 +1463,14 @@ static void ext3_commit_super (struct su
-                              struct ext3_super_block * es,
-                              int sync)
- {
-+      struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;
-+
-       es->s_wtime = cpu_to_le32(CURRENT_TIME);
--      BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "marking dirty");
--      mark_buffer_dirty(sb->u.ext3_sb.s_sbh);
-+      BUFFER_TRACE(sbh, "marking dirty");
-+      mark_buffer_dirty(sbh);
-       if (sync) {
--              ll_rw_block(WRITE, 1, &sb->u.ext3_sb.s_sbh);
--              wait_on_buffer(sb->u.ext3_sb.s_sbh);
-+              ll_rw_block(WRITE, 1, &sbh);
-+              wait_on_buffer(sbh);
-       }
- }
-@@ -1519,7 +1521,7 @@ static void ext3_clear_journal_err(struc
-               ext3_warning(sb, __FUNCTION__, "Marking fs in need of "
-                            "filesystem check.");
-               
--              sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS;
-+              EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
-               es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
-               ext3_commit_super (sb, es, 1);
---- ./fs/ext3/symlink.c.orig   Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/symlink.c        Tue May  7 15:25:39 2002
-@@ -23,13 +23,13 @@
- static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
--      char *s = (char *)dentry->d_inode->u.ext3_i.i_data;
--      return vfs_readlink(dentry, buffer, buflen, s);
-+      struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
-+      return vfs_readlink(dentry, buffer, buflen, (char *)ei->i_data);
- }
- static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
- {
--      char *s = (char *)dentry->d_inode->u.ext3_i.i_data;
--      return vfs_follow_link(nd, s);
-+      struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
-+      return vfs_follow_link(nd, (char*)ei->i_data);
- }
---- ./include/linux/ext3_fs.h.orig     Tue Apr 16 14:27:25 2002
-+++ ./include/linux/ext3_fs.h  Tue May  7 16:47:36 2002
-@@ -84,22 +84,25 @@
- #define EXT3_MIN_BLOCK_SIZE           1024
- #define       EXT3_MAX_BLOCK_SIZE             4096
- #define EXT3_MIN_BLOCK_LOG_SIZE                 10
-+
- #ifdef __KERNEL__
--# define EXT3_BLOCK_SIZE(s)           ((s)->s_blocksize)
--#else
--# define EXT3_BLOCK_SIZE(s)           (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
--#endif
--#define       EXT3_ADDR_PER_BLOCK(s)          (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
--#ifdef __KERNEL__
--# define EXT3_BLOCK_SIZE_BITS(s)      ((s)->s_blocksize_bits)
--#else
--# define EXT3_BLOCK_SIZE_BITS(s)      ((s)->s_log_block_size + 10)
--#endif
--#ifdef __KERNEL__
--#define       EXT3_ADDR_PER_BLOCK_BITS(s)     ((s)->u.ext3_sb.s_addr_per_block_bits)
--#define EXT3_INODE_SIZE(s)            ((s)->u.ext3_sb.s_inode_size)
--#define EXT3_FIRST_INO(s)             ((s)->u.ext3_sb.s_first_ino)
-+#define EXT3_SB(sb)   (&((sb)->u.ext3_sb))
-+#define EXT3_I(inode) (&((inode)->u.ext3_i))
-+
-+#define EXT3_BLOCK_SIZE(s)            ((s)->s_blocksize)
-+#define EXT3_BLOCK_SIZE_BITS(s)               ((s)->s_blocksize_bits)
-+#define       EXT3_ADDR_PER_BLOCK_BITS(s)     (EXT3_SB(s)->s_addr_per_block_bits)
-+#define EXT3_INODE_SIZE(s)            (EXT3_SB(s)->s_inode_size)
-+#define EXT3_FIRST_INO(s)             (EXT3_SB(s)->s_first_ino)
- #else
-+
-+/* Assume that user mode programs are passing in an ext3fs superblock, not
-+ * a kernel struct super_block.  This will allow us to call the feature-test
-+ * macros from user land. */
-+#define EXT3_SB(sb)   (sb)
-+
-+#define EXT3_BLOCK_SIZE(s)    (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
-+#define EXT3_BLOCK_SIZE_BITS(s)       ((s)->s_log_block_size + 10)
- #define EXT3_INODE_SIZE(s)    (((s)->s_rev_level == EXT3_GOOD_OLD_REV) ? \
-                                EXT3_GOOD_OLD_INODE_SIZE : \
-                                (s)->s_inode_size)
-@@ -108,6 +110,7 @@
-                                EXT3_GOOD_OLD_FIRST_INO : \
-                                (s)->s_first_ino)
- #endif
-+#define EXT3_ADDR_PER_BLOCK(s)        (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
- /*
-  * Macro-instructions used to manage fragments
-@@ -116,8 +120,8 @@
- #define       EXT3_MAX_FRAG_SIZE              4096
- #define EXT3_MIN_FRAG_LOG_SIZE                  10
- #ifdef __KERNEL__
--# define EXT3_FRAG_SIZE(s)            ((s)->u.ext3_sb.s_frag_size)
--# define EXT3_FRAGS_PER_BLOCK(s)      ((s)->u.ext3_sb.s_frags_per_block)
-+# define EXT3_FRAG_SIZE(s)            (EXT3_SB(s)->s_frag_size)
-+# define EXT3_FRAGS_PER_BLOCK(s)      (EXT3_SB(s)->s_frags_per_block)
- #else
- # define EXT3_FRAG_SIZE(s)            (EXT3_MIN_FRAG_SIZE << (s)->s_log_frag_size)
- # define EXT3_FRAGS_PER_BLOCK(s)      (EXT3_BLOCK_SIZE(s) / EXT3_FRAG_SIZE(s))
-@@ -163,15 +167,13 @@
- /*
-  * Macro-instructions used to manage group descriptors
-  */
-+# define EXT3_BLOCKS_PER_GROUP(s)     (EXT3_SB(s)->s_blocks_per_group)
-+# define EXT3_INODES_PER_GROUP(s)     (EXT3_SB(s)->s_inodes_per_group)
- #ifdef __KERNEL__
--# define EXT3_BLOCKS_PER_GROUP(s)     ((s)->u.ext3_sb.s_blocks_per_group)
--# define EXT3_DESC_PER_BLOCK(s)               ((s)->u.ext3_sb.s_desc_per_block)
--# define EXT3_INODES_PER_GROUP(s)     ((s)->u.ext3_sb.s_inodes_per_group)
--# define EXT3_DESC_PER_BLOCK_BITS(s)  ((s)->u.ext3_sb.s_desc_per_block_bits)
-+# define EXT3_DESC_PER_BLOCK(s)               (EXT3_SB(s)->s_desc_per_block)
-+# define EXT3_DESC_PER_BLOCK_BITS(s)  (EXT3_SB(s)->s_desc_per_block_bits)
- #else
--# define EXT3_BLOCKS_PER_GROUP(s)     ((s)->s_blocks_per_group)
- # define EXT3_DESC_PER_BLOCK(s)               (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_group_desc))
--# define EXT3_INODES_PER_GROUP(s)     ((s)->s_inodes_per_group)
- #endif
- /*
-@@ -344,7 +347,7 @@
- #ifndef _LINUX_EXT2_FS_H
- #define clear_opt(o, opt)             o &= ~EXT3_MOUNT_##opt
- #define set_opt(o, opt)                       o |= EXT3_MOUNT_##opt
--#define test_opt(sb, opt)             ((sb)->u.ext3_sb.s_mount_opt & \
-+#define test_opt(sb, opt)             (EXT3_SB(sb)->s_mount_opt & \
-                                        EXT3_MOUNT_##opt)
- #else
- #define EXT2_MOUNT_NOLOAD             EXT3_MOUNT_NOLOAD
-@@ -441,17 +443,11 @@
- /*EC*/        __u32   s_reserved[197];        /* Padding to the end of the block */
- };
--#ifdef __KERNEL__
--#define EXT3_SB(sb)   (&((sb)->u.ext3_sb))
--#define EXT3_I(inode) (&((inode)->u.ext3_i))
--#else
--/* Assume that user mode programs are passing in an ext3fs superblock, not
-- * a kernel struct super_block.  This will allow us to call the feature-test
-- * macros from user land. */
--#define EXT3_SB(sb)   (sb)
--#endif
--
--#define NEXT_ORPHAN(inode) (inode)->u.ext3_i.i_dtime
-+#define NEXT_ORPHAN(inode) EXT3_I(inode)->i_dtime
-+static inline struct inode *orphan_list_entry(struct list_head *l)
-+{
-+      return list_entry(l, struct inode, u.ext3_i.i_orphan);
-+}
- /*
-  * Codes for operating systems
---- ./include/linux/ext3_jbd.h.orig    Tue May  7 14:44:08 2002
-+++ ./include/linux/ext3_jbd.h Tue May  7 14:44:43 2002
-@@ -291,7 +291,7 @@
-               return 1;
-       if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
-               return 1;
--      if (inode->u.ext3_i.i_flags & EXT3_JOURNAL_DATA_FL)
-+      if (EXT3_I(inode)->i_flags & EXT3_JOURNAL_DATA_FL)
-               return 1;
-       return 0;
- }
diff --git a/lustre/kernel_patches/patches/ext3-compat-2.4.18-chaos.patch b/lustre/kernel_patches/patches/ext3-compat-2.4.18-chaos.patch
deleted file mode 100644 (file)
index 68a2244..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
- fs/ext3/namei.c |    3 ++-
- lib/rbtree.c    |    6 +++---
- 2 files changed, 5 insertions(+), 4 deletions(-)
-
---- linux-2.4.18-chaos-pdirops/fs/ext3/namei.c~ext3-compat-2.4.18-chaos        2003-09-23 13:13:10.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/fs/ext3/namei.c  2003-09-23 13:13:28.000000000 +0400
-@@ -28,6 +28,7 @@
- #include <linux/string.h>
- #include <linux/locks.h>
- #include <linux/quotaops.h>
-+#include <linux/slab.h>
- /*
-@@ -830,9 +831,9 @@ static int ext3_rmdir (struct inode * di
-        * recovery. */
-       inode->i_size = 0;
-       ext3_orphan_add(handle, inode);
--      ext3_mark_inode_dirty(handle, inode);
-       dir->i_nlink--;
-       inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-+      ext3_mark_inode_dirty(handle, inode);
-       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-       ext3_mark_inode_dirty(handle, dir);
---- linux-2.4.18-chaos-pdirops/lib/rbtree.c~ext3-compat-2.4.18-chaos   2003-07-28 17:52:20.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/lib/rbtree.c     2003-09-23 13:13:15.000000000 +0400
-@@ -219,6 +219,8 @@ static void __rb_erase_color(rb_node_t *
-               node->rb_color = RB_BLACK;
- }
-+EXPORT_SYMBOL_GPL(rb_insert_color);
-+
- void rb_erase(rb_node_t * node, rb_root_t * root)
- {
-       rb_node_t * child, * parent;
-@@ -292,6 +294,4 @@ void rb_erase(rb_node_t * node, rb_root_
-       if (color == RB_BLACK)
-               __rb_erase_color(child, parent, root);
- }
--
--EXPORT_SYMBOL_GPL(rb_insert_color);
--EXPORT_SYMBOL_GPL(rb_erase);
-+EXPORT_SYMBOL(rb_erase);
-
-_
diff --git a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.18-2.patch b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.18-2.patch
deleted file mode 100644 (file)
index 1e2295c..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
- fs/ext3/file.c             |    4 
- fs/ext3/inode.c            |  112 +++++++++++++++++++++
- fs/ext3/super.c            |  231 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/ext3_fs.h    |    5 
- include/linux/ext3_fs_sb.h |   10 +
- 5 files changed, 362 insertions(+)
-
---- linux-2.4.18-chaos/fs/ext3/file.c~ext3-delete_thread-2.4.18-2      2003-09-16 23:34:07.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/file.c   2003-09-16 23:42:34.000000000 +0400
-@@ -124,7 +124,11 @@ struct file_operations ext3_file_operati
- };
- struct inode_operations ext3_file_inode_operations = {
-+#ifdef EXT3_DELETE_THREAD
-+      truncate:       ext3_truncate_thread,   /* BKL held */
-+#else
-       truncate:       ext3_truncate,          /* BKL held */
-+#endif
-       setattr:        ext3_setattr,           /* BKL held */
- };
---- linux-2.4.18-chaos/fs/ext3/inode.c~ext3-delete_thread-2.4.18-2     2003-09-16 23:39:37.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/inode.c  2003-09-16 23:42:34.000000000 +0400
-@@ -2041,6 +2041,118 @@ out_unlock:
-       return;         /* AKPM: return what? */
- }
-+#ifdef EXT3_DELETE_THREAD
-+/* Move blocks from to-be-truncated inode over to a new inode, and delete
-+ * that one from the delete thread instead.  This avoids a lot of latency
-+ * when truncating large files.
-+ *
-+ * If we have any problem deferring the truncate, just truncate it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+void ext3_truncate_thread(struct inode *old_inode)
-+{
-+      struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+      struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+      struct inode *new_inode;
-+      handle_t *handle;
-+      unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+      if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+              goto out_truncate;
-+
-+      /* XXX This is a temporary limitation for code simplicity.
-+       *     We could truncate to arbitrary sizes at some later time.
-+       */
-+      if (old_inode->i_size != 0)
-+              goto out_truncate;
-+
-+      /* We may want to truncate the inode immediately and not defer it */
-+      if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS ||
-+          old_inode->i_size > oei->i_disksize)
-+              goto out_truncate;
-+
-+      /* We can't use the delete thread as-is during real orphan recovery,
-+       * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+       * to loop endlessly.  It would be nice to do so, but needs work.
-+       */
-+      if (oei->i_state & EXT3_STATE_DELETE ||
-+          sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+              ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+                         old_inode->i_ino, blocks);
-+              goto out_truncate;
-+      }
-+
-+      ext3_discard_prealloc(old_inode);
-+
-+      /* old_inode   = 1
-+       * new_inode   = sb + GDT + ibitmap
-+       * orphan list = 1 inode/superblock for add, 2 inodes for del
-+       * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS
-+       */
-+      handle = ext3_journal_start(old_inode, 7);
-+      if (IS_ERR(handle))
-+              goto out_truncate;
-+
-+      new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode);
-+      if (IS_ERR(new_inode)) {
-+              ext3_debug("truncate inode %lu directly (no new inodes)\n",
-+                         old_inode->i_ino);
-+              goto out_journal;
-+      }
-+
-+      nei = EXT3_I(new_inode);
-+
-+      down_write(&oei->truncate_sem);
-+      new_inode->i_size = old_inode->i_size;
-+      new_inode->i_blocks = old_inode->i_blocks;
-+      new_inode->i_uid = old_inode->i_uid;
-+      new_inode->i_gid = old_inode->i_gid;
-+      new_inode->i_nlink = 0;
-+
-+      /* FIXME when we do arbitrary truncates */
-+      old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0;
-+      old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME;
-+
-+      memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
-+      memset(oei->i_data, 0, sizeof(oei->i_data));
-+
-+      nei->i_disksize = oei->i_disksize;
-+      nei->i_state |= EXT3_STATE_DELETE;
-+      up_write(&oei->truncate_sem);
-+
-+      if (ext3_orphan_add(handle, new_inode) < 0)
-+              goto out_journal;
-+
-+      if (ext3_orphan_del(handle, old_inode) < 0) {
-+              ext3_orphan_del(handle, new_inode);
-+              iput(new_inode);
-+              goto out_journal;
-+      }
-+
-+      ext3_journal_stop(handle, old_inode);
-+
-+      spin_lock(&sbi->s_delete_lock);
-+      J_ASSERT(list_empty(&new_inode->i_dentry));
-+      list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+      sbi->s_delete_blocks += blocks;
-+      sbi->s_delete_inodes++;
-+      spin_unlock(&sbi->s_delete_lock);
-+
-+      ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+                 new_inode->i_ino, blocks);
-+
-+      wake_up(&sbi->s_delete_thread_queue);
-+      return;
-+
-+out_journal:
-+      ext3_journal_stop(handle, old_inode);
-+out_truncate:
-+      ext3_truncate(old_inode);
-+}
-+#endif /* EXT3_DELETE_THREAD */
-+
- /* 
-  * ext3_get_inode_loc returns with an extra refcount against the
-  * inode's underlying buffer_head on success. 
---- linux-2.4.18-chaos/fs/ext3/super.c~ext3-delete_thread-2.4.18-2     2003-09-16 23:42:33.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/super.c  2003-09-16 23:42:34.000000000 +0400
-@@ -398,6 +398,220 @@ static void dump_orphan_list(struct supe
-       }
- }
-+#ifdef EXT3_DELETE_THREAD
-+/*
-+ * Delete inodes in a loop until there are no more to be deleted.
-+ * Normally, we run in the background doing the deletes and sleeping again,
-+ * and clients just add new inodes to be deleted onto the end of the list.
-+ * If someone is concerned about free space (e.g. block allocation or similar)
-+ * then they can sleep on s_delete_waiter_queue and be woken up when space
-+ * has been freed.
-+ */
-+int ext3_delete_thread(void *data)
-+{
-+      struct super_block *sb = data;
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      struct task_struct *tsk = current;
-+
-+      /* Almost like daemonize, but not quite */
-+      exit_mm(current);
-+      tsk->session = 1;
-+      tsk->pgrp = 1;
-+      tsk->tty = NULL;
-+      exit_files(current);
-+      reparent_to_init();
-+
-+      sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev));
-+      sigfillset(&tsk->blocked);
-+
-+      /*tsk->flags |= PF_KERNTHREAD;*/
-+
-+      INIT_LIST_HEAD(&sbi->s_delete_list);
-+      wake_up(&sbi->s_delete_waiter_queue);
-+      ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev));
-+
-+      /* main loop */
-+      for (;;) {
-+              wait_event_interruptible(sbi->s_delete_thread_queue,
-+                                       !list_empty(&sbi->s_delete_list) ||
-+                                       !test_opt(sb, ASYNCDEL));
-+              ext3_debug("%s woken up: %lu inodes, %lu blocks\n",
-+                         tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks);
-+
-+              spin_lock(&sbi->s_delete_lock);
-+              if (list_empty(&sbi->s_delete_list)) {
-+                      clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+                      memset(&sbi->s_delete_list, 0,
-+                             sizeof(sbi->s_delete_list));
-+                      spin_unlock(&sbi->s_delete_lock);
-+                      ext3_debug("delete thread on %s exiting\n",
-+                                 kdevname(sb->s_dev));
-+                      wake_up(&sbi->s_delete_waiter_queue);
-+                      break;
-+              }
-+
-+              while (!list_empty(&sbi->s_delete_list)) {
-+                      struct inode *inode=list_entry(sbi->s_delete_list.next,
-+                                                     struct inode, i_dentry);
-+                      unsigned long blocks = inode->i_blocks >>
-+                                                      (inode->i_blkbits - 9);
-+
-+                      list_del_init(&inode->i_dentry);
-+                      spin_unlock(&sbi->s_delete_lock);
-+                      ext3_debug("%s delete ino %lu blk %lu\n",
-+                                 tsk->comm, inode->i_ino, blocks);
-+
-+                      iput(inode);
-+
-+                      spin_lock(&sbi->s_delete_lock);
-+                      sbi->s_delete_blocks -= blocks;
-+                      sbi->s_delete_inodes--;
-+              }
-+              if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) {
-+                      ext3_warning(sb, __FUNCTION__,
-+                                   "%lu blocks, %lu inodes on list?\n",
-+                                   sbi->s_delete_blocks,sbi->s_delete_inodes);
-+                      sbi->s_delete_blocks = 0;
-+                      sbi->s_delete_inodes = 0;
-+              }
-+              spin_unlock(&sbi->s_delete_lock);
-+              wake_up(&sbi->s_delete_waiter_queue);
-+      }
-+
-+      return 0;
-+}
-+
-+static void ext3_start_delete_thread(struct super_block *sb)
-+{
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int rc;
-+
-+      spin_lock_init(&sbi->s_delete_lock);
-+      init_waitqueue_head(&sbi->s_delete_thread_queue);
-+      init_waitqueue_head(&sbi->s_delete_waiter_queue);
-+
-+      if (!test_opt(sb, ASYNCDEL))
-+              return;
-+
-+      rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES);
-+      if (rc < 0)
-+              printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n",
-+                     rc);
-+      else
-+              wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next);
-+}
-+
-+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi)
-+{
-+      if (sbi->s_delete_list.next == 0)       /* thread never started */
-+              return;
-+
-+      clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+      wake_up(&sbi->s_delete_thread_queue);
-+      wait_event(sbi->s_delete_waiter_queue, list_empty(&sbi->s_delete_list));
-+}
-+
-+/* Instead of playing games with the inode flags, destruction, etc we just
-+ * create a new inode locally and put it on a list for the truncate thread.
-+ * We need large parts of the inode struct in order to complete the
-+ * truncate and unlink, so we may as well just have a real inode to do it.
-+ *
-+ * If we have any problem deferring the delete, just delete it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+static void ext3_delete_inode_thread(struct inode *old_inode)
-+{
-+      struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+      struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+      struct inode *new_inode;
-+      unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+      if (is_bad_inode(old_inode)) {
-+              clear_inode(old_inode);
-+              return;
-+      }
-+
-+      if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+              goto out_delete;
-+
-+      /* We may want to delete the inode immediately and not defer it */
-+      if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS)
-+              goto out_delete;
-+
-+      /* We can't use the delete thread as-is during real orphan recovery,
-+       * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+       * to loop endlessly.  It would be nice to do so, but needs work.
-+       */
-+      if (oei->i_state & EXT3_STATE_DELETE ||
-+          sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+              ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+                         old_inode->i_ino, blocks);
-+              goto out_delete;
-+      }
-+
-+      /* We can iget this inode again here, because our caller has unhashed
-+       * old_inode, so new_inode will be in a different inode struct.
-+       *
-+       * We need to ensure that the i_orphan pointers in the other inodes
-+       * point at the new inode copy instead of the old one so the orphan
-+       * list doesn't get corrupted when the old orphan inode is freed.
-+       */
-+      down(&sbi->s_orphan_lock);
-+
-+      sbi->s_mount_state |= EXT3_ORPHAN_FS;
-+      new_inode = iget(old_inode->i_sb, old_inode->i_ino);
-+      sbi->s_mount_state &= ~EXT3_ORPHAN_FS;
-+      if (is_bad_inode(new_inode)) {
-+              printk(KERN_WARNING "read bad inode %lu\n", old_inode->i_ino);
-+              iput(new_inode);
-+              new_inode = NULL;
-+      }
-+      if (!new_inode) {
-+              up(&sbi->s_orphan_lock);
-+              ext3_debug("delete inode %lu directly (bad read)\n",
-+                         old_inode->i_ino);
-+              goto out_delete;
-+      }
-+      J_ASSERT(new_inode != old_inode);
-+
-+      J_ASSERT(!list_empty(&oei->i_orphan));
-+
-+      nei = EXT3_I(new_inode);
-+      /* Ugh.  We need to insert new_inode into the same spot on the list
-+       * as old_inode was, to ensure the in-memory orphan list is still
-+       * in the same order as the on-disk orphan list (badness otherwise).
-+       */
-+      nei->i_orphan = oei->i_orphan;
-+      nei->i_orphan.next->prev = &nei->i_orphan;
-+      nei->i_orphan.prev->next = &nei->i_orphan;
-+      nei->i_state |= EXT3_STATE_DELETE;
-+      up(&sbi->s_orphan_lock);
-+
-+      clear_inode(old_inode);
-+
-+      spin_lock(&sbi->s_delete_lock);
-+      J_ASSERT(list_empty(&new_inode->i_dentry));
-+      list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+      sbi->s_delete_blocks += blocks;
-+      sbi->s_delete_inodes++;
-+      spin_unlock(&sbi->s_delete_lock);
-+
-+      ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+                 new_inode->i_ino, blocks);
-+
-+      wake_up(&sbi->s_delete_thread_queue);
-+      return;
-+
-+out_delete:
-+      ext3_delete_inode(old_inode);
-+}
-+#else
-+#define ext3_start_delete_thread(sbi) do {} while(0)
-+#define ext3_stop_delete_thread(sbi) do {} while(0)
-+#endif /* EXT3_DELETE_THREAD */
-+
- void ext3_put_super (struct super_block * sb)
- {
-       struct ext3_sb_info *sbi = EXT3_SB(sb);
-@@ -405,6 +619,7 @@ void ext3_put_super (struct super_block 
-       kdev_t j_dev = sbi->s_journal->j_dev;
-       int i;
-+      ext3_stop_delete_thread(sbi);
-       ext3_xattr_put_super(sb);
-       journal_destroy(sbi->s_journal);
-       if (!(sb->s_flags & MS_RDONLY)) {
-@@ -453,7 +668,11 @@ static struct super_operations ext3_sops
-       write_inode:    ext3_write_inode,       /* BKL not held.  Don't need */
-       dirty_inode:    ext3_dirty_inode,       /* BKL not held.  We take it */
-       put_inode:      ext3_put_inode,         /* BKL not held.  Don't need */
-+#ifdef EXT3_DELETE_THREAD
-+      delete_inode:   ext3_delete_inode_thread,/* BKL not held. We take it */
-+#else
-       delete_inode:   ext3_delete_inode,      /* BKL not held.  We take it */
-+#endif
-       put_super:      ext3_put_super,         /* BKL held */
-       write_super:    ext3_write_super,       /* BKL held */
-       sync_fs:        ext3_sync_fs,
-@@ -514,6 +733,14 @@ static int parse_options (char * options
-            this_char = strtok (NULL, ",")) {
-               if ((value = strchr (this_char, '=')) != NULL)
-                       *value++ = 0;
-+#ifdef EXT3_DELETE_THREAD
-+              if (!strcmp(this_char, "asyncdel"))
-+                      set_opt(*mount_options, ASYNCDEL);
-+              else if (!strcmp(this_char, "noasyncdel"))
-+                      clear_opt(*mount_options, ASYNCDEL);
-+              else
-+#endif
-+
-               if (!strcmp (this_char, "bsddf"))
-                       clear_opt (*mount_options, MINIX_DF);
-               else if (!strcmp (this_char, "nouid32")) {
-@@ -1203,6 +1430,7 @@ struct super_block * ext3_read_super (st
-       }
-       ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-+      ext3_start_delete_thread(sb);
-       /*
-        * akpm: core read_super() calls in here with the superblock locked.
-        * That deadlocks, because orphan cleanup needs to lock the superblock
-@@ -1643,6 +1871,9 @@ int ext3_remount (struct super_block * s
-       if (!parse_options(data, &tmp, sbi, &tmp, 1))
-               return -EINVAL;
-+      if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY))
-+              ext3_stop_delete_thread(sbi);
-+
-       if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
-               ext3_abort(sb, __FUNCTION__, "Abort forced by user");
---- linux-2.4.18-chaos/include/linux/ext3_fs.h~ext3-delete_thread-2.4.18-2     2003-09-16 23:39:37.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/include/linux/ext3_fs.h  2003-09-16 23:42:34.000000000 +0400
-@@ -195,6 +195,7 @@ struct ext3_group_desc
-  */
- #define EXT3_STATE_JDATA              0x00000001 /* journaled data exists */
- #define EXT3_STATE_NEW                        0x00000002 /* inode is newly created */
-+#define EXT3_STATE_DELETE             0x00000010 /* deferred delete inode */
- /*
-  * ioctl commands
-@@ -322,6 +323,7 @@ struct ext3_inode {
-   #define EXT3_MOUNT_WRITEBACK_DATA   0x0C00  /* No data ordering */
- #define EXT3_MOUNT_UPDATE_JOURNAL     0x1000  /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32           0x2000  /* Disable 32-bit UIDs */
-+#define EXT3_MOUNT_ASYNCDEL           0x20000 /* Delayed deletion */
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -708,6 +710,9 @@ extern void ext3_discard_prealloc (struc
- extern void ext3_dirty_inode(struct inode *);
- extern int ext3_change_inode_journal_flag(struct inode *, int);
- extern void ext3_truncate (struct inode *);
-+#ifdef EXT3_DELETE_THREAD
-+extern void ext3_truncate_thread(struct inode *inode);
-+#endif
- /* ioctl.c */
- extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
---- linux-2.4.18-chaos/include/linux/ext3_fs_sb.h~ext3-delete_thread-2.4.18-2  2003-09-16 23:42:33.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/include/linux/ext3_fs_sb.h       2003-09-16 23:42:34.000000000 +0400
-@@ -29,6 +29,8 @@
- #define EXT3_MAX_GROUP_LOADED 32
-+#define EXT3_DELETE_THREAD
-+
- /*
-  * third extended-fs super-block data in memory
-  */
-@@ -76,6 +78,14 @@ struct ext3_sb_info {
-       struct timer_list turn_ro_timer;        /* For turning read-only (crash simulation) */
-       wait_queue_head_t ro_wait_queue;        /* For people waiting for the fs to go read-only */
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+      spinlock_t s_delete_lock;
-+      struct list_head s_delete_list;
-+      unsigned long s_delete_blocks;
-+      unsigned long s_delete_inodes;
-+      wait_queue_head_t s_delete_thread_queue;
-+      wait_queue_head_t s_delete_waiter_queue;
-+#endif
- };
- #endif        /* _LINUX_EXT3_FS_SB */
-
-_
diff --git a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.18.patch b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.18.patch
deleted file mode 100644 (file)
index a6a64de..0000000
+++ /dev/null
@@ -1,517 +0,0 @@
-
-Create a service thread to handle delete and truncate of inodes, to avoid
-long latency while truncating very large files.
-
-
- fs/ext3/inode.c            |  116 ++++++++++++++++++++++
- fs/ext3/super.c            |  231 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/ext3_fs.h    |    5 
- include/linux/ext3_fs_sb.h |   10 +
- 4 files changed, 362 insertions(+)
-
-Index: linux-2.4.18-chaos/fs/ext3/super.c
-===================================================================
---- linux-2.4.18-chaos.orig/fs/ext3/super.c    2004-01-13 15:39:03.000000000 +0300
-+++ linux-2.4.18-chaos/fs/ext3/super.c 2004-01-13 16:35:05.000000000 +0300
-@@ -398,6 +398,221 @@
-       }
- }
-+#ifdef EXT3_DELETE_THREAD
-+/*
-+ * Delete inodes in a loop until there are no more to be deleted.
-+ * Normally, we run in the background doing the deletes and sleeping again,
-+ * and clients just add new inodes to be deleted onto the end of the list.
-+ * If someone is concerned about free space (e.g. block allocation or similar)
-+ * then they can sleep on s_delete_waiter_queue and be woken up when space
-+ * has been freed.
-+ */
-+int ext3_delete_thread(void *data)
-+{
-+      struct super_block *sb = data;
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      struct task_struct *tsk = current;
-+
-+      /* Almost like daemonize, but not quite */
-+      exit_mm(current);
-+      tsk->session = 1;
-+      tsk->pgrp = 1;
-+      tsk->tty = NULL;
-+      exit_files(current);
-+      reparent_to_init();
-+
-+      sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev));
-+      sigfillset(&tsk->blocked);
-+
-+      /*tsk->flags |= PF_KERNTHREAD;*/
-+
-+      INIT_LIST_HEAD(&sbi->s_delete_list);
-+      wake_up(&sbi->s_delete_waiter_queue);
-+      ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev));
-+
-+      /* main loop */
-+      for (;;) {
-+              wait_event_interruptible(sbi->s_delete_thread_queue,
-+                                       !list_empty(&sbi->s_delete_list) ||
-+                                       !test_opt(sb, ASYNCDEL));
-+              ext3_debug("%s woken up: %lu inodes, %lu blocks\n",
-+                         tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks);
-+
-+              spin_lock(&sbi->s_delete_lock);
-+              if (list_empty(&sbi->s_delete_list)) {
-+                      clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+                      memset(&sbi->s_delete_list, 0,
-+                             sizeof(sbi->s_delete_list));
-+                      spin_unlock(&sbi->s_delete_lock);
-+                      ext3_debug("delete thread on %s exiting\n",
-+                                 kdevname(sb->s_dev));
-+                      wake_up(&sbi->s_delete_waiter_queue);
-+                      break;
-+              }
-+
-+              while (!list_empty(&sbi->s_delete_list)) {
-+                      struct inode *inode=list_entry(sbi->s_delete_list.next,
-+                                                     struct inode, i_dentry);
-+                      unsigned long blocks = inode->i_blocks >>
-+                                                      (inode->i_blkbits - 9);
-+
-+                      list_del_init(&inode->i_dentry);
-+                      spin_unlock(&sbi->s_delete_lock);
-+                      ext3_debug("%s delete ino %lu blk %lu\n",
-+                                 tsk->comm, inode->i_ino, blocks);
-+
-+                      iput(inode);
-+
-+                      spin_lock(&sbi->s_delete_lock);
-+                      sbi->s_delete_blocks -= blocks;
-+                      sbi->s_delete_inodes--;
-+              }
-+              if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) {
-+                      ext3_warning(sb, __FUNCTION__,
-+                                   "%lu blocks, %lu inodes on list?\n",
-+                                   sbi->s_delete_blocks,sbi->s_delete_inodes);
-+                      sbi->s_delete_blocks = 0;
-+                      sbi->s_delete_inodes = 0;
-+              }
-+              spin_unlock(&sbi->s_delete_lock);
-+              wake_up(&sbi->s_delete_waiter_queue);
-+      }
-+
-+      return 0;
-+}
-+
-+static void ext3_start_delete_thread(struct super_block *sb)
-+{
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+      int rc;
-+
-+      spin_lock_init(&sbi->s_delete_lock);
-+      init_waitqueue_head(&sbi->s_delete_thread_queue);
-+      init_waitqueue_head(&sbi->s_delete_waiter_queue);
-+
-+      if (!test_opt(sb, ASYNCDEL))
-+              return;
-+
-+      rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES);
-+      if (rc < 0)
-+              printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n",
-+                     rc);
-+      else
-+              wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next);
-+}
-+
-+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi)
-+{
-+      if (sbi->s_delete_list.next == 0)       /* thread never started */
-+              return;
-+
-+      clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+      wake_up(&sbi->s_delete_thread_queue);
-+      wait_event(sbi->s_delete_waiter_queue,
-+                      sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0);
-+}
-+
-+/* Instead of playing games with the inode flags, destruction, etc we just
-+ * create a new inode locally and put it on a list for the truncate thread.
-+ * We need large parts of the inode struct in order to complete the
-+ * truncate and unlink, so we may as well just have a real inode to do it.
-+ *
-+ * If we have any problem deferring the delete, just delete it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+static void ext3_delete_inode_thread(struct inode *old_inode)
-+{
-+      struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+      struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+      struct inode *new_inode;
-+      unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+      if (is_bad_inode(old_inode)) {
-+              clear_inode(old_inode);
-+              return;
-+      }
-+
-+      if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+              goto out_delete;
-+
-+      /* We may want to delete the inode immediately and not defer it */
-+      if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS)
-+              goto out_delete;
-+
-+      /* We can't use the delete thread as-is during real orphan recovery,
-+       * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+       * to loop endlessly.  It would be nice to do so, but needs work.
-+       */
-+      if (oei->i_state & EXT3_STATE_DELETE ||
-+          sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+              ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+                         old_inode->i_ino, blocks);
-+              goto out_delete;
-+      }
-+
-+      /* We can iget this inode again here, because our caller has unhashed
-+       * old_inode, so new_inode will be in a different inode struct.
-+       *
-+       * We need to ensure that the i_orphan pointers in the other inodes
-+       * point at the new inode copy instead of the old one so the orphan
-+       * list doesn't get corrupted when the old orphan inode is freed.
-+       */
-+      down(&sbi->s_orphan_lock);
-+
-+      sbi->s_mount_state |= EXT3_ORPHAN_FS;
-+      new_inode = iget(old_inode->i_sb, old_inode->i_ino);
-+      sbi->s_mount_state &= ~EXT3_ORPHAN_FS;
-+      if (is_bad_inode(new_inode)) {
-+              printk(KERN_WARNING "read bad inode %lu\n", old_inode->i_ino);
-+              iput(new_inode);
-+              new_inode = NULL;
-+      }
-+      if (!new_inode) {
-+              up(&sbi->s_orphan_lock);
-+              ext3_debug("delete inode %lu directly (bad read)\n",
-+                         old_inode->i_ino);
-+              goto out_delete;
-+      }
-+      J_ASSERT(new_inode != old_inode);
-+
-+      J_ASSERT(!list_empty(&oei->i_orphan));
-+
-+      nei = EXT3_I(new_inode);
-+      /* Ugh.  We need to insert new_inode into the same spot on the list
-+       * as old_inode was, to ensure the in-memory orphan list is still
-+       * in the same order as the on-disk orphan list (badness otherwise).
-+       */
-+      nei->i_orphan = oei->i_orphan;
-+      nei->i_orphan.next->prev = &nei->i_orphan;
-+      nei->i_orphan.prev->next = &nei->i_orphan;
-+      nei->i_state |= EXT3_STATE_DELETE;
-+      up(&sbi->s_orphan_lock);
-+
-+      clear_inode(old_inode);
-+
-+      spin_lock(&sbi->s_delete_lock);
-+      J_ASSERT(list_empty(&new_inode->i_dentry));
-+      list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+      sbi->s_delete_blocks += blocks;
-+      sbi->s_delete_inodes++;
-+      spin_unlock(&sbi->s_delete_lock);
-+
-+      ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+                 new_inode->i_ino, blocks);
-+
-+      wake_up(&sbi->s_delete_thread_queue);
-+      return;
-+
-+out_delete:
-+      ext3_delete_inode(old_inode);
-+}
-+#else
-+#define ext3_start_delete_thread(sbi) do {} while(0)
-+#define ext3_stop_delete_thread(sbi) do {} while(0)
-+#endif /* EXT3_DELETE_THREAD */
-+
- void ext3_put_super (struct super_block * sb)
- {
-       struct ext3_sb_info *sbi = EXT3_SB(sb);
-@@ -405,6 +620,8 @@
-       kdev_t j_dev = sbi->s_journal->j_dev;
-       int i;
-+      J_ASSERT(sbi->s_delete_inodes == 0);
-+
-       ext3_xattr_put_super(sb);
-       journal_destroy(sbi->s_journal);
-       if (!(sb->s_flags & MS_RDONLY)) {
-@@ -453,7 +670,11 @@
-       write_inode:    ext3_write_inode,       /* BKL not held.  Don't need */
-       dirty_inode:    ext3_dirty_inode,       /* BKL not held.  We take it */
-       put_inode:      ext3_put_inode,         /* BKL not held.  Don't need */
-+#ifdef EXT3_DELETE_THREAD
-+      delete_inode:   ext3_delete_inode_thread,/* BKL not held. We take it */
-+#else
-       delete_inode:   ext3_delete_inode,      /* BKL not held.  We take it */
-+#endif
-       put_super:      ext3_put_super,         /* BKL held */
-       write_super:    ext3_write_super,       /* BKL held */
-       sync_fs:        ext3_sync_fs,
-@@ -514,6 +735,14 @@
-            this_char = strtok (NULL, ",")) {
-               if ((value = strchr (this_char, '=')) != NULL)
-                       *value++ = 0;
-+#ifdef EXT3_DELETE_THREAD
-+              if (!strcmp(this_char, "asyncdel"))
-+                      set_opt(*mount_options, ASYNCDEL);
-+              else if (!strcmp(this_char, "noasyncdel"))
-+                      clear_opt(*mount_options, ASYNCDEL);
-+              else
-+#endif
-+
-               if (!strcmp (this_char, "bsddf"))
-                       clear_opt (*mount_options, MINIX_DF);
-               else if (!strcmp (this_char, "nouid32")) {
-@@ -1209,6 +1438,7 @@
-       }
-       ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-+      ext3_start_delete_thread(sb);
-       /*
-        * akpm: core read_super() calls in here with the superblock locked.
-        * That deadlocks, because orphan cleanup needs to lock the superblock
-@@ -1585,7 +1815,12 @@
- static int ext3_sync_fs(struct super_block *sb)
- {
-       tid_t target;
--      
-+
-+      if (atomic_read(&sb->s_active) == 0) {
-+              /* fs is being umounted: time to stop delete thread */
-+              ext3_stop_delete_thread(EXT3_SB(sb));
-+      }
-+
-       sb->s_dirt = 0;
-       target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
-       log_wait_commit(EXT3_SB(sb)->s_journal, target);
-@@ -1649,6 +1884,9 @@
-       if (!parse_options(data, &tmp, sbi, &tmp, 1))
-               return -EINVAL;
-+      if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY))
-+              ext3_stop_delete_thread(sbi);
-+
-       if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
-               ext3_abort(sb, __FUNCTION__, "Abort forced by user");
-Index: linux-2.4.18-chaos/fs/ext3/file.c
-===================================================================
---- linux-2.4.18-chaos.orig/fs/ext3/file.c     2003-07-28 17:52:04.000000000 +0400
-+++ linux-2.4.18-chaos/fs/ext3/file.c  2004-01-13 16:26:01.000000000 +0300
-@@ -121,7 +121,11 @@
- };
- struct inode_operations ext3_file_inode_operations = {
-+#ifdef EXT3_DELETE_THREAD
-+      truncate:       ext3_truncate_thread,   /* BKL held */
-+#else
-       truncate:       ext3_truncate,          /* BKL held */
-+#endif
-       setattr:        ext3_setattr,           /* BKL held */
- };
-Index: linux-2.4.18-chaos/fs/ext3/inode.c
-===================================================================
---- linux-2.4.18-chaos.orig/fs/ext3/inode.c    2004-01-13 15:39:03.000000000 +0300
-+++ linux-2.4.18-chaos/fs/ext3/inode.c 2004-01-13 16:26:01.000000000 +0300
-@@ -2041,6 +2041,118 @@
-       return;         /* AKPM: return what? */
- }
-+#ifdef EXT3_DELETE_THREAD
-+/* Move blocks from to-be-truncated inode over to a new inode, and delete
-+ * that one from the delete thread instead.  This avoids a lot of latency
-+ * when truncating large files.
-+ *
-+ * If we have any problem deferring the truncate, just truncate it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+void ext3_truncate_thread(struct inode *old_inode)
-+{
-+      struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+      struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+      struct inode *new_inode;
-+      handle_t *handle;
-+      unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+      if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+              goto out_truncate;
-+
-+      /* XXX This is a temporary limitation for code simplicity.
-+       *     We could truncate to arbitrary sizes at some later time.
-+       */
-+      if (old_inode->i_size != 0)
-+              goto out_truncate;
-+
-+      /* We may want to truncate the inode immediately and not defer it */
-+      if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS ||
-+          old_inode->i_size > oei->i_disksize)
-+              goto out_truncate;
-+
-+      /* We can't use the delete thread as-is during real orphan recovery,
-+       * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+       * to loop endlessly.  It would be nice to do so, but needs work.
-+       */
-+      if (oei->i_state & EXT3_STATE_DELETE ||
-+          sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+              ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+                         old_inode->i_ino, blocks);
-+              goto out_truncate;
-+      }
-+
-+      ext3_discard_prealloc(old_inode);
-+
-+      /* old_inode   = 1
-+       * new_inode   = sb + GDT + ibitmap
-+       * orphan list = 1 inode/superblock for add, 2 inodes for del
-+       * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS
-+       */
-+      handle = ext3_journal_start(old_inode, 7);
-+      if (IS_ERR(handle))
-+              goto out_truncate;
-+
-+      new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode);
-+      if (IS_ERR(new_inode)) {
-+              ext3_debug("truncate inode %lu directly (no new inodes)\n",
-+                         old_inode->i_ino);
-+              goto out_journal;
-+      }
-+
-+      nei = EXT3_I(new_inode);
-+
-+      down_write(&oei->truncate_sem);
-+      new_inode->i_size = old_inode->i_size;
-+      new_inode->i_blocks = old_inode->i_blocks;
-+      new_inode->i_uid = old_inode->i_uid;
-+      new_inode->i_gid = old_inode->i_gid;
-+      new_inode->i_nlink = 0;
-+
-+      /* FIXME when we do arbitrary truncates */
-+      old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0;
-+      old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME;
-+
-+      memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
-+      memset(oei->i_data, 0, sizeof(oei->i_data));
-+
-+      nei->i_disksize = oei->i_disksize;
-+      nei->i_state |= EXT3_STATE_DELETE;
-+      up_write(&oei->truncate_sem);
-+
-+      if (ext3_orphan_add(handle, new_inode) < 0)
-+              goto out_journal;
-+
-+      if (ext3_orphan_del(handle, old_inode) < 0) {
-+              ext3_orphan_del(handle, new_inode);
-+              iput(new_inode);
-+              goto out_journal;
-+      }
-+
-+      ext3_journal_stop(handle, old_inode);
-+
-+      spin_lock(&sbi->s_delete_lock);
-+      J_ASSERT(list_empty(&new_inode->i_dentry));
-+      list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+      sbi->s_delete_blocks += blocks;
-+      sbi->s_delete_inodes++;
-+      spin_unlock(&sbi->s_delete_lock);
-+
-+      ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+                 new_inode->i_ino, blocks);
-+
-+      wake_up(&sbi->s_delete_thread_queue);
-+      return;
-+
-+out_journal:
-+      ext3_journal_stop(handle, old_inode);
-+out_truncate:
-+      ext3_truncate(old_inode);
-+}
-+#endif /* EXT3_DELETE_THREAD */
-+
- /* 
-  * ext3_get_inode_loc returns with an extra refcount against the
-  * inode's underlying buffer_head on success. 
-Index: linux-2.4.18-chaos/fs/buffer.c
-===================================================================
---- linux-2.4.18-chaos.orig/fs/buffer.c        2003-07-28 17:52:03.000000000 +0400
-+++ linux-2.4.18-chaos/fs/buffer.c     2004-01-13 16:34:43.000000000 +0300
-@@ -352,9 +352,9 @@
-       lock_super(sb);
-       if (sb->s_dirt && sb->s_op && sb->s_op->write_super)
-               sb->s_op->write_super(sb);
-+      unlock_super(sb);
-       if (sb->s_op && sb->s_op->sync_fs)
-               sb->s_op->sync_fs(sb);
--      unlock_super(sb);
-       unlock_kernel();
-       return sync_buffers(dev, 1);
-Index: linux-2.4.18-chaos/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.18-chaos.orig/include/linux/ext3_fs.h    2004-01-13 15:39:03.000000000 +0300
-+++ linux-2.4.18-chaos/include/linux/ext3_fs.h 2004-01-13 16:26:01.000000000 +0300
-@@ -190,6 +190,7 @@
-  */
- #define EXT3_STATE_JDATA              0x00000001 /* journaled data exists */
- #define EXT3_STATE_NEW                        0x00000002 /* inode is newly created */
-+#define EXT3_STATE_DELETE             0x00000010 /* deferred delete inode */
- /*
-  * ioctl commands
-@@ -317,6 +318,7 @@
- #define EXT3_MOUNT_UPDATE_JOURNAL     0x1000  /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32           0x2000  /* Disable 32-bit UIDs */
- #define EXT3_MOUNT_INDEX              0x4000  /* Enable directory index */
-+#define EXT3_MOUNT_ASYNCDEL           0x20000 /* Delayed deletion */
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -651,6 +653,9 @@
- extern void ext3_dirty_inode(struct inode *);
- extern int ext3_change_inode_journal_flag(struct inode *, int);
- extern void ext3_truncate (struct inode *);
-+#ifdef EXT3_DELETE_THREAD
-+extern void ext3_truncate_thread(struct inode *inode);
-+#endif
- /* ioctl.c */
- extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
-Index: linux-2.4.18-chaos/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.18-chaos.orig/include/linux/ext3_fs_sb.h 2004-01-13 15:39:03.000000000 +0300
-+++ linux-2.4.18-chaos/include/linux/ext3_fs_sb.h      2004-01-13 16:26:01.000000000 +0300
-@@ -29,6 +29,8 @@
- #define EXT3_MAX_GROUP_LOADED 32
-+#define EXT3_DELETE_THREAD
-+
- /*
-  * third extended-fs super-block data in memory
-  */
-@@ -74,6 +76,14 @@
-       struct timer_list turn_ro_timer;        /* For turning read-only (crash simulation) */
-       wait_queue_head_t ro_wait_queue;        /* For people waiting for the fs to go read-only */
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+      spinlock_t s_delete_lock;
-+      struct list_head s_delete_list;
-+      unsigned long s_delete_blocks;
-+      unsigned long s_delete_inodes;
-+      wait_queue_head_t s_delete_thread_queue;
-+      wait_queue_head_t s_delete_waiter_queue;
-+#endif
- };
- #endif        /* _LINUX_EXT3_FS_SB */
diff --git a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.18-chaos.patch b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.18-chaos.patch
deleted file mode 100644 (file)
index b6dc0dd..0000000
+++ /dev/null
@@ -1,761 +0,0 @@
- fs/ext3/ialloc.c          |    6 
- fs/ext3/inode.c           |   10 
- fs/ext3/super.c           |    4 
- fs/ext3/xattr.c           |  598 +++++++++++++++++++++++++++++++++++++++++++++-
- include/linux/ext3_fs.h   |    2 
- include/linux/ext3_fs_i.h |    3 
- 6 files changed, 613 insertions(+), 10 deletions(-)
-
---- linux-2.4.18-chaos/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.18-chaos  2003-10-08 10:38:03.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/ialloc.c 2003-10-08 15:08:45.000000000 +0400
-@@ -586,6 +586,12 @@ repeat:
-       insert_inode_hash(inode);
-       inode->i_generation = sbi->s_next_generation++;
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+              ei->i_extra_isize = sizeof(__u16)       /* i_extra_isize */
-+                              + sizeof(__u16);        /* i_pad1 */
-+      } else
-+              ei->i_extra_isize = 0;
-+
-       ei->i_state = EXT3_STATE_NEW;
-       err = ext3_get_inode_loc_new(inode, &iloc, 1);
-       if (err) goto fail;
---- linux-2.4.18-chaos/fs/ext3/inode.c~ext3-ea-in-inode-2.4.18-chaos   2003-10-08 10:38:03.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/inode.c  2003-10-08 15:08:45.000000000 +0400
-@@ -2459,6 +2459,11 @@ void ext3_read_inode(struct inode * inod
-               ei->i_data[block] = iloc.raw_inode->i_block[block];
-       INIT_LIST_HEAD(&ei->i_orphan);
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
-+              ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
-+      else
-+              ei->i_extra_isize = 0;
-+
-       brelse (iloc.bh);
-       if (S_ISREG(inode->i_mode)) {
-@@ -2523,6 +2528,8 @@ static int ext3_do_update_inode(handle_t
-               if (err)
-                       goto out_brelse;
-       }
-+      if (ei->i_state & EXT3_STATE_NEW)
-+              memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb));
-       raw_inode->i_mode = cpu_to_le16(inode->i_mode);
-       if(!(test_opt(inode->i_sb, NO_UID32))) {
-               raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
-@@ -2606,6 +2613,9 @@ static int ext3_do_update_inode(handle_t
-       else for (block = 0; block < EXT3_N_BLOCKS; block++)
-               raw_inode->i_block[block] = ei->i_data[block];
-+      if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
-+              raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
-+
-       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-       rc = ext3_journal_dirty_metadata(handle, bh);
-       if (!err)
---- linux-2.4.18-chaos/fs/ext3/xattr.c~ext3-ea-in-inode-2.4.18-chaos   2003-10-08 10:38:01.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/xattr.c  2003-10-12 16:16:44.000000000 +0400
-@@ -102,6 +102,9 @@
- static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
-                          struct ext3_xattr_header *);
-+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,
-+                      void *, size_t, int);
-+
- #ifdef CONFIG_EXT3_FS_XATTR_SHARING
- static int ext3_xattr_cache_insert(struct buffer_head *);
-@@ -362,17 +365,12 @@ ext3_removexattr(struct dentry *dentry, 
- }
- /*
-- * ext3_xattr_get()
-- *
-- * Copy an extended attribute into the buffer
-- * provided, or compute the buffer size required.
-- * Buffer is NULL to compute the size of the buffer required.
-+ * ext3_xattr_block_get()
-  *
-- * Returns a negative error number on failure, or the number of bytes
-- * used / required on success.
-+ * routine looks for attribute in EA block and returns it's value and size
-  */
- int
--ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
-              void *buffer, size_t buffer_size)
- {
-       struct buffer_head *bh = NULL;
-@@ -461,6 +459,94 @@ cleanup:
- }
- /*
-+ * ext3_xattr_ibode_get()
-+ *
-+ * routine looks for attribute in inode body and returns it's value and size
-+ */
-+int
-+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
-+             void *buffer, size_t buffer_size)
-+{
-+      int size, name_len = strlen(name), storage_size;
-+      struct ext3_xattr_entry *last;
-+      struct ext3_inode *raw_inode;
-+      struct ext3_iloc iloc;
-+      char *start, *end;
-+      int ret = -ENOENT;
-+      
-+      if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+              return -ENOENT;
-+
-+      ret = ext3_get_inode_loc(inode, &iloc);
-+      if (ret)
-+              return ret;
-+      raw_inode = iloc.raw_inode;
-+
-+      storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+                              EXT3_GOOD_OLD_INODE_SIZE -
-+                              EXT3_I(inode)->i_extra_isize -
-+                              sizeof(__u32);
-+      start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+                      EXT3_I(inode)->i_extra_isize;
-+      if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+              brelse(iloc.bh);
-+              return -ENOENT;
-+      }
-+      start += sizeof(__u32);
-+      end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+      last = (struct ext3_xattr_entry *) start;
-+      while (!IS_LAST_ENTRY(last)) {
-+              struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+              if (le32_to_cpu(last->e_value_size) > storage_size ||
-+                              (char *) next >= end) {
-+                      ext3_error(inode->i_sb, "ext3_xattr_ibody_get",
-+                              "inode %ld", inode->i_ino);
-+                      brelse(iloc.bh);
-+                      return -EIO;
-+              }
-+              if (name_index == last->e_name_index &&
-+                  name_len == last->e_name_len &&
-+                  !memcmp(name, last->e_name, name_len))
-+                      goto found;
-+              last = next;
-+      }
-+
-+      /* can't find EA */
-+      brelse(iloc.bh);
-+      return -ENOENT;
-+      
-+found:
-+      size = le32_to_cpu(last->e_value_size);
-+      if (buffer) {
-+              ret = -ERANGE;
-+              if (buffer_size >= size) {
-+                      memcpy(buffer, start + le16_to_cpu(last->e_value_offs),
-+                      size);
-+                      ret = size;
-+              }
-+      } else
-+              ret = size;
-+      brelse(iloc.bh);
-+      return ret;
-+}
-+
-+int ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+                      void *buffer, size_t buffer_size)
-+{
-+      int err;
-+
-+      /* try to find attribute in inode body */
-+      err = ext3_xattr_ibody_get(inode, name_index, name,
-+                                      buffer, buffer_size);
-+      if (err < 0)
-+              /* search was unsuccessful, try to find EA in dedicated block */
-+              err = ext3_xattr_block_get(inode, name_index, name,
-+                              buffer, buffer_size);
-+      return err;
-+}
-+
-+/*
-  * ext3_xattr_list()
-  *
-  * Copy a list of attribute names into the buffer
-@@ -471,7 +557,7 @@ cleanup:
-  * used / required on success.
-  */
- int
--ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
- {
-       struct buffer_head *bh = NULL;
-       struct ext3_xattr_entry *entry;
-@@ -547,6 +633,131 @@ cleanup:
-       return error;
- }
-+/* ext3_xattr_ibody_list()
-+ *
-+ * generate list of attributes stored in inode body
-+ */
-+int
-+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+      struct ext3_xattr_entry *last;
-+      struct ext3_inode *raw_inode;
-+      char *start, *end, *buf;
-+      struct ext3_iloc iloc;
-+      int storage_size;
-+      int ret;
-+      int size = 0;
-+      
-+      if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+              return 0;
-+
-+      ret = ext3_get_inode_loc(inode, &iloc);
-+      if (ret)
-+              return ret;
-+      raw_inode = iloc.raw_inode;
-+
-+      storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+                              EXT3_GOOD_OLD_INODE_SIZE -
-+                              EXT3_I(inode)->i_extra_isize -
-+                              sizeof(__u32);
-+      start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+                      EXT3_I(inode)->i_extra_isize;
-+      if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+              brelse(iloc.bh);
-+              return 0;
-+      }
-+      start += sizeof(__u32);
-+      end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+      last = (struct ext3_xattr_entry *) start;
-+      while (!IS_LAST_ENTRY(last)) {
-+              struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+              struct ext3_xattr_handler *handler;
-+              if (le32_to_cpu(last->e_value_size) > storage_size ||
-+                              (char *) next >= end) {
-+                      ext3_error(inode->i_sb, "ext3_xattr_ibody_list",
-+                              "inode %ld", inode->i_ino);
-+                      brelse(iloc.bh);
-+                      return -EIO;
-+              }
-+              handler = ext3_xattr_handler(last->e_name_index);
-+              if (handler)
-+                      size += handler->list(NULL, inode, last->e_name,
-+                                            last->e_name_len);
-+              last = next;
-+      }
-+
-+      if (!buffer) {
-+              ret = size;
-+              goto cleanup;
-+      } else {
-+              ret = -ERANGE;
-+              if (size > buffer_size)
-+                      goto cleanup;
-+      }
-+
-+      last = (struct ext3_xattr_entry *) start;
-+      buf = buffer;
-+      while (!IS_LAST_ENTRY(last)) {
-+              struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+              struct ext3_xattr_handler *handler;
-+              handler = ext3_xattr_handler(last->e_name_index);
-+              if (handler)
-+                      buf += handler->list(buf, inode, last->e_name,
-+                                            last->e_name_len);
-+              last = next;
-+      }
-+      ret = size;
-+cleanup:
-+      brelse(iloc.bh);
-+      return ret;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+      int error;
-+      int size = buffer_size;
-+
-+      /* get list of attributes stored in inode body */
-+      error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
-+      if (error < 0) {
-+              /* some error occured while collecting
-+               * attributes in inode body */
-+              size = 0;
-+              goto cleanup;
-+      }
-+      size = error;
-+
-+      /* get list of attributes stored in dedicated block */
-+      if (buffer) {
-+              buffer_size -= error;
-+              if (buffer_size <= 0) {
-+                      buffer = NULL;
-+                      buffer_size = 0;
-+              } else
-+                      buffer += error;
-+      }
-+
-+      error = ext3_xattr_block_list(inode, buffer, buffer_size);
-+      if (error < 0)
-+              /* listing was successful, so we return len */
-+              size = 0;
-+
-+cleanup:
-+      return error + size;
-+}
-+
- /*
-  * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-  * not set, set it.
-@@ -570,6 +781,279 @@ static void ext3_xattr_update_super_bloc
- }
- /*
-+ * ext3_xattr_ibody_find()
-+ *
-+ * search attribute and calculate free space in inode body
-+ * NOTE: free space includes space our attribute hold
-+ */
-+int
-+ext3_xattr_ibody_find(struct inode *inode, int name_index,
-+              const char *name, struct ext3_xattr_entry *rentry, int *free)
-+{
-+      struct ext3_xattr_entry *last;
-+      struct ext3_inode *raw_inode;
-+      int name_len = strlen(name);
-+      int err, storage_size;
-+      struct ext3_iloc iloc;
-+      char *start, *end;
-+      int ret = -ENOENT;
-+      
-+      if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+              return ret;
-+
-+      err = ext3_get_inode_loc(inode, &iloc);
-+      if (err)
-+              return -EIO;
-+      raw_inode = iloc.raw_inode;
-+
-+      storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+                              EXT3_GOOD_OLD_INODE_SIZE -
-+                              EXT3_I(inode)->i_extra_isize -
-+                              sizeof(__u32);
-+      *free = storage_size - sizeof(__u32);
-+      start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+                      EXT3_I(inode)->i_extra_isize;
-+      if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+              brelse(iloc.bh);
-+              return -ENOENT;
-+      }
-+      start += sizeof(__u32);
-+      end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+      last = (struct ext3_xattr_entry *) start;
-+      while (!IS_LAST_ENTRY(last)) {
-+              struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+              if (le32_to_cpu(last->e_value_size) > storage_size ||
-+                              (char *) next >= end) {
-+                      ext3_error(inode->i_sb, "ext3_xattr_ibody_find",
-+                              "inode %ld", inode->i_ino);
-+                      brelse(iloc.bh);
-+                      return -EIO;
-+              }
-+
-+              if (name_index == last->e_name_index &&
-+                  name_len == last->e_name_len &&
-+                  !memcmp(name, last->e_name, name_len)) {
-+                      memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
-+                      ret = 0;
-+              } else {
-+                      *free -= EXT3_XATTR_LEN(last->e_name_len);
-+                      *free -= le32_to_cpu(last->e_value_size);
-+              }
-+              last = next;
-+      }
-+      
-+      brelse(iloc.bh);
-+      return ret;
-+}
-+
-+/*
-+ * ext3_xattr_block_find()
-+ *
-+ * search attribute and calculate free space in EA block (if it allocated)
-+ * NOTE: free space includes space our attribute hold
-+ */
-+int
-+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
-+             struct ext3_xattr_entry *rentry, int *free)
-+{
-+      struct buffer_head *bh = NULL;
-+      struct ext3_xattr_entry *entry;
-+      char *end;
-+      int name_len, error = -ENOENT;
-+
-+      if (!EXT3_I(inode)->i_file_acl) {
-+              *free = inode->i_sb->s_blocksize -
-+                      sizeof(struct ext3_xattr_header) -
-+                      sizeof(__u32);
-+              return -ENOENT;
-+      }
-+      ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
-+      bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
-+      if (!bh)
-+              return -EIO;
-+      ea_bdebug(bh, "b_count=%d, refcount=%d",
-+              atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+      end = bh->b_data + bh->b_size;
-+      if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+          HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block:    ext3_error(inode->i_sb, "ext3_xattr_get",
-+                      "inode %ld: bad block %d", inode->i_ino,
-+                      EXT3_I(inode)->i_file_acl);
-+              brelse(bh);
-+              return -EIO;
-+      }
-+      /* find named attribute */
-+      name_len = strlen(name);
-+      *free = bh->b_size - sizeof(__u32);
-+
-+      entry = FIRST_ENTRY(bh);
-+      while (!IS_LAST_ENTRY(entry)) {
-+              struct ext3_xattr_entry *next =
-+                      EXT3_XATTR_NEXT(entry);
-+              if ((char *)next >= end)
-+                      goto bad_block;
-+              if (name_index == entry->e_name_index &&
-+                  name_len == entry->e_name_len &&
-+                  memcmp(name, entry->e_name, name_len) == 0) {
-+                      memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
-+                      error = 0;
-+              } else {
-+                      *free -= EXT3_XATTR_LEN(entry->e_name_len);
-+                      *free -= le32_to_cpu(entry->e_value_size);
-+              }
-+              entry = next;
-+      }
-+      brelse(bh);
-+
-+      return error;
-+}
-+
-+/*
-+ * ext3_xattr_inode_set()
-+ *
-+ * this routine add/remove/replace attribute in inode body
-+ */
-+int
-+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index,
-+                    const char *name, const void *value, size_t value_len,
-+                    int flags)
-+{
-+      struct ext3_xattr_entry *last, *next, *here = NULL;
-+      struct ext3_inode *raw_inode;
-+      int name_len = strlen(name);
-+      int esize = EXT3_XATTR_LEN(name_len);
-+      struct buffer_head *bh;
-+      int err, storage_size;
-+      struct ext3_iloc iloc;
-+      int free, min_offs;
-+      char *start, *end;
-+      
-+      if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+              return -ENOSPC;
-+
-+      err = ext3_get_inode_loc(inode, &iloc);
-+      if (err)
-+              return err;
-+      raw_inode = iloc.raw_inode;
-+      bh = iloc.bh;
-+
-+      storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+                              EXT3_GOOD_OLD_INODE_SIZE -
-+                              EXT3_I(inode)->i_extra_isize -
-+                              sizeof(__u32);
-+      start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+                      EXT3_I(inode)->i_extra_isize;
-+      if ((*(__u32*) start) != EXT3_XATTR_MAGIC) {
-+              /* inode had no attributes before */
-+              *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC);
-+      }
-+      start += sizeof(__u32);
-+      end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+      min_offs = storage_size;
-+      free = storage_size - sizeof(__u32);
-+
-+      last = (struct ext3_xattr_entry *) start;       
-+      while (!IS_LAST_ENTRY(last)) {
-+              next = EXT3_XATTR_NEXT(last);
-+              if (le32_to_cpu(last->e_value_size) > storage_size ||
-+                              (char *) next >= end) {
-+                      ext3_error(inode->i_sb, "ext3_xattr_ibody_set",
-+                              "inode %ld", inode->i_ino);
-+                      brelse(bh);
-+                      return -EIO;
-+              }
-+              
-+              if (last->e_value_size) {
-+                      int offs = le16_to_cpu(last->e_value_offs);
-+                      if (offs < min_offs)
-+                              min_offs = offs;
-+              }
-+              if (name_index == last->e_name_index &&
-+                      name_len == last->e_name_len &&
-+                      !memcmp(name, last->e_name, name_len))
-+                      here = last;
-+              else {
-+                      /* we calculate all but our attribute
-+                       * because it will be removed before changing */
-+                      free -= EXT3_XATTR_LEN(last->e_name_len);
-+                      free -= le32_to_cpu(last->e_value_size);
-+              }
-+              last = next;
-+      }
-+
-+      if (value && (esize + value_len > free)) {
-+              brelse(bh);
-+              return -ENOSPC;
-+      }
-+      
-+      err = ext3_reserve_inode_write(handle, inode, &iloc);
-+      if (err) {
-+              brelse(bh);     
-+              return err;
-+      }
-+
-+      if (here) {
-+              /* time to remove old value */
-+              struct ext3_xattr_entry *e;
-+              int size = le32_to_cpu(here->e_value_size);
-+              int border = le16_to_cpu(here->e_value_offs);
-+              char *src;
-+
-+              /* move tail */
-+              memmove(start + min_offs + size, start + min_offs,
-+                              border - min_offs);
-+
-+              /* recalculate offsets */
-+              e = (struct ext3_xattr_entry *) start;
-+              while (!IS_LAST_ENTRY(e)) {
-+                      struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e);
-+                      int offs = le16_to_cpu(e->e_value_offs);
-+                      if (offs < border)
-+                              e->e_value_offs =
-+                                      cpu_to_le16(offs + size);
-+                      e = next;
-+              }
-+              min_offs += size;
-+
-+              /* remove entry */
-+              border = EXT3_XATTR_LEN(here->e_name_len);
-+              src = (char *) here + EXT3_XATTR_LEN(here->e_name_len);
-+              size = (char *) last - src;
-+              if ((char *) here + size > end)
-+                      printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n",
-+                                      __FILE__, __LINE__, here, size, end);
-+              memmove(here, src, size);
-+              last = (struct ext3_xattr_entry *) ((char *) last - border);
-+              *((__u32 *) last) = 0;
-+      }
-+      
-+      if (value) {
-+              int offs = min_offs - value_len;
-+              /* use last to create new entry */
-+              last->e_name_len = strlen(name);
-+              last->e_name_index = name_index;
-+              last->e_value_offs = cpu_to_le16(offs);
-+              last->e_value_size = cpu_to_le32(value_len);
-+              last->e_hash = last->e_value_block = 0;
-+              memset(last->e_name, 0, esize);
-+              memcpy(last->e_name, name, last->e_name_len);
-+              if (start + offs + value_len > end)
-+                      printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n",
-+                                      __FILE__, __LINE__, start, offs,
-+                                      value_len, end);
-+              memcpy(start + offs, value, value_len);
-+              last = EXT3_XATTR_NEXT(last);
-+              *((__u32 *) last) = 0;
-+      }
-+      
-+      ext3_mark_iloc_dirty(handle, inode, &iloc);
-+      brelse(bh);
-+
-+      return 0;
-+}
-+
-+/*
-  * ext3_xattr_set()
-  *
-  * Create, replace or remove an extended attribute for this inode. Buffer
-@@ -583,6 +1067,101 @@ static void ext3_xattr_update_super_bloc
-  */
- int
- ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+              const char *name, void *value, size_t value_len, int flags)
-+{
-+      struct ext3_xattr_entry entry;
-+      int err, where = 0, found = 0, total;
-+      int free1 = -1, free2 = -1;
-+      int name_len;
-+      
-+      ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+                name_index, name, value, (long)value_len);
-+
-+      if (IS_RDONLY(inode))
-+              return -EROFS;
-+      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+              return -EPERM;
-+      if (value == NULL)
-+              value_len = 0;
-+      if (name == NULL)
-+              return -EINVAL;
-+      name_len = strlen(name);
-+      if (name_len > 255 || value_len > inode->i_sb->s_blocksize)
-+              return -ERANGE;
-+
-+      /* try to find attribute in inode body */
-+      err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
-+      if (err == 0) {
-+              /* found EA in inode */
-+              found = 1;
-+              where = 0;
-+      } else if (err == -ENOENT) {
-+              /* there is no such attribute in inode body */
-+              /* try to find attribute in dedicated block */
-+              err = ext3_xattr_block_find(inode, name_index, name,
-+                                              &entry, &free2);
-+              if (err != 0 && err != -ENOENT) {
-+                      /* not found EA in block */
-+                      goto finish;    
-+              } else if (err == 0) {
-+                      /* found EA in block */
-+                      where = 1;
-+                      found = 1;
-+              }
-+      } else
-+              goto finish;
-+
-+      /* check flags: may replace? may create ? */
-+      if (found && (flags & XATTR_CREATE)) {
-+              err = -EEXIST;
-+              goto finish;
-+      } else if (!found && (flags & XATTR_REPLACE)) {
-+              err = -ENODATA;
-+              goto finish;
-+      }
-+
-+      /* check if we have enough space to store attribute */
-+      total = EXT3_XATTR_LEN(strlen(name)) + value_len;
-+      if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) {
-+              /* have no enough space */
-+              err = -ENOSPC;
-+              goto finish;
-+      }
-+      
-+      /* time to remove attribute */
-+      if (found) {
-+              if (where == 0) {
-+                      /* EA is stored in inode body */
-+                      ext3_xattr_ibody_set(handle, inode, name_index, name,
-+                                      NULL, 0, flags);
-+              } else {
-+                      /* EA is stored in separated block */
-+                      ext3_xattr_block_set(handle, inode, name_index, name,
-+                                      NULL, 0, flags);
-+              }
-+      }
-+
-+      /* try to store EA in inode body */
-+      err = ext3_xattr_ibody_set(handle, inode, name_index, name,
-+                              value, value_len, flags);
-+      if (err) {
-+              /* can't store EA in inode body */
-+              /* try to store in block */
-+              err = ext3_xattr_block_set(handle, inode, name_index,
-+                                      name, value, value_len, flags); 
-+      }
-+
-+finish:       
-+      return err;
-+}
-+
-+/*
-+ * ext3_xattr_block_set()
-+ *
-+ * this routine add/remove/replace attribute in EA block
-+ */
-+int
-+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index,
-              const char *name, void *value, size_t value_len, int flags)
- {
-       struct super_block *sb = inode->i_sb;
-@@ -619,6 +1197,7 @@ ext3_xattr_set(handle_t *handle, struct 
-       name_len = strlen(name);
-       if (name_len > 255 || value_len > sb->s_blocksize)
-               return -ERANGE;
-+
-       ext3_xattr_lock();
-       if (EXT3_I(inode)->i_file_acl) {
-@@ -819,6 +1398,7 @@ cleanup:
-       brelse(bh);
-       if (!(bh && header == HDR(bh)))
-               kfree(header);
-+
-       ext3_xattr_unlock();
-       return error;
---- linux-2.4.18-chaos/include/linux/ext3_fs.h~ext3-ea-in-inode-2.4.18-chaos   2003-10-08 10:38:03.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/include/linux/ext3_fs.h  2003-10-08 15:08:45.000000000 +0400
-@@ -264,6 +264,8 @@ struct ext3_inode {
-                       __u32   m_i_reserved2[2];
-               } masix2;
-       } osd2;                         /* OS dependent 2 */
-+      __u16   i_extra_isize;
-+      __u16   i_pad1;
- };
- #define i_size_high   i_dir_acl
---- linux-2.4.18-chaos/include/linux/ext3_fs_i.h~ext3-ea-in-inode-2.4.18-chaos 2003-10-08 10:38:03.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/include/linux/ext3_fs_i.h        2003-10-08 15:08:45.000000000 +0400
-@@ -62,6 +62,9 @@ struct ext3_inode_info {
-        */
-       loff_t  i_disksize;
-+      /* on-disk additional length */
-+      __u16 i_extra_isize;
-+
-       /*
-        * truncate_sem is for serialising ext3_truncate() against
-        * ext3_getblock().  In the 2.4 ext2 design, great chunks of inode's
---- linux-2.4.18-chaos/fs/ext3/super.c~ext3-ea-in-inode-2.4.18-chaos   2003-10-08 10:38:03.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/super.c  2003-10-08 15:08:45.000000000 +0400
-@@ -1292,7 +1292,9 @@ struct super_block * ext3_read_super (st
-       } else {
-               sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
-               sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
--              if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) {
-+              if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
-+                  (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
-+                  (sbi->s_inode_size > blocksize)) {
-                       printk (KERN_ERR
-                               "EXT3-fs: unsupported inode size: %d\n",
-                               sbi->s_inode_size);
-
-_
diff --git a/lustre/kernel_patches/patches/ext3-extents-2.4.18-chaos-pdirops.patch b/lustre/kernel_patches/patches/ext3-extents-2.4.18-chaos-pdirops.patch
deleted file mode 100644 (file)
index 592af93..0000000
+++ /dev/null
@@ -1,1891 +0,0 @@
- fs/ext3/Makefile           |    3 
- fs/ext3/extents.c          | 1624 +++++++++++++++++++++++++++++++++++++++++++++
- fs/ext3/ialloc.c           |    4 
- fs/ext3/inode.c            |   30 
- fs/ext3/super.c            |    8 
- include/linux/ext3_fs.h    |   18 
- include/linux/ext3_fs_i.h  |    4 
- include/linux/ext3_fs_sb.h |   10 
- 8 files changed, 1693 insertions(+), 8 deletions(-)
-
---- /dev/null  2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.18-chaos-pdirops-alexey/fs/ext3/extents.c        2003-09-23 18:09:30.000000000 +0400
-@@ -0,0 +1,1624 @@
-+/*
-+ *
-+ * linux/fs/ext3/extents.c
-+ *
-+ * Extents support for EXT3
-+ *
-+ * 07/08/2003    Alex Tomas <bzzz@tmi.comex.ru>
-+ * 
-+ * TODO:
-+ *   - ext3*_error() should be used in some situations
-+ *   - find_goal() [to be tested and improved]
-+ *   - error handling
-+ *   - we could leak allocated block in some error cases
-+ *   - quick search for index/leaf in ext3_ext_find_extent()
-+ *   - tree reduction
-+ *   - cache last found extent
-+ *   - arch-independent
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/time.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/jbd.h>
-+#include <linux/smp_lock.h>
-+#include <linux/highuid.h>
-+#include <linux/pagemap.h>
-+#include <linux/quotaops.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+#include <linux/locks.h>
-+
-+/*
-+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
-+ * become very little, so index split, in-depth growing and
-+ * other hard changes happens much more often
-+ * this is for debug purposes only
-+ */
-+#define AGRESSIVE_TEST_
-+
-+/*
-+ * if EXT_DEBUG defined you can use 'extdebug' mount option
-+ * to get lots of info what's going on
-+ */
-+#define EXT_DEBUG
-+#ifdef EXT_DEBUG
-+#define ext_debug(inode,fmt,a...)             \
-+do {                                          \
-+      if (test_opt((inode)->i_sb, EXTDEBUG))  \
-+              printk(fmt, ##a);               \
-+} while (0);
-+#else
-+#define ext_debug(inode,fmt,a...)
-+#endif
-+
-+#define EXT3_ALLOC_NEEDED     2       /* block bitmap + group descriptor */
-+
-+/*
-+ * ext3_inode has i_block array (total 60 bytes)
-+ * first 4 bytes are used to store:
-+ *  - tree depth (0 mean there is no tree yet. all extents in the inode)
-+ *  - number of alive extents in the inode
-+ */
-+
-+/*
-+ * this is extent on-disk structure
-+ * it's used at the bottom of the tree
-+ */
-+struct ext3_extent {
-+      __u32   e_block;        /* first logical block extent covers */
-+      __u32   e_start;        /* first physical block extents lives */
-+      __u32   e_num;          /* number of blocks covered by extent */
-+};
-+
-+/*
-+ * this is index on-disk structure
-+ * it's used at all the levels, but the bottom
-+ */
-+struct ext3_extent_idx {
-+      __u32   e_block;        /* index covers logical blocks from 'block' */
-+      __u32   e_leaf;         /* pointer to the physical block of the next *
-+                               * level. leaf or next index could bet here */
-+};
-+
-+/*
-+ * each block (leaves and indexes), even inode-stored has header
-+ */
-+struct ext3_extent_header {   
-+      __u16   e_num;          /* number of valid entries */
-+      __u16   e_max;          /* capacity of store in entries */
-+};
-+
-+/*
-+ * array of ext3_ext_path contains path to some extent
-+ * creation/lookup routines use it for traversal/splitting/etc
-+ * truncate uses it to simulate recursive walking
-+ */
-+struct ext3_ext_path {
-+      __u32                           p_block;
-+      __u16                           p_depth;
-+      struct ext3_extent              *p_ext;
-+      struct ext3_extent_idx          *p_idx;
-+      struct ext3_extent_header       *p_hdr;
-+      struct buffer_head              *p_bh;
-+};
-+
-+#define EXT_FIRST_EXTENT(__hdr__) \
-+      ((struct ext3_extent *) (((char *) (__hdr__)) +         \
-+                               sizeof(struct ext3_extent_header)))
-+#define EXT_FIRST_INDEX(__hdr__) \
-+      ((struct ext3_extent_idx *) (((char *) (__hdr__)) +     \
-+                                   sizeof(struct ext3_extent_header)))
-+#define EXT_HAS_FREE_INDEX(__path__) \
-+      ((__path__)->p_hdr->e_num < (__path__)->p_hdr->e_max)
-+#define EXT_LAST_EXTENT(__hdr__) \
-+      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->e_num - 1)
-+#define EXT_LAST_INDEX(__hdr__) \
-+      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->e_num - 1)
-+#define EXT_MAX_EXTENT(__hdr__) \
-+      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->e_max - 1)
-+#define EXT_MAX_INDEX(__hdr__) \
-+      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->e_max - 1)
-+
-+
-+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
-+
-+/*
-+ * could return:
-+ *  - EROFS
-+ *  - ENOMEM
-+ */
-+static int ext3_ext_get_access(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path)
-+{
-+      if (path->p_bh) {
-+              /* path points to block */
-+              return ext3_journal_get_write_access(handle, path->p_bh);
-+      }
-+
-+      /* path points to leaf/index in inode body */
-+      return 0;
-+}
-+
-+/*
-+ * could return:
-+ *  - EROFS
-+ *  - ENOMEM
-+ *  - EIO
-+ */
-+static int ext3_ext_dirty(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path)
-+{
-+      if (path->p_bh) {
-+              /* path points to block */
-+              return ext3_journal_dirty_metadata(handle, path->p_bh);
-+      }
-+
-+      /* path points to leaf/index in inode body */
-+      return ext3_mark_inode_dirty(handle, inode);
-+}
-+
-+static inline int ext3_ext_space_block(struct inode *inode)
-+{
-+      int size;
-+
-+      size = (inode->i_sb->s_blocksize - sizeof(struct ext3_extent_header))
-+              / sizeof(struct ext3_extent);
-+#ifdef AGRESSIVE_TEST
-+      size = 6; /* FIXME: for debug, remove this line */
-+#endif
-+      return size;
-+}
-+
-+static inline int ext3_ext_space_inode(struct inode *inode)
-+{
-+      int size;
-+
-+      size = (sizeof(EXT3_I(inode)->i_data) -
-+                      sizeof(struct ext3_extent_header))
-+                      / sizeof(struct ext3_extent);
-+#ifdef AGRESSIVE_TEST
-+      size = 3; /* FIXME: for debug, remove this line */
-+#endif
-+      return size;
-+}
-+
-+static inline int ext3_ext_space_inode_idx(struct inode *inode)
-+{
-+      int size;
-+
-+      size = (sizeof(EXT3_I(inode)->i_data) -
-+                      sizeof(struct ext3_extent_header))
-+                      / sizeof(struct ext3_extent_idx);
-+#ifdef AGRESSIVE_TEST
-+      size = 4; /* FIXME: for debug, remove this line */
-+#endif
-+      return size;
-+}
-+
-+static void ext3_ext_show_path(struct inode *inode, struct ext3_ext_path *path)
-+{
-+      int k, l = path->p_depth;
-+
-+      ext_debug(inode, "path:");
-+      for (k = 0; k <= l; k++, path++) {
-+              if (path->p_idx) {
-+                      ext_debug(inode, "  %d->%d", path->p_idx->e_block,
-+                                      path->p_idx->e_leaf);
-+              } else if (path->p_ext) {
-+                      ext_debug(inode, "  %d:%d:%d",
-+                                      path->p_ext->e_block,
-+                                      path->p_ext->e_start,
-+                                      path->p_ext->e_num);
-+              } else
-+                      ext_debug(inode, "  []");
-+      }
-+      ext_debug(inode, "\n");
-+}
-+
-+static void ext3_ext_show_leaf(struct inode *inode, struct ext3_ext_path *path)
-+{
-+      int depth = EXT3_I(inode)->i_depth;
-+      struct ext3_extent_header *eh = path[depth].p_hdr;
-+      struct ext3_extent *ex = EXT_FIRST_EXTENT(eh);
-+      int i;
-+
-+      for (i = 0; i < eh->e_num; i++, ex++) {
-+              ext_debug(inode, "%d:%d:%d ",
-+                              ex->e_block, ex->e_start, ex->e_num);
-+      }
-+      ext_debug(inode, "\n");
-+}
-+
-+static void ext3_ext_drop_refs(struct inode *inode, struct ext3_ext_path *path)
-+{
-+      int depth = path->p_depth;
-+      int i;
-+
-+      for (i = 0; i <= depth; i++, path++)
-+              if (path->p_bh) {
-+                      brelse(path->p_bh);
-+                      path->p_bh = NULL;
-+              }
-+}
-+
-+static int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path)
-+{
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      unsigned long bg_start;
-+      unsigned long colour;
-+      int depth;
-+      
-+      if (path) {
-+              depth = path->p_depth;
-+              /* try to find previous block */
-+              if (path[depth].p_ext)
-+                      return path[depth].p_ext->e_start +
-+                              path[depth].p_ext->e_num - 1;
-+              
-+              /* it looks index is empty
-+               * try to find starting from index itself */
-+              if (path[depth].p_bh)
-+                      return path[depth].p_bh->b_blocknr;
-+      }
-+
-+      /* OK. use inode's group */
-+      bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+              le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
-+      colour = (current->pid % 16) *
-+                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-+      return bg_start + colour;
-+}
-+
-+static struct ext3_ext_path *
-+ext3_ext_find_extent(struct inode *inode, int block, struct ext3_ext_path *path)
-+{
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      struct ext3_extent_header *eh = (void *) ei->i_data;
-+      struct ext3_extent_idx *ix;
-+      struct buffer_head *bh;
-+      struct ext3_extent *ex;
-+      int depth, i, k, ppos = 0, prev = 0;
-+      
-+      eh = (struct ext3_extent_header *) ei->i_data;
-+
-+      /* initialize capacity of leaf in inode for first time */
-+      if (eh->e_max == 0)
-+              eh->e_max = ext3_ext_space_inode(inode);
-+      i = depth = ei->i_depth;
-+      EXT_ASSERT(i == 0 || eh->e_num > 0);
-+      
-+      /* account possible depth increase */
-+      if (!path) {
-+              path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+                              GFP_NOFS);
-+              if (!path)
-+                      return ERR_PTR(-ENOMEM);
-+      }
-+      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
-+
-+      /* walk through the tree */
-+      while (i) {
-+              ext_debug(inode, "depth %d: num %d, max %d\n",
-+                              ppos, eh->e_num, eh->e_max);
-+              ix = EXT_FIRST_INDEX(eh);
-+              if (eh->e_num) {
-+                      EXT_ASSERT(prev == 0 || ix->e_block == prev);
-+                      path[ppos].p_idx = ix;
-+              }
-+              EXT_ASSERT(eh->e_num <= eh->e_max);
-+              for (k = 0; k < eh->e_num; k++, ix++) {
-+                      ext_debug(inode, "index: %d -> %d\n",
-+                                      ix->e_block, ix->e_leaf);
-+                      EXT_ASSERT((k == 0 && prev <= (int)ix->e_block) ||
-+                                      (k > 0 && prev < (int)ix->e_block));
-+                      if (block < ix->e_block)
-+                              break;
-+                      prev = ix->e_block;
-+                      path[ppos].p_idx = ix;
-+              }
-+              path[ppos].p_block = path[ppos].p_idx->e_leaf;
-+              path[ppos].p_depth = i;
-+              path[ppos].p_hdr = eh;
-+              path[ppos].p_ext = NULL;
-+
-+              bh = sb_bread(inode->i_sb, path[ppos].p_block);
-+              if (!bh) {
-+                      ext3_ext_drop_refs(inode, path);
-+                      kfree(path);
-+                      return ERR_PTR(-EIO);
-+              }
-+              eh = (struct ext3_extent_header *) bh->b_data;
-+              ppos++;
-+              EXT_ASSERT(ppos <= depth);
-+              path[ppos].p_bh = bh;
-+              i--;
-+      }
-+
-+      path[ppos].p_depth = i;
-+      path[ppos].p_hdr = eh;
-+      path[ppos].p_ext = NULL;
-+      
-+      /* find extent */
-+      ex = EXT_FIRST_EXTENT(eh);
-+      if (eh->e_num)
-+              path[ppos].p_ext = ex;
-+      EXT_ASSERT(eh->e_num <= eh->e_max);
-+      for (k = 0; k < eh->e_num; k++, ex++) {
-+              EXT_ASSERT(ex->e_num < EXT3_BLOCKS_PER_GROUP(inode->i_sb));
-+              EXT_ASSERT((k == 0 && prev <= (int)ex->e_block) ||
-+                              (k > 0 && prev < (int)ex->e_block));
-+              if (block < ex->e_block) 
-+                      break;
-+              prev = ex->e_block;
-+              path[ppos].p_ext = ex;
-+      }
-+
-+      ext3_ext_show_path(inode, path);
-+
-+      return path;
-+}
-+
-+static void ext3_ext_check_boundary(struct inode *inode,
-+                                      struct ext3_ext_path *curp,
-+                                      void *addr, int len)
-+{
-+      void *end;
-+
-+      if (!len)
-+              return;
-+      if (curp->p_bh)
-+              end = (void *) curp->p_hdr + inode->i_sb->s_blocksize;
-+      else
-+              end = (void *) curp->p_hdr + sizeof(EXT3_I(inode)->i_data);
-+      if (((unsigned long) addr) + len > (unsigned long) end) {
-+              printk("overflow! 0x%p > 0x%p\n", addr + len, end);
-+              BUG();
-+      }
-+      if ((unsigned long) addr < (unsigned long) curp->p_hdr) {
-+              printk("underflow! 0x%p < 0x%p\n", addr, curp->p_hdr);
-+              BUG();
-+      }
-+}
-+
-+/*
-+ * insert new index [logical;ptr] into the block at cupr
-+ * it check where to insert: before curp or after curp
-+ */
-+static int ext3_ext_insert_index(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *curp, int logical,
-+                              int ptr)
-+{
-+      struct ext3_extent_idx *ix;
-+      int len, err;
-+
-+      if ((err = ext3_ext_get_access(handle, inode, curp)))
-+              return err;
-+
-+      EXT_ASSERT(logical != curp->p_idx->e_block);
-+      len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
-+      if (logical > curp->p_idx->e_block) {
-+              /* insert after */
-+              len = (len - 1) * sizeof(struct ext3_extent_idx);
-+              len = len < 0 ? 0 : len;
-+              ext_debug(inode, "insert new index %d after: %d. "
-+                              "move %d from 0x%p to 0x%p\n",
-+                              logical, ptr, len,
-+                              (curp->p_idx + 1), (curp->p_idx + 2));
-+
-+              ext3_ext_check_boundary(inode, curp, curp->p_idx + 2, len);
-+              memmove(curp->p_idx + 2, curp->p_idx + 1, len);
-+              ix = curp->p_idx + 1;
-+      } else {
-+              /* insert before */
-+              len = len * sizeof(struct ext3_extent_idx);
-+              len = len < 0 ? 0 : len;
-+              ext_debug(inode, "insert new index %d before: %d. "
-+                              "move %d from 0x%p to 0x%p\n",
-+                              logical, ptr, len,
-+                              curp->p_idx, (curp->p_idx + 1));
-+
-+              ext3_ext_check_boundary(inode, curp, curp->p_idx + 1, len);
-+              memmove(curp->p_idx + 1, curp->p_idx, len);
-+              ix = curp->p_idx;
-+      }
-+
-+      ix->e_block = logical;
-+      ix->e_leaf = ptr;
-+      curp->p_hdr->e_num++;
-+
-+      err = ext3_ext_dirty(handle, inode, curp);
-+      ext3_std_error(inode->i_sb, err);
-+
-+      return err;
-+}
-+
-+/*
-+ * routine inserts new subtree into the path, using free index entry
-+ * at depth 'at:
-+ *  - allocates all needed blocks (new leaf and all intermediate index blocks)
-+ *  - makes decision where to split
-+ *  - moves remaining extens and index entries (right to the split point)
-+ *    into the newly allocated blocks
-+ *  - initialize subtree
-+ */
-+static int ext3_ext_split(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path,
-+                              struct ext3_extent *newext, int at)
-+{
-+      struct buffer_head *bh = NULL;
-+      int depth = EXT3_I(inode)->i_depth;
-+      struct ext3_extent_header *neh;
-+      struct ext3_extent_idx *fidx;
-+      struct ext3_extent *ex;
-+      int i = at, k, m, a;
-+      long newblock, oldblock, border;
-+      int *ablocks = NULL; /* array of allocated blocks */
-+      int err = 0;
-+
-+      /* make decision: where to split? */
-+      /* FIXME: now desicion is simplest: at current extent */
-+
-+      /* if current leaf will be splitted, then we should use 
-+       * border from split point */
-+      
-+      if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
-+              border = path[depth].p_ext[1].e_block;
-+              ext_debug(inode, "leaf will be splitted."
-+                              " next leaf starts at %d\n",
-+                              (int)border);
-+      } else {
-+              border = newext->e_block;
-+              ext_debug(inode, "leaf will be added."
-+                              " next leaf starts at %d\n",
-+                              (int)border);
-+      }
-+
-+      /* 
-+       * if error occurs, then we break processing
-+       * and turn filesystem read-only. so, index won't
-+       * be inserted and tree will be in consistent
-+       * state. next mount will repair buffers too
-+       */
-+
-+      /*
-+       * get array to track all allocated blocks
-+       * we need this to handle errors and free blocks
-+       * upon them
-+       */
-+      ablocks = kmalloc(sizeof(long) * depth, GFP_NOFS);
-+      if (!ablocks)
-+              return -ENOMEM;
-+      memset(ablocks, 0, sizeof(long) * depth);
-+
-+      /* allocate all needed blocks */
-+      ext_debug(inode, "allocate %d blocks for indexes/leaf\n", depth - at);
-+      newblock = 0; /* FIXME: something more sophisticated needed here */ 
-+      for (a = 0; newext->e_num > 0 && a < depth - at; a++) {
-+              newblock = ablocks[a] = newext->e_start++;
-+              newext->e_num--;
-+      }
-+      for (; a < depth - at; a++) {
-+              newblock = ext3_new_block(handle, inode,
-+                                              newblock + 1, 0, 0, &err);
-+              if (newblock == 0)
-+                      goto cleanup;
-+              ablocks[a] = newblock;
-+      }
-+
-+      /* initialize new leaf */
-+      newblock = ablocks[--a];
-+      EXT_ASSERT(newblock);
-+      bh = sb_getblk(inode->i_sb, newblock);
-+      if (!bh) {
-+              err = -EIO;
-+              goto cleanup;
-+      }
-+      lock_buffer(bh);
-+
-+      if ((err = ext3_journal_get_create_access(handle, bh)))
-+              goto cleanup;
-+
-+      neh = (struct ext3_extent_header *) bh->b_data;
-+      neh->e_num = 0;
-+      neh->e_max = ext3_ext_space_block(inode);
-+      ex = EXT_FIRST_EXTENT(neh);
-+
-+      /* move remain of path[depth] to the new leaf */
-+      EXT_ASSERT(path[depth].p_hdr->e_num ==
-+                      path[depth].p_hdr->e_max);
-+      /* start copy from next extent */
-+      /* TODO: we could do it by single memmove */
-+      m = 0;
-+      path[depth].p_ext++;
-+      while (path[depth].p_ext <=
-+                      EXT_MAX_EXTENT(path[depth].p_hdr)) {
-+              ext_debug(inode, "move %d:%d:%d in new leaf\n",
-+                              path[depth].p_ext->e_block,
-+                              path[depth].p_ext->e_start,
-+                              path[depth].p_ext->e_num);
-+              memmove(ex++, path[depth].p_ext++,
-+                              sizeof(struct ext3_extent));
-+              neh->e_num++;
-+              m++;
-+      }
-+      mark_buffer_uptodate(bh, 1);
-+      unlock_buffer(bh);
-+
-+      if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+              goto cleanup;   
-+      brelse(bh);
-+      bh = NULL;
-+
-+      /* correct old leaf */
-+      if (m) {
-+              if ((err = ext3_ext_get_access(handle, inode, path)))
-+                      goto cleanup;
-+              path[depth].p_hdr->e_num -= m;
-+              if ((err = ext3_ext_dirty(handle, inode, path)))
-+                      goto cleanup;
-+              
-+      }
-+
-+      /* create intermediate indexes */
-+      k = depth - at - 1;
-+      EXT_ASSERT(k >= 0);
-+      if (k)
-+              ext_debug(inode,
-+                              "create %d intermediate indices\n", k);
-+      /* insert new index into current index block */
-+      /* current depth stored in i var */
-+      i = depth - 1;
-+      while (k--) {
-+              oldblock = newblock;
-+              newblock = ablocks[--a];
-+              bh = sb_getblk(inode->i_sb, newblock);
-+              if (!bh) {
-+                      err = -EIO;
-+                      goto cleanup;
-+              }
-+              lock_buffer(bh);
-+
-+              if ((err = ext3_journal_get_create_access(handle, bh)))
-+                      goto cleanup;
-+
-+              neh = (struct ext3_extent_header *) bh->b_data;
-+              neh->e_num = 1;
-+              neh->e_max = ext3_ext_space_block(inode);
-+              fidx = EXT_FIRST_INDEX(neh);
-+              fidx->e_block = border;
-+              fidx->e_leaf = oldblock;
-+
-+              ext_debug(inode,
-+                              "int.index at %d (block %u): %d -> %d\n",
-+                              i, (unsigned) newblock,
-+                              (int) border,
-+                              (int) oldblock);
-+              /* copy indexes */
-+              m = 0;
-+              path[i].p_idx++;
-+              ext_debug(inode, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+                              EXT_MAX_INDEX(path[i].p_hdr));
-+              EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+                              EXT_LAST_INDEX(path[i].p_hdr));
-+              while (path[i].p_idx <=
-+                              EXT_MAX_INDEX(path[i].p_hdr)) {
-+                      ext_debug(inode, "%d: move %d:%d in new index\n",
-+                                      i, path[i].p_idx->e_block,
-+                                      path[i].p_idx->e_leaf);
-+                      memmove(++fidx, path[i].p_idx++,
-+                                      sizeof(struct ext3_extent_idx));
-+                      neh->e_num++;
-+                      m++;
-+              }
-+
-+              mark_buffer_uptodate(bh, 1);
-+              unlock_buffer(bh);
-+
-+              if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+                      goto cleanup;
-+              brelse(bh);
-+              bh = NULL;
-+
-+              /* correct old index */
-+              if (m) {
-+                      err = ext3_ext_get_access(handle,inode,path+i);
-+                      if (err)
-+                              goto cleanup;
-+                      path[i].p_hdr->e_num -= m;
-+                      err = ext3_ext_dirty(handle, inode, path + i);
-+                      if (err)
-+                              goto cleanup;
-+              }
-+
-+              i--;
-+      }
-+
-+      /* insert new index */
-+      if (!err)
-+              err = ext3_ext_insert_index(handle, inode, path + at,
-+                                              border, newblock);
-+
-+cleanup:
-+      if (bh) {
-+              if (buffer_locked(bh))
-+                      unlock_buffer(bh);
-+              brelse(bh);
-+      }
-+
-+      if (err) {
-+              /* free all allocated blocks in error case */
-+              for (i = 0; i < depth; i++)
-+                      if (!ablocks[i])
-+                              continue;
-+                      ext3_free_blocks(handle, inode, ablocks[i], 1);
-+      }
-+      kfree(ablocks);
-+
-+      return err;
-+}
-+
-+/*
-+ * routine implements tree growing procedure:
-+ *  - allocates new block
-+ *  - moves top-level data (index block or leaf) into the new block
-+ *  - initialize new top-level, creating index that points to the
-+ *    just created block
-+ */
-+static int ext3_ext_grow_indepth(handle_t *handle, struct inode *inode,
-+                                      struct ext3_ext_path *path,
-+                                      struct ext3_extent *newext)
-+{
-+      struct buffer_head *bh;
-+      struct ext3_ext_path *curp = path;
-+      struct ext3_extent_header *neh;
-+      struct ext3_extent_idx *fidx;
-+      int len, err = 0;
-+      long newblock;
-+
-+      /*
-+       * use already allocated by the called block for new root block
-+       */
-+      newblock = newext->e_start++;
-+      if (newext->e_num == 0) {
-+              /* 
-+               * FIXME: if this may happen, then we have to handle
-+               * possible error and free allocated block
-+               */
-+              printk("grow_indepth with zero blocks\n");
-+              newblock = ext3_new_block(handle, inode,
-+                                              newblock, 0, 0, &err);
-+      } else
-+              newext->e_num--;
-+      
-+      bh = sb_getblk(inode->i_sb, newblock);
-+      if (!bh) {
-+              err = -EIO;
-+              ext3_std_error(inode->i_sb, err);
-+              return err;
-+      }
-+      lock_buffer(bh);
-+
-+      if ((err = ext3_journal_get_create_access(handle, bh))) {
-+              unlock_buffer(bh);
-+              goto out;       
-+      }
-+
-+      /* move top-level index/leaf into new block */
-+      len = sizeof(struct ext3_extent_header) +
-+              sizeof(struct ext3_extent) * curp->p_hdr->e_max;
-+      EXT_ASSERT(len >= 0 && len < 4096);
-+      memmove(bh->b_data, curp->p_hdr, len);
-+
-+      /* set size of new block */
-+      neh = (struct ext3_extent_header *) bh->b_data;
-+      neh->e_max = ext3_ext_space_block(inode);
-+      mark_buffer_uptodate(bh, 1);
-+      unlock_buffer(bh);
-+
-+      if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+              goto out;
-+
-+      /* create index in new top-level index: num,max,pointer */
-+      if ((err = ext3_ext_get_access(handle, inode, curp)))
-+              goto out;
-+
-+      curp->p_hdr->e_max = ext3_ext_space_inode_idx(inode);
-+      curp->p_hdr->e_num = 1;
-+      curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
-+      curp->p_idx->e_block = EXT_FIRST_EXTENT(path[0].p_hdr)->e_block;
-+      curp->p_idx->e_leaf = newblock;
-+
-+      neh = (struct ext3_extent_header *) EXT3_I(inode)->i_data;
-+      fidx = EXT_FIRST_INDEX(neh);
-+      ext_debug(inode, "new root: num %d(%d), lblock %d, ptr %d\n",
-+                      neh->e_num, neh->e_max, fidx->e_block, fidx->e_leaf); 
-+
-+      EXT3_I(inode)->i_depth++;
-+      err = ext3_ext_dirty(handle, inode, curp);
-+out:
-+      brelse(bh);
-+
-+      return err;
-+}
-+
-+/*
-+ * routine finds empty index and adds new leaf. if no free index found
-+ * then it requests in-depth growing
-+ */
-+static int ext3_ext_create_new_leaf(handle_t *handle, struct inode *inode,
-+                                      struct ext3_ext_path *path,
-+                                      struct ext3_extent *newext)
-+{
-+      long newblock = newext->e_start;
-+      struct ext3_ext_path *curp;
-+      int depth, i, err = 0;
-+
-+repeat:
-+      i = depth = EXT3_I(inode)->i_depth;
-+      
-+      /* walk up to the tree and look for free index entry */
-+      curp = path + depth;
-+      while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
-+              i--;
-+              curp--;
-+      }
-+
-+      /* we use already allocated block for index block
-+       * so, subsequent data blocks should be contigoues */
-+      if (EXT_HAS_FREE_INDEX(curp)) {
-+              /* if we found index with free entry, then use that
-+               * entry: create all needed subtree and add new leaf */
-+              err = ext3_ext_split(handle, inode, path, newext, i);
-+
-+              /* refill path */
-+              ext3_ext_drop_refs(inode, path);
-+              path = ext3_ext_find_extent(inode, newext->e_block, path);
-+              if (IS_ERR(path))
-+                      err = PTR_ERR(path);
-+      } else {
-+              /* tree is full, time to grow in depth */
-+              err = ext3_ext_grow_indepth(handle, inode, path, newext);
-+
-+              /* refill path */
-+              ext3_ext_drop_refs(inode, path);
-+              path = ext3_ext_find_extent(inode, newext->e_block, path);
-+              if (IS_ERR(path))
-+                      err = PTR_ERR(path);
-+      
-+              /*
-+               * only first (depth 0 -> 1) produces free space
-+               * in all other cases we have to split growed tree
-+               */
-+              depth = EXT3_I(inode)->i_depth;
-+              if (path[depth].p_hdr->e_num == path[depth].p_hdr->e_max) {
-+                      /* now we need split */
-+                      goto repeat;
-+              }
-+      }
-+
-+      if (err)
-+              return err;
-+
-+      /*
-+       * probably we've used some blocks from extent
-+       * let's allocate new block for it
-+       */
-+      if (newext->e_num == 0 && !err) {
-+              newext->e_start =
-+                      ext3_new_block(handle, inode, newblock,
-+                                      0, 0, &err);
-+              if (newext->e_start != 0)
-+                      newext->e_num = 1;
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * returns next allocated block or 0xffffffff
-+ * NOTE: it consider block number from index entry as
-+ * allocated block. thus, index entries have to be consistent
-+ * with leafs
-+ */
-+static inline unsigned ext3_ext_next_allocated_block(struct inode *inode,
-+                                               struct ext3_ext_path *path)
-+{
-+      int depth;
-+
-+      EXT_ASSERT(path != NULL);
-+      depth = path->p_depth;
-+
-+      if (depth == 0 && path->p_ext == NULL)
-+              return 0xffffffff;
-+
-+      /* FIXME: what if index isn't full ?! */
-+      while (depth >= 0) {
-+              if (depth == path->p_depth) {
-+                      /* leaf */
-+                      if (path[depth].p_ext !=
-+                                      EXT_LAST_EXTENT(path[depth].p_hdr))
-+                              return path[depth].p_ext[1].e_block;
-+              } else {
-+                      /* index */
-+                      if (path[depth].p_idx !=
-+                                      EXT_LAST_INDEX(path[depth].p_hdr))
-+                              return path[depth].p_idx[1].e_block;
-+              }
-+              depth--;        
-+      }
-+
-+      return 0xffffffff;
-+}
-+
-+/*
-+ * returns first allocated block from next leaf or 0xffffffff
-+ */
-+static unsigned ext3_ext_next_leaf_block(struct inode *inode,
-+                                               struct ext3_ext_path *path)
-+{
-+      int depth;
-+
-+      EXT_ASSERT(path != NULL);
-+      depth = path->p_depth;
-+
-+      /* zero-tree has no leaf blocks at all */
-+      if (depth == 0)
-+              return 0xffffffff;
-+
-+      /* go to index block */
-+      depth--;
-+      
-+      while (depth >= 0) {
-+              if (path[depth].p_idx !=
-+                              EXT_LAST_INDEX(path[depth].p_hdr))
-+                      return path[depth].p_idx[1].e_block;
-+              depth--;        
-+      }
-+
-+      return 0xffffffff;
-+}
-+
-+/*
-+ * if leaf gets modified and modified extent is first in the leaf
-+ * then we have to correct all indexes above
-+ * TODO: do we need to correct tree in all cases?
-+ */
-+int ext3_ext_correct_indexes(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path)
-+{
-+      int depth = EXT3_I(inode)->i_depth;     
-+      struct ext3_extent_header *eh;
-+      struct ext3_extent *ex;
-+      long border;
-+      int k, err = 0;
-+      
-+      eh = path[depth].p_hdr;
-+      ex = path[depth].p_ext;
-+
-+      EXT_ASSERT(ex);
-+      EXT_ASSERT(eh);
-+      
-+      if (depth == 0) {
-+              /* there is no tree at all */
-+              return 0;
-+      }
-+      
-+      if (ex != EXT_FIRST_EXTENT(eh)) {
-+              /* we correct tree if first leaf got modified only */
-+              return 0;
-+      }
-+      
-+      /*
-+       * TODO: we need correction if border is smaller then current one
-+       */
-+      k = depth - 1;
-+      border = path[depth].p_ext->e_block;
-+      if ((err = ext3_ext_get_access(handle, inode, path + k)))
-+              return err;
-+      path[k].p_idx->e_block = border;
-+      if ((err = ext3_ext_dirty(handle, inode, path + k)))
-+              return err;
-+
-+      while (k--) {
-+              /* change all left-side indexes */
-+              if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
-+                      break;
-+              if ((err = ext3_ext_get_access(handle, inode, path + k)))
-+                      break;
-+              path[k].p_idx->e_block = border;
-+              if ((err = ext3_ext_dirty(handle, inode, path + k)))
-+                      break;
-+      }
-+
-+      return err;
-+}
-+
-+/*
-+ * this routine tries to merge requsted extent into the existing
-+ * extent or inserts requested extent as new one into the tree,
-+ * creating new leaf in no-space case
-+ */
-+int ext3_ext_insert_extent(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path,
-+                              struct ext3_extent *newext)
-+{
-+      int depth, len;
-+      struct ext3_extent_header * eh;
-+      struct ext3_extent *ex;
-+      struct ext3_extent *nearex; /* nearest extent */
-+      struct ext3_ext_path *npath = NULL;
-+      int err;
-+
-+      depth = EXT3_I(inode)->i_depth; 
-+      if ((ex = path[depth].p_ext)) {
-+              /* try to insert block into found extent and return */
-+              if (ex->e_block + ex->e_num == newext->e_block &&
-+                              ex->e_start + ex->e_num == newext->e_start) {
-+#ifdef AGRESSIVE_TEST
-+                      if (ex->e_num >= 2)
-+                              goto repeat;
-+#endif
-+                      if ((err = ext3_ext_get_access(handle, inode,
-+                                                      path + depth)))
-+                              return err;
-+                      ext_debug(inode, "append %d block to %d:%d (from %d)\n",
-+                                      newext->e_num, ex->e_block, ex->e_num,
-+                                      ex->e_start);
-+                      ex->e_num += newext->e_num;
-+                      err = ext3_ext_dirty(handle, inode, path + depth);
-+                      return err;
-+              }
-+      }
-+
-+repeat:
-+      depth = EXT3_I(inode)->i_depth; 
-+      eh = path[depth].p_hdr;
-+      if (eh->e_num == eh->e_max) {
-+              /* probably next leaf has space for us? */
-+              int next = ext3_ext_next_leaf_block(inode, path);
-+              if (next != 0xffffffff) {
-+                      ext_debug(inode, "next leaf block - %d\n", next);
-+                      EXT_ASSERT(!npath);
-+                      npath = ext3_ext_find_extent(inode, next, NULL);
-+                      if (IS_ERR(npath))
-+                              return PTR_ERR(npath);
-+                      EXT_ASSERT(npath->p_depth == path->p_depth);
-+                      eh = npath[depth].p_hdr;
-+                      if (eh->e_num < eh->e_max) {
-+                              ext_debug(inode,
-+                                              "next leaf has free ext(%d)\n",
-+                                              eh->e_num);
-+                              path = npath;
-+                              goto repeat;
-+                      }
-+                      ext_debug(inode, "next leaf hasno free space(%d,%d)\n",
-+                                      eh->e_num, eh->e_max);
-+              }
-+              /*
-+               * there is no free space in found leaf
-+               * we're gonna add new leaf in the tree
-+               */
-+              err = ext3_ext_create_new_leaf(handle, inode, path, newext);
-+              if (err)
-+                      goto cleanup;
-+              goto repeat;
-+      }
-+
-+      nearex = path[depth].p_ext;
-+
-+      if ((err = ext3_ext_get_access(handle, inode, path + depth)))
-+              goto cleanup;
-+
-+      if (!nearex) {
-+              /* there is no extent in this leaf, create first one */
-+              ext_debug(inode, "first extent in the leaf: %d:%d:%d\n",
-+                              newext->e_block, newext->e_start,
-+                              newext->e_num);
-+              eh->e_num++;
-+              path[depth].p_ext = EXT_FIRST_EXTENT(eh);
-+
-+      } else if (newext->e_block > nearex->e_block) {
-+              EXT_ASSERT(newext->e_block != nearex->e_block);
-+              len = EXT_MAX_EXTENT(eh) - nearex;
-+              len = (len - 1) * sizeof(struct ext3_extent);
-+              len = len < 0 ? 0 : len;
-+              ext_debug(inode, "insert %d:%d:%d after: nearest 0x%p, "
-+                              "move %d from 0x%p to 0x%p\n",
-+                              newext->e_block, newext->e_start, newext->e_num,
-+                              nearex, len, nearex + 1, nearex + 2);
-+              ext3_ext_check_boundary(inode, path + depth, nearex + 2, len);
-+              memmove(nearex + 2, nearex + 1, len);
-+              path[depth].p_ext = nearex + 1;
-+              eh->e_num++;
-+      } else {
-+              EXT_ASSERT(newext->e_block != nearex->e_block);
-+              len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
-+              len = len < 0 ? 0 : len;
-+              ext_debug(inode, "insert %d:%d:%d before: nearest 0x%p, "
-+                              "move %d from 0x%p to 0x%p\n",
-+                              newext->e_block, newext->e_start, newext->e_num,
-+                              nearex, len, nearex + 1, nearex + 2);
-+              
-+              memmove(nearex + 1, nearex, len);
-+              path[depth].p_ext = nearex;
-+      }
-+
-+      if (!err) {
-+              eh->e_num++;
-+              nearex = path[depth].p_ext;
-+              nearex->e_block = newext->e_block;
-+              nearex->e_start = newext->e_start;
-+              nearex->e_num = newext->e_num;
-+              EXT_ASSERT(nearex->e_num < EXT3_BLOCKS_PER_GROUP(inode->i_sb) &&
-+                              nearex->e_num > 0);
-+
-+              /* time to correct all indexes above */
-+              err = ext3_ext_correct_indexes(handle, inode, path);
-+      }
-+
-+      err = ext3_ext_dirty(handle, inode, path + depth);
-+
-+cleanup:
-+      if (npath) {
-+              ext3_ext_drop_refs(inode, npath);
-+              kfree(npath);
-+      }
-+              
-+      return err;
-+}
-+
-+int ext3_ext_get_block(handle_t *handle, struct inode *inode, long iblock,
-+                      struct buffer_head *bh_result, int create,
-+                      int extend_disksize)
-+{
-+      struct ext3_ext_path *path;
-+      int depth = EXT3_I(inode)->i_depth;
-+      struct ext3_extent newex;
-+      struct ext3_extent *ex;
-+      int goal, newblock, err = 0;
-+
-+      ext_debug(inode, "block %d requested for inode %u, bh_result 0x%p\n",
-+                      (int) iblock, (unsigned) inode->i_ino, bh_result);
-+      bh_result->b_state &= ~(1UL << BH_New);
-+
-+      down(&EXT3_I(inode)->i_ext_sem);
-+
-+      /* find extent for this block */
-+      path = ext3_ext_find_extent(inode, iblock, NULL);
-+      if (IS_ERR(path)) {
-+              err = PTR_ERR(path);
-+              goto out2;
-+      }
-+
-+      if ((ex = path[depth].p_ext)) {
-+              /* if found exent covers block, simple return it */
-+              if (iblock >= ex->e_block && iblock < ex->e_block + ex->e_num) {
-+                      newblock = iblock - ex->e_block + ex->e_start;
-+                      ext_debug(inode, "%d fit into %d:%d -> %d\n",
-+                                      (int) iblock, ex->e_block, ex->e_num,
-+                                      newblock);
-+                      goto out;
-+              }
-+      }
-+
-+      /*
-+       * we couldn't try to create block if create flag is zero 
-+       */
-+      if (!create) 
-+              goto out2;
-+
-+      /* allocate new block */
-+      goal = ext3_ext_find_goal(inode, path);
-+      newblock = ext3_new_block(handle, inode, goal, 0, 0, &err);
-+      if (!newblock)
-+              goto out2;
-+      ext_debug(inode, "allocate new block: goal %d, found %d\n",
-+                      goal, newblock);
-+
-+      /* try to insert new extent into found leaf and return */
-+      newex.e_block = iblock;
-+      newex.e_start = newblock;
-+      newex.e_num = 1;
-+      err = ext3_ext_insert_extent(handle, inode, path, &newex);
-+      if (err)
-+              goto out2;
-+      
-+      /* previous routine could use block we allocated */
-+      newblock = newex.e_start;
-+      bh_result->b_state |= (1UL << BH_New);
-+
-+out:
-+      ext3_ext_show_leaf(inode, path);
-+      bh_result->b_dev = inode->i_dev;
-+      bh_result->b_blocknr = newblock;
-+      bh_result->b_state |= (1UL << BH_Mapped);
-+out2:
-+      ext3_ext_drop_refs(inode, path);
-+      kfree(path);
-+      up(&EXT3_I(inode)->i_ext_sem);
-+
-+      return err;     
-+}
-+
-+/*
-+ * returns 1 if current index have to be freed (even partial)
-+ */
-+static int ext3_ext_more_to_truncate(struct inode *inode,
-+                              struct ext3_ext_path *path)
-+{
-+      EXT_ASSERT(path->p_idx);
-+
-+      if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
-+              return 0;
-+
-+      /*
-+       * if truncate on deeper level happened it it wasn't partial
-+       * so we have to consider current index for truncation
-+       */
-+      if (path->p_hdr->e_num == path->p_block)
-+              return 0;
-+
-+      /*
-+       * put actual number of indexes to know is this number got
-+       * changed at the next iteration
-+       */
-+      path->p_block = path->p_hdr->e_num;
-+      
-+      return 1;
-+}
-+
-+/*
-+ * routine removes index from the index block
-+ * it's used in truncate case only. thus all requests are for
-+ * last index in the block only
-+ */
-+int ext3_ext_remove_index(handle_t *handle, struct inode *inode,
-+                                      struct ext3_ext_path *path)
-+{
-+      struct buffer_head *bh;
-+      int err;
-+      
-+      /* free index block */
-+      path--;
-+      EXT_ASSERT(path->p_hdr->e_num);
-+      if ((err = ext3_ext_get_access(handle, inode, path)))
-+              return err;
-+      path->p_hdr->e_num--;
-+      if ((err = ext3_ext_dirty(handle, inode, path)))
-+              return err;
-+      bh = sb_get_hash_table(inode->i_sb, path->p_idx->e_leaf);
-+      ext3_forget(handle, 0, inode, bh, path->p_idx->e_leaf);
-+      ext3_free_blocks(handle, inode, path->p_idx->e_leaf, 1);
-+
-+      ext_debug(inode, "index is empty, remove it, free block %d\n",
-+                      path->p_idx->e_leaf);
-+      return err;
-+}
-+
-+/*
-+ * returns 1 if current extent needs to be freed (even partial)
-+ * instead, returns 0
-+ */
-+int ext3_ext_more_leaves_to_truncate(struct inode *inode,
-+                                      struct ext3_ext_path *path)
-+{
-+      unsigned blocksize = inode->i_sb->s_blocksize;
-+      struct ext3_extent *ex = path->p_ext;
-+      int last_block; 
-+
-+      EXT_ASSERT(ex);
-+
-+      /* is there leave in the current leaf? */
-+      if (ex < EXT_FIRST_EXTENT(path->p_hdr))
-+              return 0;
-+      
-+      last_block = (inode->i_size + blocksize-1)
-+                      >> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
-+
-+      if (last_block >= ex->e_block + ex->e_num)
-+              return 0;
-+
-+      /* seems it extent have to be freed */
-+      return 1;
-+}
-+
-+handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
-+{
-+      int err;
-+
-+      if (handle->h_buffer_credits > needed)
-+              return handle;
-+      if (!ext3_journal_extend(handle, needed))
-+              return handle;
-+      err = ext3_journal_restart(handle, needed);
-+      
-+      return handle;
-+}
-+
-+/*
-+ * this routine calculate max number of blocks to be modified
-+ * while freeing extent and is intended to be used in truncate path
-+ */
-+static int ext3_ext_calc_credits(struct inode *inode,
-+                                      struct ext3_ext_path *path,
-+                                      int num)
-+{
-+      int depth = EXT3_I(inode)->i_depth;
-+      int needed;
-+      
-+      /*
-+       * extent couldn't cross group, so we will modify
-+       * single bitmap block and single group descriptor
-+       */
-+      needed = 2;
-+
-+      /*
-+       * if this is last extent in a leaf, then we have to
-+       * free leaf block and remove pointer from index above.
-+       * that pointer could be last in index block, so we'll
-+       * have to remove it too. this way we could modify/free
-+       * the whole path + root index (inode stored) will be
-+       * modified
-+       */
-+      if (!path || (num == path->p_ext->e_num &&
-+                              path->p_ext == EXT_FIRST_EXTENT(path->p_hdr)))
-+              needed += (depth * EXT3_ALLOC_NEEDED) + 1;
-+
-+      /*
-+       * it seems current calculation has bug
-+       * this is workaround -bzzz
-+       */
-+      needed += 10;
-+
-+      return needed;
-+}
-+
-+/*
-+ * core of the truncate procedure:
-+ * - calculated what part of each extent in the requested leaf
-+ *   need to be freed
-+ * - frees and forgets these blocks
-+ *
-+ * TODO: we could optimize and free several extents during
-+ *       single journal_restart()-journal_restart() cycle
-+ */
-+static int ext3_ext_truncate_leaf(handle_t *handle,
-+                                      struct inode *inode,
-+                                      struct ext3_ext_path *path,
-+                                      int depth)
-+{
-+      unsigned blocksize = inode->i_sb->s_blocksize;
-+      int last_block; 
-+      int i, err = 0, sf, num;
-+
-+      ext_debug(inode, "level %d - leaf\n", depth);
-+      if (!path->p_hdr)
-+              path->p_hdr =
-+                      (struct ext3_extent_header *) path->p_bh->b_data;
-+
-+      EXT_ASSERT(path->p_hdr->e_num <= path->p_hdr->e_max);
-+      
-+      last_block = (inode->i_size + blocksize-1)
-+                                      >> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
-+      path->p_ext = EXT_LAST_EXTENT(path->p_hdr);
-+      while (ext3_ext_more_leaves_to_truncate(inode, path)) {
-+
-+              /* what part of extent have to be freed? */
-+              sf = last_block > path->p_ext->e_block ?
-+                      last_block : path->p_ext->e_block;
-+
-+              /* number of blocks from extent to be freed */
-+              num = path->p_ext->e_block + path->p_ext->e_num - sf;
-+
-+              /* calc physical first physical block to be freed */
-+              sf = path->p_ext->e_start + (sf - path->p_ext->e_block);
-+
-+              i = ext3_ext_calc_credits(inode, path, num);
-+              handle = ext3_ext_journal_restart(handle, i);
-+              if (IS_ERR(handle))
-+                      return PTR_ERR(handle);
-+              
-+              ext_debug(inode, "free extent %d:%d:%d -> free %d:%d\n",
-+                              path->p_ext->e_block, path->p_ext->e_start,
-+                              path->p_ext->e_num, sf, num);
-+              for (i = 0; i < num; i++) {
-+                      struct buffer_head *bh =
-+                              sb_get_hash_table(inode->i_sb, sf + i);
-+                      ext3_forget(handle, 0, inode, bh, sf + i);
-+              }
-+              ext3_free_blocks(handle, inode, sf, num);
-+
-+              /* collect extents usage stats */
-+              spin_lock(&EXT3_SB(inode->i_sb)->s_ext_lock);
-+              EXT3_SB(inode->i_sb)->s_ext_extents++;
-+              EXT3_SB(inode->i_sb)->s_ext_blocks += num;
-+              spin_unlock(&EXT3_SB(inode->i_sb)->s_ext_lock);
-+
-+              /* reduce extent */
-+              if ((err = ext3_ext_get_access(handle, inode, path)))
-+                      return err;
-+              path->p_ext->e_num -= num;
-+              if (path->p_ext->e_num == 0)
-+                      path->p_hdr->e_num--;
-+              if ((err = ext3_ext_dirty(handle, inode, path)))
-+                      return err;
-+
-+              path->p_ext--;
-+      }
-+      
-+      /* if this leaf is free, then we should
-+       * remove it from index block above */
-+      if (path->p_hdr->e_num == 0 && depth > 0) 
-+              err = ext3_ext_remove_index(handle, inode, path);
-+
-+      return err;
-+}
-+
-+static void ext3_ext_collect_stats(struct inode *inode)
-+{
-+      int depth;
-+      
-+      /* skip inodes with old good bitmap */
-+      if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL))
-+              return;
-+      
-+      /* collect on full truncate only */
-+      if (inode->i_size)
-+              return;
-+
-+      depth = EXT3_I(inode)->i_depth;
-+      if (depth < EXT3_SB(inode->i_sb)->s_ext_mindepth)
-+               EXT3_SB(inode->i_sb)->s_ext_mindepth = depth;
-+      if (depth > EXT3_SB(inode->i_sb)->s_ext_maxdepth)
-+               EXT3_SB(inode->i_sb)->s_ext_maxdepth = depth;
-+      EXT3_SB(inode->i_sb)->s_ext_sum += depth;
-+      EXT3_SB(inode->i_sb)->s_ext_count++;
-+      
-+}
-+
-+void ext3_ext_truncate(struct inode * inode)
-+{
-+      struct address_space *mapping = inode->i_mapping;
-+      struct ext3_ext_path *path;
-+      struct page * page;
-+      handle_t *handle;
-+      int i, depth, err = 0;
-+
-+      ext3_ext_collect_stats(inode);
-+
-+      /*
-+       * We have to lock the EOF page here, because lock_page() nests
-+       * outside journal_start().
-+       */
-+      if ((inode->i_size & (inode->i_sb->s_blocksize - 1)) == 0) {
-+              /* Block boundary? Nothing to do */
-+              page = NULL;
-+      } else {
-+              page = grab_cache_page(mapping,
-+                              inode->i_size >> PAGE_CACHE_SHIFT);
-+              if (!page)
-+                      return;
-+      }
-+
-+      /*
-+       * probably first extent we're gonna free will be last in block
-+       */
-+      i = ext3_ext_calc_credits(inode, NULL, 0);
-+      handle = ext3_journal_start(inode, i);
-+      if (IS_ERR(handle)) {
-+              if (page) {
-+                      clear_highpage(page);
-+                      flush_dcache_page(page);
-+                      unlock_page(page);
-+                      page_cache_release(page);
-+              }
-+              return;
-+      }
-+
-+      if (page)
-+              ext3_block_truncate_page(handle, mapping, inode->i_size, page,
-+                                              inode->i_sb->s_blocksize);
-+
-+      down(&EXT3_I(inode)->i_ext_sem);
-+
-+      /* 
-+       * TODO: optimization is possible here
-+       * probably we need not scaning at all,
-+       * because page truncation is enough
-+       */
-+      if (ext3_orphan_add(handle, inode))
-+              goto out_stop;
-+
-+      /* we have to know where to truncate from in crash case */
-+      EXT3_I(inode)->i_disksize = inode->i_size;
-+      ext3_mark_inode_dirty(handle, inode);
-+
-+      /*
-+       * we start scanning from right side freeing all the blocks
-+       * after i_size and walking into the deep
-+       */
-+      i = 0;
-+      depth = EXT3_I(inode)->i_depth;
-+      path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
-+      if (IS_ERR(path)) {
-+              ext3_error(inode->i_sb, "ext3_ext_truncate",
-+                              "Can't allocate path array");
-+              goto out_stop;
-+      }
-+      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
-+
-+      path[i].p_hdr = (struct ext3_extent_header *) EXT3_I(inode)->i_data;
-+      while (i >= 0 && err == 0) {
-+              if (i == depth) {
-+                      /* this is leaf block */
-+                      err = ext3_ext_truncate_leaf(handle, inode,
-+                                                      path + i, i);
-+                      /* root level have p_bh == NULL, brelse() eats this */
-+                      brelse(path[i].p_bh);
-+                      i--;
-+                      continue;
-+              }
-+              
-+              /* this is index block */
-+              if (!path[i].p_hdr) {
-+                      path[i].p_hdr =
-+                              (struct ext3_extent_header *) path[i].p_bh->b_data;
-+                      ext_debug(inode, "initialize header\n");
-+              }
-+
-+              EXT_ASSERT(path[i].p_hdr->e_num <= path[i].p_hdr->e_max);
-+              
-+              if (!path[i].p_idx) {
-+                      /* this level hasn't touched yet */
-+                      path[i].p_idx = EXT_LAST_INDEX(path[i].p_hdr);
-+                      path[i].p_block = path[i].p_hdr->e_num + 1;
-+                      ext_debug(inode, "init index ptr: hdr 0x%p, num %d\n",
-+                                      path[i].p_hdr, path[i].p_hdr->e_num);
-+              } else {
-+                      /* we've already was here, see at next index */
-+                      path[i].p_idx--;
-+              }
-+
-+              ext_debug(inode, "level %d - index, first 0x%p, cur 0x%p\n",
-+                              i, EXT_FIRST_INDEX(path[i].p_hdr),
-+                              path[i].p_idx);
-+              if (ext3_ext_more_to_truncate(inode, path + i)) {
-+                      /* go to the next level */
-+                      ext_debug(inode, "move to level %d (block %d)\n", i+1,
-+                                      path[i].p_idx->e_leaf);
-+                      memset(path + i + 1, 0, sizeof(*path));
-+                      path[i+1].p_bh = sb_bread(inode->i_sb,
-+                                                      path[i].p_idx->e_leaf);
-+                      if (!path[i+1].p_bh) {
-+                              /* should we reset i_size? */
-+                              err = -EIO;
-+                              break;
-+                      }
-+                      i++;
-+              } else {
-+                      /* we finish processing this index, go up */
-+                      if (path[i].p_hdr->e_num == 0 && i > 0) {
-+                              /* index is empty, remove it
-+                               * handle must be already prepared by the
-+                               * truncate_leaf()
-+                               */
-+                              err = ext3_ext_remove_index(handle, inode,
-+                                                              path + i);
-+                      }
-+                      /* root level have p_bh == NULL, brelse() eats this */
-+                      brelse(path[i].p_bh);
-+                      i--;
-+                      ext_debug(inode, "return to level %d\n", i);
-+              }
-+      }
-+
-+      /* TODO: flexible tree reduction should be here */
-+      if (path->p_hdr->e_num == 0) {
-+              /*
-+               * truncate to zero freed all the tree
-+               * so, we need to correct i_depth
-+               */
-+              EXT3_I(inode)->i_depth = 0;
-+              path->p_hdr->e_max = 0;
-+              ext3_mark_inode_dirty(handle, inode);
-+      }
-+
-+      kfree(path);
-+
-+      /* In a multi-transaction truncate, we only make the final
-+       * transaction synchronous */
-+      if (IS_SYNC(inode))
-+              handle->h_sync = 1;
-+
-+out_stop:
-+      /*
-+       * If this was a simple ftruncate(), and the file will remain alive
-+       * then we need to clear up the orphan record which we created above.
-+       * However, if this was a real unlink then we were called by
-+       * ext3_delete_inode(), and we allow that function to clean up the
-+       * orphan info for us.
-+       */
-+      if (inode->i_nlink)
-+              ext3_orphan_del(handle, inode);
-+
-+      up(&EXT3_I(inode)->i_ext_sem);
-+      ext3_journal_stop(handle, inode);
-+}
-+
-+/*
-+ * this routine calculate max number of blocks we could modify
-+ * in order to allocate new block for an inode
-+ */
-+int ext3_ext_writepage_trans_blocks(struct inode *inode, int num)
-+{
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      int depth = ei->i_depth + 1;
-+      int needed;
-+      
-+      /*
-+       * the worste case we're expecting is creation of the
-+       * new root (growing in depth) with index splitting
-+       * for splitting we have to consider depth + 1 because
-+       * previous growing could increase it
-+       */
-+
-+      /* 
-+       * growing in depth:
-+       * block allocation + new root + old root
-+       */
-+      needed = EXT3_ALLOC_NEEDED + 2;
-+
-+      /* index split. we may need:
-+       *   allocate intermediate indexes and new leaf
-+       *   change two blocks at each level, but root
-+       *   modify root block (inode)
-+       */
-+      needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1;
-+
-+      /* caller want to allocate num blocks */
-+      needed *= num;
-+      
-+#ifdef CONFIG_QUOTA
-+      /* 
-+       * FIXME: real calculation should be here
-+       * it depends on blockmap format of qouta file
-+       */
-+      needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
-+#endif
-+
-+      return needed;
-+}
-+
-+/*
-+ * called at mount time
-+ */
-+void ext3_ext_init(struct super_block *sb)
-+{
-+      /*
-+       * possible initialization would be here
-+       */
-+
-+      if (test_opt(sb, EXTENTS))
-+              printk("EXT3-fs: file extents enabled\n");
-+      spin_lock_init(&EXT3_SB(sb)->s_ext_lock);
-+}
-+
-+/*
-+ * called at umount time
-+ */
-+void ext3_ext_release(struct super_block *sb)
-+{
-+      struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+      /* show collected stats */
-+      if (sbi->s_ext_count && sbi->s_ext_extents)
-+              printk("EXT3-fs: min depth - %d, max depth - %d, "
-+                              "ave. depth - %d, ave. blocks/extent - %d\n",
-+                              sbi->s_ext_mindepth,
-+                              sbi->s_ext_maxdepth,
-+                              sbi->s_ext_sum / sbi->s_ext_count,
-+                              sbi->s_ext_blocks / sbi->s_ext_extents);
-+}
-+
---- linux-2.4.18-chaos-pdirops/fs/ext3/ialloc.c~ext3-extents-2.4.18-chaos-pdirops      2003-09-23 13:44:53.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/fs/ext3/ialloc.c 2003-09-23 14:29:32.000000000 +0400
-@@ -573,6 +573,10 @@ repeat:
-       ei->i_prealloc_count = 0;
- #endif
-       ei->i_block_group = i;
-+      if (test_opt(sb, EXTENTS))
-+              EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+      ei->i_depth = 0;
-+      sema_init(&ei->i_ext_sem, 1);
-       if (ei->i_flags & EXT3_SYNC_FL)
-               inode->i_flags |= S_SYNC;
---- linux-2.4.18-chaos-pdirops/fs/ext3/inode.c~ext3-extents-2.4.18-chaos-pdirops       2003-09-23 13:44:53.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/fs/ext3/inode.c  2003-09-23 14:29:32.000000000 +0400
-@@ -842,6 +842,15 @@ changed:
-       goto reread;
- }
-+static inline int
-+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+              struct buffer_head *bh, int create, int extend_disksize)
-+{
-+      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+              return ext3_ext_get_block(handle, inode, block, bh, create, 1);
-+      return ext3_get_block_handle(handle, inode, block, bh, create, 1);
-+}
-+
- /*
-  * The BKL is not held on entry here.
-  */
-@@ -855,7 +864,7 @@ static int ext3_get_block(struct inode *
-               handle = ext3_journal_current_handle();
-               J_ASSERT(handle != 0);
-       }
--      ret = ext3_get_block_handle(handle, inode, iblock,
-+      ret = ext3_get_block_wrap(handle, inode, iblock,
-                               bh_result, create, 1);
-       return ret;
- }
-@@ -882,7 +891,7 @@ ext3_direct_io_get_block(struct inode *i
-               }
-       }
-       if (ret == 0)
--              ret = ext3_get_block_handle(handle, inode, iblock,
-+              ret = ext3_get_block_wrap(handle, inode, iblock,
-                                       bh_result, create, 0);
-       if (ret == 0)
-               bh_result->b_size = (1 << inode->i_blkbits);
-@@ -904,7 +913,7 @@ struct buffer_head *ext3_getblk(handle_t
-       dummy.b_state = 0;
-       dummy.b_blocknr = -1000;
-       buffer_trace_init(&dummy.b_history);
--      *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1);
-+      *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create, 1);
-       if (!*errp && buffer_mapped(&dummy)) {
-               struct buffer_head *bh;
-               bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
-@@ -1520,7 +1529,7 @@ ext3_block_truncate_page_prepare(struct 
-  * This required during truncate. We need to physically zero the tail end
-  * of that block so it doesn't yield old data if the file is later grown.
-  */
--static int ext3_block_truncate_page(handle_t *handle,
-+int ext3_block_truncate_page(handle_t *handle,
-                                   struct address_space *mapping, loff_t from,
-                                   struct page *page, unsigned blocksize)
- {
-@@ -1998,6 +2007,9 @@ void ext3_truncate(struct inode * inode)
-       ext3_discard_prealloc(inode);
-+      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+              return ext3_ext_truncate(inode);
-+
-       blocksize = inode->i_sb->s_blocksize;
-       last_block = (inode->i_size + blocksize-1)
-                                       >> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
-@@ -2436,6 +2448,8 @@ void ext3_read_inode(struct inode * inod
-       ei->i_prealloc_count = 0;
- #endif
-       ei->i_block_group = iloc.block_group;
-+      ei->i_depth = raw_inode->osd2.linux2.l_i_depth;
-+      sema_init(&ei->i_ext_sem, 1);
-       /*
-        * NOTE! The in-memory inode i_data array is in little-endian order
-@@ -2559,6 +2573,7 @@ static int ext3_do_update_inode(handle_t
-               raw_inode->i_fsize = 0;
-       }
- #endif
-+      raw_inode->osd2.linux2.l_i_depth = ei->i_depth;
-       raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
-       if (!S_ISREG(inode->i_mode)) {
-               raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
-@@ -2762,6 +2777,9 @@ int ext3_writepage_trans_blocks(struct i
-       int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
-       int ret;
-       
-+      if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+              return ext3_ext_writepage_trans_blocks(inode, bpp);
-+
-       if (ext3_should_journal_data(inode))
-               ret = 3 * (bpp + indirects) + 2;
-       else
-@@ -3085,7 +3103,7 @@ int ext3_prep_san_write(struct inode *in
-       /* alloc blocks one by one */
-       for (i = 0; i < nblocks; i++) {
--              ret = ext3_get_block_handle(handle, inode, blocks[i],
-+              ret = ext3_get_block_wrap(handle, inode, blocks[i],
-                                               &bh_tmp, 1, 1);
-               if (ret)
-                       break;
-@@ -3146,7 +3164,7 @@ int ext3_map_inode_page(struct inode *in
-                 if (blocks[i] != 0)
-                         continue;
--                rc = ext3_get_block_handle(handle, inode, iblock, &dummy, 1, 1);
-+                rc = ext3_get_block_wrap(handle, inode, iblock, &dummy, 1, 1);
-                 if (rc) {
-                         printk(KERN_INFO "ext3_map_inode_page: error reading "
-                                "block %ld\n", iblock);
---- linux-2.4.18-chaos-pdirops/fs/ext3/Makefile~ext3-extents-2.4.18-chaos-pdirops      2003-09-23 13:44:48.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/fs/ext3/Makefile 2003-09-23 14:29:32.000000000 +0400
-@@ -12,7 +12,8 @@ O_TARGET := ext3.o
- export-objs :=        ext3-exports.o
- obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
--              ioctl.o namei.o super.o symlink.o xattr.o hash.o ext3-exports.o
-+              ioctl.o namei.o super.o symlink.o xattr.o hash.o ext3-exports.o \
-+              extents.o
- obj-m    := $(O_TARGET)
- include $(TOPDIR)/Rules.make
---- linux-2.4.18-chaos-pdirops/fs/ext3/super.c~ext3-extents-2.4.18-chaos-pdirops       2003-09-23 13:44:53.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/fs/ext3/super.c  2003-09-23 14:29:33.000000000 +0400
-@@ -619,6 +619,7 @@ void ext3_put_super (struct super_block 
-       kdev_t j_dev = sbi->s_journal->j_dev;
-       int i;
-+      ext3_ext_release(sb);
-       ext3_stop_delete_thread(sbi);
-       ext3_xattr_put_super(sb);
-       journal_destroy(sbi->s_journal);
-@@ -741,6 +742,12 @@ static int parse_options (char * options
-               else
- #endif
-+              if (!strcmp (this_char, "extents"))
-+                      set_opt (sbi->s_mount_opt, EXTENTS);
-+              else
-+              if (!strcmp (this_char, "extdebug"))
-+                      set_opt (sbi->s_mount_opt, EXTDEBUG);
-+              else
-               if (!strcmp (this_char, "bsddf"))
-                       clear_opt (*mount_options, MINIX_DF);
-               else if (!strcmp (this_char, "nouid32")) {
-@@ -1471,6 +1478,7 @@ struct super_block * ext3_read_super (st
-               test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal":
-               test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
-               "writeback");
-+      ext3_ext_init(sb);
-       if (test_opt(sb, PDIROPS)) {
-               printk (KERN_INFO "EXT3-fs: mounted filesystem with parallel dirops\n");
---- linux-2.4.18-chaos-pdirops/include/linux/ext3_fs.h~ext3-extents-2.4.18-chaos-pdirops       2003-09-23 13:44:53.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/include/linux/ext3_fs.h  2003-09-23 14:29:33.000000000 +0400
-@@ -188,6 +188,7 @@ struct ext3_group_desc
- #define EXT3_IMAGIC_FL                        0x00002000 /* AFS directory */
- #define EXT3_JOURNAL_DATA_FL          0x00004000 /* file data should be journaled */
- #define EXT3_RESERVED_FL              0x80000000 /* reserved for ext3 lib */
-+#define EXT3_EXTENTS_FL                       0x00080000 /* Inode uses extents */
- #define EXT3_FL_USER_VISIBLE          0x00005FFF /* User visible flags */
- #define EXT3_FL_USER_MODIFIABLE               0x000000FF /* User modifiable flags */
-@@ -248,7 +249,7 @@ struct ext3_inode {
-               struct {
-                       __u8    l_i_frag;       /* Fragment number */
-                       __u8    l_i_fsize;      /* Fragment size */
--                      __u16   i_pad1;
-+                      __u16   l_i_depth;
-                       __u16   l_i_uid_high;   /* these 2 fields    */
-                       __u16   l_i_gid_high;   /* were reserved2[0] */
-                       __u32   l_i_reserved2;
-@@ -329,6 +330,8 @@ struct ext3_inode {
- #define EXT3_MOUNT_IOPEN              0x8000  /* Allow access via iopen */
- #define EXT3_MOUNT_IOPEN_NOPRIV               0x10000 /* Make iopen world-readable */
- #define EXT3_MOUNT_ASYNCDEL           0x20000 /* Delayed deletion */
-+#define EXT3_MOUNT_EXTENTS            0x40000 /* Extents support */
-+#define EXT3_MOUNT_EXTDEBUG           0x80000 /* Extents debug */
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -720,6 +723,12 @@ extern void ext3_discard_prealloc (struc
- extern void ext3_dirty_inode(struct inode *);
- extern int ext3_change_inode_journal_flag(struct inode *, int);
- extern void ext3_truncate (struct inode *);
-+extern int ext3_block_truncate_page(handle_t *handle,
-+                                  struct address_space *mapping, loff_t from,
-+                                  struct page *page, unsigned blocksize);
-+extern int ext3_forget(handle_t *handle, int is_metadata,
-+                     struct inode *inode, struct buffer_head *bh,
-+                     int blocknr);
- #ifdef EXT3_DELETE_THREAD
- extern void ext3_truncate_thread(struct inode *inode);
- #endif
-@@ -781,6 +790,13 @@ extern struct inode_operations ext3_dir_
- /* symlink.c */
- extern struct inode_operations ext3_fast_symlink_inode_operations;
-+/* extents.c */
-+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
-+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+                              struct buffer_head *, int, int);
-+extern void ext3_ext_truncate(struct inode *);
-+extern void ext3_ext_init(struct super_block *);
-+extern void ext3_ext_release(struct super_block *);
- #endif        /* __KERNEL__ */
---- linux-2.4.18-chaos-pdirops/include/linux/ext3_fs_i.h~ext3-extents-2.4.18-chaos-pdirops     2003-09-23 13:44:53.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/include/linux/ext3_fs_i.h        2003-09-23 14:29:33.000000000 +0400
-@@ -79,6 +79,10 @@ struct ext3_inode_info {
-       struct dynlock i_htree_lock;
-       struct semaphore i_append_sem;
-       struct semaphore i_rename_sem;
-+
-+      /* extents-related data */
-+      struct semaphore i_ext_sem;
-+      __u16 i_depth;
- };
- #endif        /* _LINUX_EXT3_FS_I */
---- linux-2.4.18-chaos-pdirops/include/linux/ext3_fs_sb.h~ext3-extents-2.4.18-chaos-pdirops    2003-09-23 13:34:51.000000000 +0400
-+++ linux-2.4.18-chaos-pdirops-alexey/include/linux/ext3_fs_sb.h       2003-09-23 14:29:33.000000000 +0400
-@@ -86,6 +86,16 @@ struct ext3_sb_info {
-       wait_queue_head_t s_delete_thread_queue;
-       wait_queue_head_t s_delete_waiter_queue;
- #endif
-+
-+      /* extents */
-+      int s_ext_debug;
-+      int s_ext_mindepth;
-+      int s_ext_maxdepth;
-+      int s_ext_sum;
-+      int s_ext_count;
-+      spinlock_t s_ext_lock;
-+      int s_ext_extents;
-+      int s_ext_blocks;
- };
- #endif        /* _LINUX_EXT3_FS_SB */
-
-_
diff --git a/lustre/kernel_patches/patches/ext3-extents-2.4.18-chaos.patch b/lustre/kernel_patches/patches/ext3-extents-2.4.18-chaos.patch
deleted file mode 100644 (file)
index a0b4230..0000000
+++ /dev/null
@@ -1,1895 +0,0 @@
- fs/ext3/Makefile           |    3 
- fs/ext3/extents.c          | 1615 +++++++++++++++++++++++++++++++++++++++++++++
- fs/ext3/ialloc.c           |    4 
- fs/ext3/inode.c            |   30 
- fs/ext3/super.c            |    8 
- include/linux/ext3_fs.h    |   18 
- include/linux/ext3_fs_i.h  |    4 
- include/linux/ext3_fs_sb.h |   10 
- 8 files changed, 1684 insertions(+), 8 deletions(-)
-
-Index: linux-2.4.18-chaos/fs/ext3/extents.c
-===================================================================
---- linux-2.4.18-chaos.orig/fs/ext3/extents.c  2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.18-chaos/fs/ext3/extents.c       2004-01-13 16:11:00.000000000 +0300
-@@ -0,0 +1,1614 @@
-+/*
-+ *
-+ * linux/fs/ext3/extents.c
-+ *
-+ * Extents support for EXT3
-+ *
-+ * 07/08/2003    Alex Tomas <bzzz@tmi.comex.ru>
-+ * 
-+ * TODO:
-+ *   - ext3*_error() should be used in some situations
-+ *   - find_goal() [to be tested and improved]
-+ *   - error handling
-+ *   - we could leak allocated block in some error cases
-+ *   - quick search for index/leaf in ext3_ext_find_extent()
-+ *   - tree reduction
-+ *   - cache last found extent
-+ *   - arch-independent
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/time.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/jbd.h>
-+#include <linux/smp_lock.h>
-+#include <linux/highuid.h>
-+#include <linux/pagemap.h>
-+#include <linux/quotaops.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+#include <linux/locks.h>
-+
-+/*
-+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
-+ * become very little, so index split, in-depth growing and
-+ * other hard changes happens much more often
-+ * this is for debug purposes only
-+ */
-+#define AGRESSIVE_TEST_
-+
-+/*
-+ * if EXT_DEBUG defined you can use 'extdebug' mount option
-+ * to get lots of info what's going on
-+ */
-+#define EXT_DEBUG
-+#ifdef EXT_DEBUG
-+#define ext_debug(inode,fmt,a...)             \
-+do {                                          \
-+      if (test_opt((inode)->i_sb, EXTDEBUG))  \
-+              printk(fmt, ##a);               \
-+} while (0);
-+#else
-+#define ext_debug(inode,fmt,a...)
-+#endif
-+
-+#define EXT3_ALLOC_NEEDED     2       /* block bitmap + group descriptor */
-+
-+/*
-+ * ext3_inode has i_block array (total 60 bytes)
-+ * first 4 bytes are used to store:
-+ *  - tree depth (0 mean there is no tree yet. all extents in the inode)
-+ *  - number of alive extents in the inode
-+ */
-+
-+/*
-+ * this is extent on-disk structure
-+ * it's used at the bottom of the tree
-+ */
-+struct ext3_extent {
-+      __u32   e_block;        /* first logical block extent covers */
-+      __u32   e_start;        /* first physical block extents lives */
-+      __u32   e_num;          /* number of blocks covered by extent */
-+};
-+
-+/*
-+ * this is index on-disk structure
-+ * it's used at all the levels, but the bottom
-+ */
-+struct ext3_extent_idx {
-+      __u32   e_block;        /* index covers logical blocks from 'block' */
-+      __u32   e_leaf;         /* pointer to the physical block of the next *
-+                               * level. leaf or next index could bet here */
-+};
-+
-+/*
-+ * each block (leaves and indexes), even inode-stored has header
-+ */
-+struct ext3_extent_header {   
-+      __u16   e_num;          /* number of valid entries */
-+      __u16   e_max;          /* capacity of store in entries */
-+};
-+
-+/*
-+ * array of ext3_ext_path contains path to some extent
-+ * creation/lookup routines use it for traversal/splitting/etc
-+ * truncate uses it to simulate recursive walking
-+ */
-+struct ext3_ext_path {
-+      __u32                           p_block;
-+      __u16                           p_depth;
-+      struct ext3_extent              *p_ext;
-+      struct ext3_extent_idx          *p_idx;
-+      struct ext3_extent_header       *p_hdr;
-+      struct buffer_head              *p_bh;
-+};
-+
-+#define EXT_FIRST_EXTENT(__hdr__) \
-+      ((struct ext3_extent *) (((char *) (__hdr__)) +         \
-+                               sizeof(struct ext3_extent_header)))
-+#define EXT_FIRST_INDEX(__hdr__) \
-+      ((struct ext3_extent_idx *) (((char *) (__hdr__)) +     \
-+                                   sizeof(struct ext3_extent_header)))
-+#define EXT_HAS_FREE_INDEX(__path__) \
-+      ((__path__)->p_hdr->e_num < (__path__)->p_hdr->e_max)
-+#define EXT_LAST_EXTENT(__hdr__) \
-+      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->e_num - 1)
-+#define EXT_LAST_INDEX(__hdr__) \
-+      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->e_num - 1)
-+#define EXT_MAX_EXTENT(__hdr__) \
-+      (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->e_max - 1)
-+#define EXT_MAX_INDEX(__hdr__) \
-+      (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->e_max - 1)
-+
-+
-+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
-+
-+/*
-+ * could return:
-+ *  - EROFS
-+ *  - ENOMEM
-+ */
-+static int ext3_ext_get_access(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path)
-+{
-+      if (path->p_bh) {
-+              /* path points to block */
-+              return ext3_journal_get_write_access(handle, path->p_bh);
-+      }
-+
-+      /* path points to leaf/index in inode body */
-+      return 0;
-+}
-+
-+/*
-+ * could return:
-+ *  - EROFS
-+ *  - ENOMEM
-+ *  - EIO
-+ */
-+static int ext3_ext_dirty(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path)
-+{
-+      if (path->p_bh) {
-+              /* path points to block */
-+              return ext3_journal_dirty_metadata(handle, path->p_bh);
-+      }
-+
-+      /* path points to leaf/index in inode body */
-+      return ext3_mark_inode_dirty(handle, inode);
-+}
-+
-+static inline int ext3_ext_space_block(struct inode *inode)
-+{
-+      int size;
-+
-+      size = (inode->i_sb->s_blocksize - sizeof(struct ext3_extent_header))
-+              / sizeof(struct ext3_extent);
-+#ifdef AGRESSIVE_TEST
-+      size = 6; /* FIXME: for debug, remove this line */
-+#endif
-+      return size;
-+}
-+
-+static inline int ext3_ext_space_inode(struct inode *inode)
-+{
-+      int size;
-+
-+      size = (sizeof(EXT3_I(inode)->i_data) -
-+                      sizeof(struct ext3_extent_header))
-+                      / sizeof(struct ext3_extent);
-+#ifdef AGRESSIVE_TEST
-+      size = 3; /* FIXME: for debug, remove this line */
-+#endif
-+      return size;
-+}
-+
-+static inline int ext3_ext_space_inode_idx(struct inode *inode)
-+{
-+      int size;
-+
-+      size = (sizeof(EXT3_I(inode)->i_data) -
-+                      sizeof(struct ext3_extent_header))
-+                      / sizeof(struct ext3_extent_idx);
-+#ifdef AGRESSIVE_TEST
-+      size = 4; /* FIXME: for debug, remove this line */
-+#endif
-+      return size;
-+}
-+
-+static void ext3_ext_show_path(struct inode *inode, struct ext3_ext_path *path)
-+{
-+      int k, l = path->p_depth;
-+
-+      ext_debug(inode, "path:");
-+      for (k = 0; k <= l; k++, path++) {
-+              if (path->p_idx) {
-+                      ext_debug(inode, "  %d->%d", path->p_idx->e_block,
-+                                      path->p_idx->e_leaf);
-+              } else if (path->p_ext) {
-+                      ext_debug(inode, "  %d:%d:%d",
-+                                      path->p_ext->e_block,
-+                                      path->p_ext->e_start,
-+                                      path->p_ext->e_num);
-+              } else
-+                      ext_debug(inode, "  []");
-+      }
-+      ext_debug(inode, "\n");
-+}
-+
-+static void ext3_ext_show_leaf(struct inode *inode, struct ext3_ext_path *path)
-+{
-+      int depth = EXT3_I(inode)->i_depth;
-+      struct ext3_extent_header *eh = path[depth].p_hdr;
-+      struct ext3_extent *ex = EXT_FIRST_EXTENT(eh);
-+      int i;
-+
-+      for (i = 0; i < eh->e_num; i++, ex++) {
-+              ext_debug(inode, "%d:%d:%d ",
-+                              ex->e_block, ex->e_start, ex->e_num);
-+      }
-+      ext_debug(inode, "\n");
-+}
-+
-+static void ext3_ext_drop_refs(struct inode *inode, struct ext3_ext_path *path)
-+{
-+      int depth = path->p_depth;
-+      int i;
-+
-+      for (i = 0; i <= depth; i++, path++)
-+              if (path->p_bh) {
-+                      brelse(path->p_bh);
-+                      path->p_bh = NULL;
-+              }
-+}
-+
-+static int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path)
-+{
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      unsigned long bg_start;
-+      unsigned long colour;
-+      int depth;
-+      
-+      if (path) {
-+              depth = path->p_depth;
-+              /* try to find previous block */
-+              if (path[depth].p_ext)
-+                      return path[depth].p_ext->e_start +
-+                              path[depth].p_ext->e_num - 1;
-+              
-+              /* it looks index is empty
-+               * try to find starting from index itself */
-+              if (path[depth].p_bh)
-+                      return path[depth].p_bh->b_blocknr;
-+      }
-+
-+      /* OK. use inode's group */
-+      bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+              le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
-+      colour = (current->pid % 16) *
-+                      (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-+      return bg_start + colour;
-+}
-+
-+static struct ext3_ext_path *
-+ext3_ext_find_extent(struct inode *inode, int block, struct ext3_ext_path *path)
-+{
-+      struct ext3_inode_info *ei = EXT3_I(inode);
-+      struct ext3_extent_header *eh = (void *) ei->i_data;
-+      struct ext3_extent_idx *ix;
-+      struct buffer_head *bh;
-+      struct ext3_extent *ex;
-+      int depth, i, k, ppos = 0, prev = 0;
-+      
-+      eh = (struct ext3_extent_header *) ei->i_data;
-+
-+      /* initialize capacity of leaf in inode for first time */
-+      if (eh->e_max == 0)
-+              eh->e_max = ext3_ext_space_inode(inode);
-+      i = depth = ei->i_depth;
-+      EXT_ASSERT(i == 0 || eh->e_num > 0);
-+      
-+      /* account possible depth increase */
-+      if (!path) {
-+              path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+                              GFP_NOFS);
-+              if (!path)
-+                      return ERR_PTR(-ENOMEM);
-+      }
-+      memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
-+
-+      /* walk through the tree */
-+      while (i) {
-+              ext_debug(inode, "depth %d: num %d, max %d\n",
-+                              ppos, eh->e_num, eh->e_max);
-+              ix = EXT_FIRST_INDEX(eh);
-+              if (eh->e_num) {
-+                      EXT_ASSERT(prev == 0 || ix->e_block == prev);
-+                      path[ppos].p_idx = ix;
-+              }
-+              EXT_ASSERT(eh->e_num <= eh->e_max);
-+              for (k = 0; k < eh->e_num; k++, ix++) {
-+                      ext_debug(inode, "index: %d -> %d\n",
-+                                      ix->e_block, ix->e_leaf);
-+                      EXT_ASSERT((k == 0 && prev <= (int)ix->e_block) ||
-+                                      (k > 0 && prev < (int)ix->e_block));
-+                      if (block < ix->e_block)
-+                              break;
-+                      prev = ix->e_block;
-+                      path[ppos].p_idx = ix;
-+              }
-+              path[ppos].p_block = path[ppos].p_idx->e_leaf;
-+              path[ppos].p_depth = i;
-+              path[ppos].p_hdr = eh;
-+              path[ppos].p_ext = NULL;
-+
-+              bh = sb_bread(inode->i_sb, path[ppos].p_block);
-+              if (!bh) {
-+                      ext3_ext_drop_refs(inode, path);
-+                      kfree(path);
-+                      return ERR_PTR(-EIO);
-+              }
-+              eh = (struct ext3_extent_header *) bh->b_data;
-+              ppos++;
-+              EXT_ASSERT(ppos <= depth);
-+              path[ppos].p_bh = bh;
-+              i--;
-+      }
-+
-+      path[ppos].p_depth = i;
-+      path[ppos].p_hdr = eh;
-+      path[ppos].p_ext = NULL;
-+      
-+      /* find extent */
-+      ex = EXT_FIRST_EXTENT(eh);
-+      if (eh->e_num)
-+              path[ppos].p_ext = ex;
-+      EXT_ASSERT(eh->e_num <= eh->e_max);
-+      for (k = 0; k < eh->e_num; k++, ex++) {
-+              EXT_ASSERT(ex->e_num < EXT3_BLOCKS_PER_GROUP(inode->i_sb));
-+              EXT_ASSERT((k == 0 && prev <= (int)ex->e_block) ||
-+                              (k > 0 && prev < (int)ex->e_block));
-+              if (block < ex->e_block) 
-+                      break;
-+              prev = ex->e_block;
-+              path[ppos].p_ext = ex;
-+      }
-+
-+      ext3_ext_show_path(inode, path);
-+
-+      return path;
-+}
-+
-+static void ext3_ext_check_boundary(struct inode *inode,
-+                                      struct ext3_ext_path *curp,
-+                                      void *addr, int len)
-+{
-+      void *end;
-+
-+      if (!len)
-+              return;
-+      if (curp->p_bh)
-+              end = (void *) curp->p_hdr + inode->i_sb->s_blocksize;
-+      else
-+              end = (void *) curp->p_hdr + sizeof(EXT3_I(inode)->i_data);
-+      if (((unsigned long) addr) + len > (unsigned long) end) {
-+              printk("overflow! 0x%p > 0x%p\n", addr + len, end);
-+              BUG();
-+      }
-+      if ((unsigned long) addr < (unsigned long) curp->p_hdr) {
-+              printk("underflow! 0x%p < 0x%p\n", addr, curp->p_hdr);
-+              BUG();
-+      }
-+}
-+
-+/*
-+ * insert new index [logical;ptr] into the block at cupr
-+ * it check where to insert: before curp or after curp
-+ */
-+static int ext3_ext_insert_index(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *curp, int logical,
-+                              int ptr)
-+{
-+      struct ext3_extent_idx *ix;
-+      int len, err;
-+
-+      if ((err = ext3_ext_get_access(handle, inode, curp)))
-+              return err;
-+
-+      EXT_ASSERT(logical != curp->p_idx->e_block);
-+      len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
-+      if (logical > curp->p_idx->e_block) {
-+              /* insert after */
-+              len = (len - 1) * sizeof(struct ext3_extent_idx);
-+              len = len < 0 ? 0 : len;
-+              ext_debug(inode, "insert new index %d after: %d. "
-+                              "move %d from 0x%p to 0x%p\n",
-+                              logical, ptr, len,
-+                              (curp->p_idx + 1), (curp->p_idx + 2));
-+
-+              ext3_ext_check_boundary(inode, curp, curp->p_idx + 2, len);
-+              memmove(curp->p_idx + 2, curp->p_idx + 1, len);
-+              ix = curp->p_idx + 1;
-+      } else {
-+              /* insert before */
-+              len = len * sizeof(struct ext3_extent_idx);
-+              len = len < 0 ? 0 : len;
-+              ext_debug(inode, "insert new index %d before: %d. "
-+                              "move %d from 0x%p to 0x%p\n",
-+                              logical, ptr, len,
-+                              curp->p_idx, (curp->p_idx + 1));
-+
-+              ext3_ext_check_boundary(inode, curp, curp->p_idx + 1, len);
-+              memmove(curp->p_idx + 1, curp->p_idx, len);
-+              ix = curp->p_idx;
-+      }
-+
-+      ix->e_block = logical;
-+      ix->e_leaf = ptr;
-+      curp->p_hdr->e_num++;
-+
-+      err = ext3_ext_dirty(handle, inode, curp);
-+      ext3_std_error(inode->i_sb, err);
-+
-+      return err;
-+}
-+
-+/*
-+ * routine inserts new subtree into the path, using free index entry
-+ * at depth 'at:
-+ *  - allocates all needed blocks (new leaf and all intermediate index blocks)
-+ *  - makes decision where to split
-+ *  - moves remaining extens and index entries (right to the split point)
-+ *    into the newly allocated blocks
-+ *  - initialize subtree
-+ */
-+static int ext3_ext_split(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path,
-+                              struct ext3_extent *newext, int at)
-+{
-+      struct buffer_head *bh = NULL;
-+      int depth = EXT3_I(inode)->i_depth;
-+      struct ext3_extent_header *neh;
-+      struct ext3_extent_idx *fidx;
-+      struct ext3_extent *ex;
-+      int i = at, k, m, a;
-+      long newblock, oldblock, border;
-+      int *ablocks = NULL; /* array of allocated blocks */
-+      int err = 0;
-+
-+      /* make decision: where to split? */
-+      /* FIXME: now desicion is simplest: at current extent */
-+
-+      /* if current leaf will be splitted, then we should use 
-+       * border from split point */
-+      
-+      if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
-+              border = path[depth].p_ext[1].e_block;
-+              ext_debug(inode, "leaf will be splitted."
-+                              " next leaf starts at %d\n",
-+                              (int)border);
-+      } else {
-+              border = newext->e_block;
-+              ext_debug(inode, "leaf will be added."
-+                              " next leaf starts at %d\n",
-+                              (int)border);
-+      }
-+
-+      /* 
-+       * if error occurs, then we break processing
-+       * and turn filesystem read-only. so, index won't
-+       * be inserted and tree will be in consistent
-+       * state. next mount will repair buffers too
-+       */
-+
-+      /*
-+       * get array to track all allocated blocks
-+       * we need this to handle errors and free blocks
-+       * upon them
-+       */
-+      ablocks = kmalloc(sizeof(long) * depth, GFP_NOFS);
-+      if (!ablocks)
-+              return -ENOMEM;
-+      memset(ablocks, 0, sizeof(long) * depth);
-+
-+      /* allocate all needed blocks */
-+      ext_debug(inode, "allocate %d blocks for indexes/leaf\n", depth - at);
-+      newblock = 0; /* FIXME: something more sophisticated needed here */ 
-+      for (a = 0; newext->e_num > 0 && a < depth - at; a++) {
-+              newblock = ablocks[a] = newext->e_start++;
-+              newext->e_num--;
-+      }
-+      for (; a < depth - at; a++) {
-+              newblock = ext3_new_block(handle, inode,
-+                                              newblock + 1, 0, 0, &err);
-+              if (newblock == 0)
-+                      goto cleanup;
-+              ablocks[a] = newblock;
-+      }
-+
-+      /* initialize new leaf */
-+      newblock = ablocks[--a];
-+      EXT_ASSERT(newblock);
-+      bh = sb_getblk(inode->i_sb, newblock);
-+      if (!bh) {
-+              err = -EIO;
-+              goto cleanup;
-+      }
-+      lock_buffer(bh);
-+
-+      if ((err = ext3_journal_get_create_access(handle, bh)))
-+              goto cleanup;
-+
-+      neh = (struct ext3_extent_header *) bh->b_data;
-+      neh->e_num = 0;
-+      neh->e_max = ext3_ext_space_block(inode);
-+      ex = EXT_FIRST_EXTENT(neh);
-+
-+      /* move remain of path[depth] to the new leaf */
-+      EXT_ASSERT(path[depth].p_hdr->e_num ==
-+                      path[depth].p_hdr->e_max);
-+      /* start copy from next extent */
-+      /* TODO: we could do it by single memmove */
-+      m = 0;
-+      path[depth].p_ext++;
-+      while (path[depth].p_ext <=
-+                      EXT_MAX_EXTENT(path[depth].p_hdr)) {
-+              ext_debug(inode, "move %d:%d:%d in new leaf\n",
-+                              path[depth].p_ext->e_block,
-+                              path[depth].p_ext->e_start,
-+                              path[depth].p_ext->e_num);
-+              memmove(ex++, path[depth].p_ext++,
-+                              sizeof(struct ext3_extent));
-+              neh->e_num++;
-+              m++;
-+      }
-+      mark_buffer_uptodate(bh, 1);
-+      unlock_buffer(bh);
-+
-+      if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+              goto cleanup;   
-+      brelse(bh);
-+      bh = NULL;
-+
-+      /* correct old leaf */
-+      if (m) {
-+              if ((err = ext3_ext_get_access(handle, inode, path)))
-+                      goto cleanup;
-+              path[depth].p_hdr->e_num -= m;
-+              if ((err = ext3_ext_dirty(handle, inode, path)))
-+                      goto cleanup;
-+              
-+      }
-+
-+      /* create intermediate indexes */
-+      k = depth - at - 1;
-+      EXT_ASSERT(k >= 0);
-+      if (k)
-+              ext_debug(inode,
-+                              "create %d intermediate indices\n", k);
-+      /* insert new index into current index block */
-+      /* current depth stored in i var */
-+      i = depth - 1;
-+      while (k--) {
-+              oldblock = newblock;
-+              newblock = ablocks[--a];
-+              bh = sb_getblk(inode->i_sb, newblock);
-+              if (!bh) {
-+                      err = -EIO;
-+                      goto cleanup;
-+              }
-+              lock_buffer(bh);
-+
-+              if ((err = ext3_journal_get_create_access(handle, bh)))
-+                      goto cleanup;
-+
-+              neh = (struct ext3_extent_header *) bh->b_data;
-+              neh->e_num = 1;
-+              neh->e_max = ext3_ext_space_block(inode);
-+              fidx = EXT_FIRST_INDEX(neh);
-+              fidx->e_block = border;
-+              fidx->e_leaf = oldblock;
-+
-+              ext_debug(inode,
-+                              "int.index at %d (block %u): %d -> %d\n",
-+                              i, (unsigned) newblock,
-+                              (int) border,
-+                              (int) oldblock);
-+              /* copy indexes */
-+              m = 0;
-+              path[i].p_idx++;
-+              ext_debug(inode, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+                              EXT_MAX_INDEX(path[i].p_hdr));
-+              EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+                              EXT_LAST_INDEX(path[i].p_hdr));
-+              while (path[i].p_idx <=
-+                              EXT_MAX_INDEX(path[i].p_hdr)) {
-+                      ext_debug(inode, "%d: move %d:%d in new index\n",
-+                                      i, path[i].p_idx->e_block,
-+                                      path[i].p_idx->e_leaf);
-+                      memmove(++fidx, path[i].p_idx++,
-+                                      sizeof(struct ext3_extent_idx));
-+                      neh->e_num++;
-+                      m++;
-+              }
-+
-+              mark_buffer_uptodate(bh, 1);
-+              unlock_buffer(bh);
-+
-+              if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+                      goto cleanup;
-+              brelse(bh);
-+              bh = NULL;
-+
-+              /* correct old index */
-+              if (m) {
-+                      err = ext3_ext_get_access(handle,inode,path+i);
-+                      if (err)
-+                              goto cleanup;
-+                      path[i].p_hdr->e_num -= m;
-+                      err = ext3_ext_dirty(handle, inode, path + i);
-+                      if (err)
-+                              goto cleanup;
-+              }
-+
-+              i--;
-+      }
-+
-+      /* insert new index */
-+      if (!err)
-+              err = ext3_ext_insert_index(handle, inode, path + at,
-+                                              border, newblock);
-+
-+cleanup:
-+      if (bh) {
-+              if (buffer_locked(bh))
-+                      unlock_buffer(bh);
-+              brelse(bh);
-+      }
-+
-+      if (err) {
-+              /* free all allocated blocks in error case */
-+              for (i = 0; i < depth; i++)
-+                      if (!ablocks[i])
-+                              continue;
-+                      ext3_free_blocks(handle, inode, ablocks[i], 1);
-+      }
-+      kfree(ablocks);
-+
-+      return err;
-+}
-+
-+/*
-+ * routine implements tree growing procedure:
-+ *  - allocates new block
-+ *  - moves top-level data (index block or leaf) into the new block
-+ *  - initialize new top-level, creating index that points to the
-+ *    just created block
-+ */
-+static int ext3_ext_grow_indepth(handle_t *handle, struct inode *inode,
-+                                      struct ext3_ext_path *path,
-+                                      struct ext3_extent *newext)
-+{
-+      struct buffer_head *bh;
-+      struct ext3_ext_path *curp = path;
-+      struct ext3_extent_header *neh;
-+      struct ext3_extent_idx *fidx;
-+      int len, err = 0;
-+      long newblock;
-+
-+      /*
-+       * use already allocated by the called block for new root block
-+       */
-+      newblock = newext->e_start++;
-+      if (newext->e_num == 0) {
-+              /* 
-+               * FIXME: if this may happen, then we have to handle
-+               * possible error and free allocated block
-+               */
-+              printk("grow_indepth with zero blocks\n");
-+              newblock = ext3_new_block(handle, inode,
-+                                              newblock, 0, 0, &err);
-+      } else
-+              newext->e_num--;
-+      
-+      bh = sb_getblk(inode->i_sb, newblock);
-+      if (!bh) {
-+              err = -EIO;
-+              ext3_std_error(inode->i_sb, err);
-+              return err;
-+      }
-+      lock_buffer(bh);
-+
-+      if ((err = ext3_journal_get_create_access(handle, bh))) {
-+              unlock_buffer(bh);
-+              goto out;       
-+      }
-+
-+      /* move top-level index/leaf into new block */
-+      len = sizeof(struct ext3_extent_header) +
-+              sizeof(struct ext3_extent) * curp->p_hdr->e_max;
-+      EXT_ASSERT(len >= 0 && len < 4096);
-+      memmove(bh->b_data, curp->p_hdr, len);
-+
-+      /* set size of new block */
-+      neh = (struct ext3_extent_header *) bh->b_data;
-+      neh->e_max = ext3_ext_space_block(inode);
-+      mark_buffer_uptodate(bh, 1);
-+      unlock_buffer(bh);
-+
-+      if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+              goto out;
-+
-+      /* create index in new top-level index: num,max,pointer */
-+      if ((err = ext3_ext_get_access(handle, inode, curp)))
-+              goto out;
-+
-+      curp->p_hdr->e_max = ext3_ext_space_inode_idx(inode);
-+      curp->p_hdr->e_num = 1;
-+      curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
-+      curp->p_idx->e_block = EXT_FIRST_EXTENT(path[0].p_hdr)->e_block;
-+      curp->p_idx->e_leaf = newblock;
-+
-+      neh = (struct ext3_extent_header *) EXT3_I(inode)->i_data;
-+      fidx = EXT_FIRST_INDEX(neh);
-+      ext_debug(inode, "new root: num %d(%d), lblock %d, ptr %d\n",
-+                      neh->e_num, neh->e_max, fidx->e_block, fidx->e_leaf); 
-+
-+      EXT3_I(inode)->i_depth++;
-+      err = ext3_ext_dirty(handle, inode, curp);
-+out:
-+      brelse(bh);
-+
-+      return err;
-+}
-+
-+/*
-+ * routine finds empty index and adds new leaf. if no free index found
-+ * then it requests in-depth growing
-+ */
-+static int ext3_ext_create_new_leaf(handle_t *handle, struct inode *inode,
-+                                      struct ext3_ext_path *path,
-+                                      struct ext3_extent *newext)
-+{
-+      long newblock = newext->e_start;
-+      struct ext3_ext_path *curp;
-+      int depth, i, err = 0;
-+
-+repeat:
-+      i = depth = EXT3_I(inode)->i_depth;
-+      
-+      /* walk up to the tree and look for free index entry */
-+      curp = path + depth;
-+      while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
-+              i--;
-+              curp--;
-+      }
-+
-+      /* we use already allocated block for index block
-+       * so, subsequent data blocks should be contigoues */
-+      if (EXT_HAS_FREE_INDEX(curp)) {
-+              /* if we found index with free entry, then use that
-+               * entry: create all needed subtree and add new leaf */
-+              err = ext3_ext_split(handle, inode, path, newext, i);
-+
-+              /* refill path */
-+              ext3_ext_drop_refs(inode, path);
-+              path = ext3_ext_find_extent(inode, newext->e_block, path);
-+              if (IS_ERR(path))
-+                      err = PTR_ERR(path);
-+      } else {
-+              /* tree is full, time to grow in depth */
-+              err = ext3_ext_grow_indepth(handle, inode, path, newext);
-+
-+              /* refill path */
-+              ext3_ext_drop_refs(inode, path);
-+              path = ext3_ext_find_extent(inode, newext->e_block, path);
-+              if (IS_ERR(path))
-+                      err = PTR_ERR(path);
-+      
-+              /*
-+               * only first (depth 0 -> 1) produces free space
-+               * in all other cases we have to split growed tree
-+               */
-+              depth = EXT3_I(inode)->i_depth;
-+              if (path[depth].p_hdr->e_num == path[depth].p_hdr->e_max) {
-+                      /* now we need split */
-+                      goto repeat;
-+              }
-+      }
-+
-+      if (err)
-+              return err;
-+
-+      /*
-+       * probably we've used some blocks from extent
-+       * let's allocate new block for it
-+       */
-+      if (newext->e_num == 0 && !err) {
-+              newext->e_start =
-+                      ext3_new_block(handle, inode, newblock,
-+                                      0, 0, &err);
-+              if (newext->e_start != 0)
-+                      newext->e_num = 1;
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * returns next allocated block or 0xffffffff
-+ * NOTE: it consider block number from index entry as
-+ * allocated block. thus, index entries have to be consistent
-+ * with leafs
-+ */
-+static inline unsigned ext3_ext_next_allocated_block(struct inode *inode,
-+                                               struct ext3_ext_path *path)
-+{
-+      int depth;
-+
-+      EXT_ASSERT(path != NULL);
-+      depth = path->p_depth;
-+
-+      if (depth == 0 && path->p_ext == NULL)
-+              return 0xffffffff;
-+
-+      /* FIXME: what if index isn't full ?! */
-+      while (depth >= 0) {
-+              if (depth == path->p_depth) {
-+                      /* leaf */
-+                      if (path[depth].p_ext !=
-+                                      EXT_LAST_EXTENT(path[depth].p_hdr))
-+                              return path[depth].p_ext[1].e_block;
-+              } else {
-+                      /* index */
-+                      if (path[depth].p_idx !=
-+                                      EXT_LAST_INDEX(path[depth].p_hdr))
-+                              return path[depth].p_idx[1].e_block;
-+              }
-+              depth--;        
-+      }
-+
-+      return 0xffffffff;
-+}
-+
-+/*
-+ * returns first allocated block from next leaf or 0xffffffff
-+ */
-+static unsigned ext3_ext_next_leaf_block(struct inode *inode,
-+                                               struct ext3_ext_path *path)
-+{
-+      int depth;
-+
-+      EXT_ASSERT(path != NULL);
-+      depth = path->p_depth;
-+
-+      /* zero-tree has no leaf blocks at all */
-+      if (depth == 0)
-+              return 0xffffffff;
-+
-+      /* go to index block */
-+      depth--;
-+      
-+      while (depth >= 0) {
-+              if (path[depth].p_idx !=
-+                              EXT_LAST_INDEX(path[depth].p_hdr))
-+                      return path[depth].p_idx[1].e_block;
-+              depth--;        
-+      }
-+
-+      return 0xffffffff;
-+}
-+
-+/*
-+ * if leaf gets modified and modified extent is first in the leaf
-+ * then we have to correct all indexes above
-+ * TODO: do we need to correct tree in all cases?
-+ */
-+int ext3_ext_correct_indexes(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path)
-+{
-+      int depth = EXT3_I(inode)->i_depth;     
-+      struct ext3_extent_header *eh;
-+      struct ext3_extent *ex;
-+      long border;
-+      int k, err = 0;
-+      
-+      eh = path[depth].p_hdr;
-+      ex = path[depth].p_ext;
-+
-+      EXT_ASSERT(ex);
-+      EXT_ASSERT(eh);
-+      
-+      if (depth == 0) {
-+              /* there is no tree at all */
-+              return 0;
-+      }
-+      
-+      if (ex != EXT_FIRST_EXTENT(eh)) {
-+              /* we correct tree if first leaf got modified only */
-+              return 0;
-+      }
-+      
-+      /*
-+       * TODO: we need correction if border is smaller then current one
-+       */
-+      k = depth - 1;
-+      border = path[depth].p_ext->e_block;
-+      if ((err = ext3_ext_get_access(handle, inode, path + k)))
-+              return err;
-+      path[k].p_idx->e_block = border;
-+      if ((err = ext3_ext_dirty(handle, inode, path + k)))
-+              return err;
-+
-+      while (k--) {
-+              /* change all left-side indexes */
-+              if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
-+                      break;
-+              if ((err = ext3_ext_get_access(handle, inode, path + k)))
-+                      break;
-+              path[k].p_idx->e_block = border;
-+              if ((err = ext3_ext_dirty(handle, inode, path + k)))
-+                      break;
-+      }
-+
-+      return err;
-+}
-+
-+/*
-+ * this routine tries to merge requsted extent into the existing
-+ * extent or inserts requested extent as new one into the tree,
-+ * creating new leaf in no-space case
-+ */
-+int ext3_ext_insert_extent(handle_t *handle, struct inode *inode,
-+                              struct ext3_ext_path *path,
-+                              struct ext3_extent *newext)
-+{
-+      int depth, len;
-+      struct ext3_extent_header * eh;
-+      struct ext3_extent *ex;
-+      struct ext3_extent *nearex; /* nearest extent */
-+      struct ext3_ext_path *npath = NULL;
-+      int err;
-+
-+      depth&nb