Whamcloud - gitweb
- make HEAD from b_post_cmd3
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-htree-path-ops.patch
diff --git a/lustre/kernel_patches/patches/ext3-htree-path-ops.patch b/lustre/kernel_patches/patches/ext3-htree-path-ops.patch
deleted file mode 100644 (file)
index 9a2edbd..0000000
+++ /dev/null
@@ -1,894 +0,0 @@
-Index: iam-src/fs/ext3/namei.c
-===================================================================
---- iam-src.orig/fs/ext3/namei.c       2006-02-12 16:43:57.000000000 +0300
-+++ iam-src/fs/ext3/namei.c    2006-02-12 23:22:12.000000000 +0300
-@@ -83,22 +83,21 @@ static struct buffer_head *ext3_append(h
- #define dxtrace(command)
- #endif
--struct fake_dirent
--{
-+struct fake_dirent {
-       __le32 inode;
-       __le16 rec_len;
-       u8 name_len;
-       u8 file_type;
- };
--struct dx_countlimit
--{
-+struct dx_countlimit {
-       __le16 limit;
-       __le16 count;
- };
--struct dx_entry
--{
-+struct dx_entry; /* incomplete type */
-+
-+struct dx_entry_compat {
-       __le32 hash;
-       __le32 block;
- };
-@@ -109,8 +108,7 @@ struct dx_entry
-  * hash version mod 4 should never be 0.  Sincerely, the paranoia department.
-  */
--struct dx_root
--{
-+struct dx_root {
-       struct fake_dirent dot;
-       char dot_name[4];
-       struct fake_dirent dotdot;
-@@ -124,13 +122,13 @@ struct dx_root
-               u8 unused_flags;
-       }
-       info;
--      struct dx_entry entries[0];
-+      struct {} entries[0];
- };
- struct dx_node
- {
-       struct fake_dirent fake;
--      struct dx_entry entries[0];
-+      struct {} entries[0];
- };
-@@ -147,38 +145,76 @@ struct dx_map_entry
-       u32 offs;
- };
-+struct dx_path;
-+struct dx_param {
-+      size_t       dpo_key_size;
-+      size_t       dpo_ptr_size;
-+      size_t       dpo_node_gap;
-+      size_t       dpo_root_gap;
-+
-+      u32 (*dpo_root_ptr)(struct dx_path *path);
-+      int (*dpo_node_check)(struct dx_path *path,
-+                            struct dx_frame *frame, void *cookie);
-+      int (*dpo_node_init)(struct dx_path *path,
-+                           struct buffer_head *bh, int root);
-+};
-+
- /*
-  * Structure to keep track of a path drilled through htree.
-  */
- struct dx_path {
--      struct inode    *dp_object;
--      struct dx_frame  dp_frames[DX_MAX_TREE_HEIGHT];
--      struct dx_frame *dp_frame;
-+      struct inode         *dp_object;
-+      struct dx_param      *dp_param;
-+      int                   dp_indirect;
-+      struct dx_frame       dp_frames[DX_MAX_TREE_HEIGHT];
-+      struct dx_frame      *dp_frame;
-+      void                 *dp_key_target;
-+      void                 *dp_key;
- };
-+static u32 htree_root_ptr(struct dx_path *p);
-+static int htree_node_check(struct dx_path *path,
-+                          struct dx_frame *frame, void *cookie);
-+static int htree_node_init(struct dx_path *path,
-+                         struct buffer_head *bh, int root);
-+
-+static struct dx_param htree_compat_param = {
-+      .dpo_key_size = sizeof ((struct dx_map_entry *)NULL)->hash,
-+      .dpo_ptr_size = sizeof ((struct dx_map_entry *)NULL)->offs,
-+      .dpo_node_gap = offsetof(struct dx_node, entries),
-+      .dpo_root_gap = offsetof(struct dx_root, entries),
-+
-+      .dpo_root_ptr   = htree_root_ptr,
-+      .dpo_node_check = htree_node_check,
-+      .dpo_node_init  = htree_node_init
-+};
-+
-+
- #ifdef CONFIG_EXT3_INDEX
--static inline unsigned dx_get_block (struct dx_entry *entry);
--static void dx_set_block (struct dx_entry *entry, unsigned value);
--static inline unsigned dx_get_hash (struct dx_entry *entry);
--static void dx_set_hash (struct dx_entry *entry, unsigned value);
--static unsigned dx_get_count (struct dx_entry *entries);
--static unsigned dx_get_limit (struct dx_entry *entries);
--static void dx_set_count (struct dx_entry *entries, unsigned value);
--static void dx_set_limit (struct dx_entry *entries, unsigned value);
--static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
--static unsigned dx_node_limit (struct inode *dir);
--static struct dx_frame *dx_probe(struct dentry *dentry,
--                               struct inode *dir,
--                               struct dx_hash_info *hinfo,
--                               struct dx_path *path,
--                               int *err);
-+static inline unsigned dx_get_block(struct dx_path *p, struct dx_entry *entry);
-+static void dx_set_block(struct dx_path *p,
-+                       struct dx_entry *entry, unsigned value);
-+static inline void *dx_get_key(struct dx_path *p,
-+                             struct dx_entry *entry, void *key);
-+static void dx_set_key(struct dx_path *p, struct dx_entry *entry, void *key);
-+static unsigned dx_get_count(struct dx_entry *entries);
-+static unsigned dx_get_limit(struct dx_entry *entries);
-+static void dx_set_count(struct dx_entry *entries, unsigned value);
-+static void dx_set_limit(struct dx_entry *entries, unsigned value);
-+static unsigned dx_root_limit(struct dx_path *p);
-+static unsigned dx_node_limit(struct dx_path *p);
-+static int dx_probe(struct dentry *dentry,
-+                  struct inode *dir,
-+                  struct dx_hash_info *hinfo,
-+                  struct dx_path *path);
- static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
-                       struct dx_hash_info *hinfo, struct dx_map_entry map[]);
- static void dx_sort_map(struct dx_map_entry *map, unsigned count);
- static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
-               struct dx_map_entry *offsets, int count);
- static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
--static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+static void dx_insert_block (struct dx_path *path,
-+                           struct dx_frame *frame, u32 hash, u32 block);
- static int ext3_htree_next_block(struct inode *dir, __u32 hash,
-                                struct dx_path *path, __u32 *start_hash);
- static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-@@ -186,29 +222,65 @@ static struct buffer_head * ext3_dx_find
- static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
-                            struct inode *inode);
-+static inline void dx_path_init(struct dx_path *path, struct inode *inode);
-+static inline void dx_path_fini(struct dx_path *path);
-+
-+
- /*
-  * Future: use high four bits of block for coalesce-on-delete flags
-  * Mask them off for now.
-  */
--static inline unsigned dx_get_block (struct dx_entry *entry)
-+static inline void *entry_off(struct dx_entry *entry, ptrdiff_t off)
-+{
-+      return (void *)((char *)entry + off);
-+}
-+
-+static inline size_t dx_entry_size(struct dx_path *p)
- {
--      return le32_to_cpu(entry->block) & 0x00ffffff;
-+      return p->dp_param->dpo_key_size + p->dp_param->dpo_ptr_size;
- }
--static inline void dx_set_block (struct dx_entry *entry, unsigned value)
-+static inline struct dx_entry *dx_entry_shift(struct dx_path *p,
-+                                            struct dx_entry *entry, int shift)
- {
--      entry->block = cpu_to_le32(value);
-+      void *e = entry;
-+      return e + shift * dx_entry_size(p);
- }
--static inline unsigned dx_get_hash (struct dx_entry *entry)
-+static inline ptrdiff_t dx_entry_diff(struct dx_path *p,
-+                                    struct dx_entry *e1, struct dx_entry *e2)
- {
--      return le32_to_cpu(entry->hash);
-+      ptrdiff_t diff;
-+
-+      diff = (void *)e1 - (void *)e2;
-+      assert(diff / dx_entry_size(p) * dx_entry_size(p) == diff);
-+      return diff / dx_entry_size(p);
-+}
-+
-+static inline unsigned dx_get_block(struct dx_path *p, struct dx_entry *entry)
-+{
-+      return le32_to_cpu(*(u32 *)entry_off(entry, p->dp_param->dpo_key_size))
-+              & 0x00ffffff;
- }
--static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
-+static inline void dx_set_block(struct dx_path *p,
-+                              struct dx_entry *entry, unsigned value)
- {
--      entry->hash = cpu_to_le32(value);
-+      *(u32*)entry_off(entry, p->dp_param->dpo_key_size) = cpu_to_le32(value);
-+}
-+
-+static inline void *dx_get_key(struct dx_path *p,
-+                             struct dx_entry *entry, void *key)
-+{
-+      memcpy(key, entry, p->dp_param->dpo_key_size);
-+      return key;
-+}
-+
-+static inline void dx_set_key(struct dx_path *p,
-+                            struct dx_entry *entry, void *key)
-+{
-+      memcpy(entry, key, p->dp_param->dpo_key_size);
- }
- static inline unsigned dx_get_count (struct dx_entry *entries)
-@@ -231,17 +303,123 @@ static inline void dx_set_limit (struct 
-       ((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
- }
--static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
-+static inline unsigned dx_root_limit(struct dx_path *p)
- {
--      unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) -
--              EXT3_DIR_REC_LEN(2) - infosize;
--      return 0? 20: entry_space / sizeof(struct dx_entry);
-+      struct dx_param *param = p->dp_param;
-+      unsigned entry_space   = p->dp_object->i_sb->s_blocksize -
-+              param->dpo_root_gap;
-+      return entry_space / (param->dpo_key_size + param->dpo_ptr_size);
-+}
-+
-+static inline unsigned dx_node_limit(struct dx_path *p)
-+{
-+      struct dx_param *param = p->dp_param;
-+      unsigned entry_space   = p->dp_object->i_sb->s_blocksize -
-+              param->dpo_node_gap;
-+      return entry_space / (param->dpo_key_size + param->dpo_ptr_size);
-+}
-+
-+static inline int dx_index_is_compat(struct dx_path *path)
-+{
-+      return path->dp_param == &htree_compat_param;
-+}
-+
-+static struct dx_entry *dx_get_entries(struct dx_path *path, void *data,
-+                                     int root)
-+{
-+      return data +
-+              (root ?
-+               path->dp_param->dpo_root_gap : path->dp_param->dpo_node_gap);
-+}
-+
-+static struct dx_entry *dx_node_get_entries(struct dx_path *path,
-+                                          struct dx_frame *frame)
-+{
-+      return dx_get_entries(path,
-+                            frame->bh->b_data, frame == path->dp_frames);
-+}
-+
-+static u32 htree_root_ptr(struct dx_path *path)
-+{
-+      return 0;
-+}
-+
-+struct htree_cookie {
-+      struct dx_hash_info *hinfo;
-+      struct dentry       *dentry;
-+};
-+
-+static int htree_node_check(struct dx_path *path, struct dx_frame *frame,
-+                          void *cookie)
-+{
-+      void *data;
-+      struct dx_entry *entries;
-+      struct super_block *sb;
-+
-+      data = frame->bh->b_data;
-+      entries = dx_node_get_entries(path, frame);
-+      sb = path->dp_object->i_sb;
-+      if (frame == path->dp_frames) {
-+              /* root node */
-+              struct dx_root *root;
-+              struct htree_cookie *hc = cookie;
-+
-+              root = data;
-+              if (root->info.hash_version != DX_HASH_TEA &&
-+                  root->info.hash_version != DX_HASH_HALF_MD4 &&
-+                  root->info.hash_version != DX_HASH_R5 &&
-+                  root->info.hash_version != DX_HASH_LEGACY) {
-+                      ext3_warning(sb, __FUNCTION__,
-+                                   "Unrecognised inode hash code %d",
-+                                   root->info.hash_version);
-+                      return ERR_BAD_DX_DIR;
-+              }
-+
-+              if (root->info.unused_flags & 1) {
-+                      ext3_warning(sb, __FUNCTION__,
-+                                   "Unimplemented inode hash flags: %#06x",
-+                                   root->info.unused_flags);
-+                      return ERR_BAD_DX_DIR;
-+              }
-+
-+              path->dp_indirect = root->info.indirect_levels;
-+              if (path->dp_indirect > DX_MAX_TREE_HEIGHT - 1) {
-+                      ext3_warning(sb, __FUNCTION__,
-+                                   "Unimplemented inode hash depth: %#06x",
-+                                   root->info.indirect_levels);
-+                      return ERR_BAD_DX_DIR;
-+              }
-+
-+              assert((char *)entries == (((char *)&root->info) +
-+                                         root->info.info_length));
-+              assert(dx_get_limit(entries) == dx_root_limit(path));
-+
-+              hc->hinfo->hash_version = root->info.hash_version;
-+              hc->hinfo->seed = EXT3_SB(sb)->s_hash_seed;
-+              if (hc->dentry)
-+                      ext3fs_dirhash(hc->dentry->d_name.name,
-+                                     hc->dentry->d_name.len, hc->hinfo);
-+              path->dp_key_target = &hc->hinfo->hash;
-+      } else {
-+              /* non-root index */
-+              assert(entries == data + path->dp_param->dpo_node_gap);
-+              assert(dx_get_limit(entries) == dx_node_limit(path));
-+      }
-+      frame->entries = frame->at = entries;
-+      return 0;
- }
--static inline unsigned dx_node_limit (struct inode *dir)
-+static int htree_node_init(struct dx_path *path,
-+                         struct buffer_head *bh, int root)
- {
--      unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0);
--      return 0? 22: entry_space / sizeof(struct dx_entry);
-+      struct dx_node *node;
-+
-+      assert(!root);
-+
-+      node = (void *)bh->b_data;
-+      node->fake.rec_len = cpu_to_le16(path->dp_object->i_sb->s_blocksize);
-+      node->fake.inode = 0;
-+      return 0;
- }
- /*
-@@ -327,123 +505,101 @@ struct stats dx_show_entries(struct dx_h
- }
- #endif /* DX_DEBUG */
--/*
-- * Probe for a directory leaf block to search.
-- *
-- * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
-- * error in the directory index, and the caller should fall back to
-- * searching the directory normally.  The callers of dx_probe **MUST**
-- * check for this error code, and make sure it never gets reflected
-- * back to userspace.
-- */
--static struct dx_frame *
--dx_probe(struct dentry *dentry, struct inode *dir,
--       struct dx_hash_info *hinfo, struct dx_path *path, int *err)
--{
--      unsigned count, indirect;
--      struct dx_entry *at, *entries, *p, *q, *m;
--      struct dx_root *root;
--      struct buffer_head *bh;
--      struct dx_frame *frame = path->dp_frames;
--      u32 hash;
-+static int dx_lookup(struct dx_path *path, void *cookie)
-+{
-+      u32 ptr;
-+      int err;
-+      int i;
--      frame->bh = NULL;
--      if (dentry)
--              dir = dentry->d_parent->d_inode;
--      if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
--              goto fail;
--      root = (struct dx_root *) bh->b_data;
--      if (root->info.hash_version != DX_HASH_TEA &&
--          root->info.hash_version != DX_HASH_HALF_MD4 &&
--          root->info.hash_version != DX_HASH_R5 &&
--          root->info.hash_version != DX_HASH_LEGACY) {
--              ext3_warning(dir->i_sb, __FUNCTION__,
--                           "Unrecognised inode hash code %d", root->info.hash_version);
--              brelse(bh);
--              *err = ERR_BAD_DX_DIR;
--              goto fail;
--      }
--      hinfo->hash_version = root->info.hash_version;
--      hinfo->seed = EXT3_SB(dir->i_sb)->s_hash_seed;
--      if (dentry)
--              ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
--      hash = hinfo->hash;
--
--      if (root->info.unused_flags & 1) {
--              ext3_warning(dir->i_sb, __FUNCTION__,
--                           "Unimplemented inode hash flags: %#06x",
--                           root->info.unused_flags);
--              brelse(bh);
--              *err = ERR_BAD_DX_DIR;
--              goto fail;
--      }
-+      struct dx_param *param;
-+      struct dx_frame *frame;
--      if ((indirect = root->info.indirect_levels) > DX_MAX_TREE_HEIGHT - 1) {
--              ext3_warning(dir->i_sb, __FUNCTION__,
--                           "Unimplemented inode hash depth: %#06x",
--                           root->info.indirect_levels);
--              brelse(bh);
--              *err = ERR_BAD_DX_DIR;
--              goto fail;
--      }
-+      param = path->dp_param;
--      entries = (struct dx_entry *) (((char *)&root->info) +
--                                     root->info.info_length);
--      assert(dx_get_limit(entries) == dx_root_limit(dir,
--                                                    root->info.info_length));
--      dxtrace (printk("Look up %x", hash));
--      while (1)
--      {
-+      for (frame = path->dp_frames, i = 0,
-+           ptr = param->dpo_root_ptr(path); i <= path->dp_indirect;
-+           ptr = dx_get_block(path, frame->at), ++frame, ++i) {
-+              struct dx_entry *entries;
-+              struct dx_entry *p;
-+              struct dx_entry *q;
-+              struct dx_entry *m;
-+              unsigned count;
-+
-+              frame->bh = ext3_bread(NULL, path->dp_object, ptr, 0, &err);
-+              if (frame->bh == NULL) {
-+                      err = -EIO;
-+                      break;
-+              }
-+              err = param->dpo_node_check(path, frame, cookie);
-+              if (err != 0)
-+                      break;
-+
-+              entries = frame->entries;
-               count = dx_get_count(entries);
--              assert (count && count <= dx_get_limit(entries));
--              p = entries + 1;
--              q = entries + count - 1;
--              while (p <= q)
--              {
--                      m = p + (q - p)/2;
-+              assert(count && count <= dx_get_limit(entries));
-+              p = dx_entry_shift(path, entries, 1);
-+              q = dx_entry_shift(path, entries, count - 1);
-+              while (p <= q) {
-+                      m = dx_entry_shift(path,
-+                                         p, dx_entry_diff(path, q, p) / 2);
-                       dxtrace(printk("."));
--                      if (dx_get_hash(m) > hash)
--                              q = m - 1;
-+                      if (memcmp(dx_get_key(path, m, path->dp_key),
-+                                 path->dp_key_target,
-+                                 param->dpo_key_size) > 0)
-+                              q = dx_entry_shift(path, m, -1);
-                       else
--                              p = m + 1;
-+                              p = dx_entry_shift(path, m, +1);
-               }
--              if (0) // linear search cross check
--              {
-+              frame->at = dx_entry_shift(path, p, -1);
-+              if (1) { // linear search cross check
-                       unsigned n = count - 1;
-+                      struct dx_entry *at;
-+
-                       at = entries;
--                      while (n--)
--                      {
-+                      while (n--) {
-                               dxtrace(printk(","));
--                              if (dx_get_hash(++at) > hash)
--                              {
--                                      at--;
-+                              at = dx_entry_shift(path, at, +1);
-+                              if (memcmp(dx_get_key(path, at, path->dp_key),
-+                                         path->dp_key_target,
-+                                         param->dpo_key_size) > 0) {
-+                                      at = dx_entry_shift(path, at, -1);
-                                       break;
-                               }
-                       }
--                      assert (at == p - 1);
-+                      assert(at == frame->at);
-               }
--
--              at = p - 1;
--              dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
--              frame->bh = bh;
--              frame->entries = entries;
--              frame->at = at;
--              if (!indirect--)
--                      return path->dp_frame = frame;
--              if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
--                      goto fail2;
--              at = entries = ((struct dx_node *) bh->b_data)->entries;
--              assert (dx_get_limit(entries) == dx_node_limit (dir));
--              frame++;
--      }
--fail2:
--      while (frame >= path->dp_frames) {
--              brelse(frame->bh);
--              frame--;
-       }
--fail:
--      return NULL;
-+      if (err != 0)
-+              dx_path_fini(path);
-+      path->dp_frame = --frame;
-+      return err;
-+}
-+
-+/*
-+ * Probe for a directory leaf block to search.
-+ *
-+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
-+ * error in the directory index, and the caller should fall back to
-+ * searching the directory normally.  The callers of dx_probe **MUST**
-+ * check for this error code, and make sure it never gets reflected
-+ * back to userspace.
-+ */
-+static int dx_probe(struct dentry *dentry, struct inode *dir,
-+                  struct dx_hash_info *hinfo, struct dx_path *path)
-+{
-+      int err;
-+      __u32 hash_storage;
-+      struct htree_cookie hc = {
-+              .dentry = dentry,
-+              .hinfo  = hinfo
-+      };
-+
-+      assert(dx_index_is_compat(path));
-+      path->dp_key = &hash_storage;
-+      err = dx_lookup(path, &hc);
-+      assert(err != 0 || path->dp_frames[path->dp_indirect].bh != NULL);
-+      return err;
- }
- static inline void dx_path_init(struct dx_path *path, struct inode *inode)
-@@ -458,8 +614,10 @@ static inline void dx_path_fini(struct d
-       int i;
-       for (i = 0; i < ARRAY_SIZE(path->dp_frames); i--) {
--              if (path->dp_frames[i].bh != NULL)
-+              if (path->dp_frames[i].bh != NULL) {
-                       brelse(path->dp_frames[i].bh);
-+                      path->dp_frames[i].bh = NULL;
-+              }
-       }
- }
-@@ -488,6 +646,8 @@ static int ext3_htree_next_block(struct 
-       int err, num_frames = 0;
-       __u32 bhash;
-+      assert(dx_index_is_compat(path));
-+
-       p = path->dp_frame;
-       /*
-        * Find the next leaf page by incrementing the frame pointer.
-@@ -497,7 +657,9 @@ static int ext3_htree_next_block(struct 
-        * nodes need to be read.
-        */
-       while (1) {
--              if (++(p->at) < p->entries + dx_get_count(p->entries))
-+              p->at = dx_entry_shift(path, p->at, +1);
-+              if (p->at < dx_entry_shift(path, p->entries,
-+                                         dx_get_count(p->entries)))
-                       break;
-               if (p == path->dp_frames)
-                       return 0;
-@@ -512,7 +674,7 @@ static int ext3_htree_next_block(struct 
-        * desired contiuation hash.  If it doesn't, return since
-        * there's no point to read in the successive index pages.
-        */
--      bhash = dx_get_hash(p->at);
-+      dx_get_key(path, p->at, &bhash);
-       if (start_hash)
-               *start_hash = bhash;
-       if ((hash & 1) == 0) {
-@@ -524,12 +686,13 @@ static int ext3_htree_next_block(struct 
-        * block so no check is necessary
-        */
-       while (num_frames--) {
--              if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), 0, &err)))
-+              if (!(bh = ext3_bread(NULL, dir,
-+                                    dx_get_block(path, p->at), 0, &err)))
-                       return err; /* Failure */
-               ++p;
-               brelse (p->bh);
-               p->bh = bh;
--              p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
-+              p->at = p->entries = dx_node_get_entries(path, p);
-       }
-       return 1;
- }
-@@ -609,6 +772,7 @@ int ext3_htree_fill_tree(struct file *di
-                      start_minor_hash));
-       dir = dir_file->f_dentry->d_inode;
-       dx_path_init(&path, dir);
-+      path.dp_param = &htree_compat_param;
-       if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) {
-               hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
-               hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
-@@ -619,7 +783,8 @@ int ext3_htree_fill_tree(struct file *di
-       }
-       hinfo.hash = start_hash;
-       hinfo.minor_hash = 0;
--      if (!dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, &path, &err))
-+      err = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, &path);
-+      if (err != 0)
-               return err;
-       /* Add '.' and '..' from the htree header */
-@@ -634,7 +799,7 @@ int ext3_htree_fill_tree(struct file *di
-       }
-       while (1) {
--              block = dx_get_block(path.dp_frame->at);
-+              block = dx_get_block(&path, path.dp_frame->at);
-               ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo,
-                                            start_hash, start_minor_hash);
-               if (ret < 0) {
-@@ -722,17 +887,19 @@ static void dx_sort_map (struct dx_map_e
-       } while(more);
- }
--static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
-+static void dx_insert_block(struct dx_path *path,
-+                          struct dx_frame *frame, u32 hash, u32 block)
- {
-       struct dx_entry *entries = frame->entries;
--      struct dx_entry *old = frame->at, *new = old + 1;
-+      struct dx_entry *old = frame->at, *new = dx_entry_shift(path, old, +1);
-       int count = dx_get_count(entries);
-       assert(count < dx_get_limit(entries));
--      assert(old < entries + count);
--      memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
--      dx_set_hash(new, hash);
--      dx_set_block(new, block);
-+      assert(old < dx_entry_shift(path, entries, count));
-+      memmove(dx_entry_shift(path, new, 1), new,
-+              (char *)dx_entry_shift(path, entries, count) - (char *)new);
-+      dx_set_key(path, new, &hash);
-+      dx_set_block(path, new, block);
-       dx_set_count(entries, count + 1);
- }
- #endif
-@@ -934,7 +1101,9 @@ static struct buffer_head * ext3_dx_find
-       struct dx_hash_info     hinfo;
-       u32 hash;
-       struct dx_path path;
--      struct dx_entry dummy_dot;
-+      struct dx_entry_compat dummy_dot = {
-+              .block = 0
-+      };
-       struct ext3_dir_entry_2 *de, *top;
-       struct buffer_head *bh;
-       unsigned long block;
-@@ -944,19 +1113,21 @@ static struct buffer_head * ext3_dx_find
-       struct inode *dir = dentry->d_parent->d_inode;
-       dx_path_init(&path, dir);
-+      path.dp_param = &htree_compat_param;
-+      
-       sb = dir->i_sb;
-       /* NFS may look up ".." - look at dx_root directory block */
-       if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
--              if (!(dx_probe(dentry, NULL, &hinfo, &path, err)))
-+              *err = dx_probe(dentry, NULL, &hinfo, &path);
-+              if (*err != 0)
-                       return NULL;
-       } else {
--              path.dp_frame->bh = NULL;                       /* for dx_path_fini() */
--              path.dp_frame->at = &dummy_dot;         /* hack for zero entry*/
--              dx_set_block(path.dp_frame->at, 0);     /* dx_root block is 0 */
-+              path.dp_frame->bh = NULL;               /* for dx_path_fini() */
-+              path.dp_frame->at = (void *)&dummy_dot; /* hack for zero entry*/
-       }
-       hash = hinfo.hash;
-       do {
--              block = dx_get_block(path.dp_frame->at);
-+              block = dx_get_block(&path, path.dp_frame->at);
-               if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
-                       goto errout;
-               de = (struct ext3_dir_entry_2 *) bh->b_data;
-@@ -1115,10 +1286,11 @@ static struct ext3_dir_entry_2* dx_pack_
- /* Allocate new node, and split leaf node @bh into it, inserting new pointer
-  * into parent node identified by @frame */
--static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
-+static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct dx_path *path,
-                       struct buffer_head **bh,struct dx_frame *frame,
-                       struct dx_hash_info *hinfo, int *error)
- {
-+      struct inode *dir = path->dp_object;
-       unsigned blocksize = dir->i_sb->s_blocksize;
-       unsigned count, continued;
-       struct buffer_head *bh2;
-@@ -1180,7 +1352,7 @@ static struct ext3_dir_entry_2 *do_split
-               swap(*bh, bh2);
-               de = de2;
-       }
--      dx_insert_block (frame, hash2 + continued, newblock);
-+      dx_insert_block(path, frame, hash2 + continued, newblock);
-       err = ext3_journal_dirty_metadata (handle, bh2);
-       if (err)
-               goto journal_error;
-@@ -1315,6 +1487,7 @@ static int make_indexed_dir(handle_t *ha
-       struct fake_dirent *fde;
-       dx_path_init(&path, dir);
-+      path.dp_param = &htree_compat_param;
-       blocksize =  dir->i_sb->s_blocksize;
-       dxtrace(printk("Creating index\n"));
-       retval = ext3_journal_get_write_access(handle, bh);
-@@ -1350,10 +1523,10 @@ static int make_indexed_dir(handle_t *ha
-       root->info.info_length = sizeof(root->info);
-       root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
-       root->info.hash_version = DX_HASH_R5;
--      entries = root->entries;
--      dx_set_block (entries, 1);
-+      entries = (void *)root->entries;
-+      dx_set_block (&path, entries, 1);
-       dx_set_count (entries, 1);
--      dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
-+      dx_set_limit (entries, dx_root_limit(&path));
-       /* Initialize as for dx_probe */
-       hinfo.hash_version = root->info.hash_version;
-@@ -1363,7 +1536,7 @@ static int make_indexed_dir(handle_t *ha
-       path.dp_frame->at = entries;
-       path.dp_frame->bh = bh;
-       bh = bh2;
--      de = do_split(handle,dir, &bh, path.dp_frame, &hinfo, &retval);
-+      de = do_split(handle, &path, &bh, path.dp_frame, &hinfo, &retval);
-       dx_path_fini(&path);
-       if (!de)
-               return retval;
-@@ -1446,8 +1619,8 @@ static int ext3_dx_add_entry(handle_t *h
-                            struct inode *inode)
- {
-       struct dx_path path;
-+      struct dx_param *param;
-       struct dx_frame *frame, *safe;
--      struct dx_node *node2;
-       struct dx_entry *entries;   /* old block contents */
-       struct dx_entry *entries2;  /* new block contents */
-       struct dx_hash_info hinfo;
-@@ -1463,7 +1636,10 @@ static int ext3_dx_add_entry(handle_t *h
-       size_t isize;
-       dx_path_init(&path, dir);
--      if (!dx_probe(dentry, NULL, &hinfo, &path, &err))
-+      param = path.dp_param = &htree_compat_param;
-+
-+      err = dx_probe(dentry, NULL, &hinfo, &path);
-+      if (err != 0)
-               return err;
-       frame = path.dp_frame;
-       entries = frame->entries;
-@@ -1471,7 +1647,8 @@ static int ext3_dx_add_entry(handle_t *h
-       /* XXX nikita: global serialization! */
-       isize = dir->i_size;
--      if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
-+      if (!(bh = ext3_bread(handle, dir,
-+                            dx_get_block(&path, frame->at), 0, &err)))
-               goto cleanup;
-       BUFFER_TRACE(bh, "get_write_access");
-@@ -1519,12 +1696,9 @@ static int ext3_dx_add_entry(handle_t *h
-        * transaction... */
-       for (frame = safe + 1, i = 0; i < nr_splet; ++i, ++frame) {
-               bh_new[i] = ext3_append (handle, dir, &newblock[i], &err);
--              if (!bh_new[i])
-+              if (!bh_new[i] ||
-+                  param->dpo_node_init(&path, bh_new[i], 0) != 0)
-                       goto cleanup;
--              node2 = (struct dx_node *)(bh_new[i]->b_data);
--              entries2 = node2->entries;
--              node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
--              node2->fake.inode = 0;
-               BUFFER_TRACE(frame->bh, "get_write_access");
-               err = ext3_journal_get_write_access(handle, frame->bh);
-               if (err)
-@@ -1545,11 +1719,10 @@ static int ext3_dx_add_entry(handle_t *h
-               entries = frame->entries;
-               count = dx_get_count(entries);
--              idx = frame->at - entries;
-+              idx = dx_entry_diff(&path, frame->at, entries);
-               bh2 = bh_new[i];
--              node2 = (struct dx_node *)(bh2->b_data);
--              entries2 = node2->entries;
-+              entries2 = dx_get_entries(&path, bh2->b_data, 0);
-               if (frame == path.dp_frames) {
-                       /* splitting root node. Tricky point:
-@@ -1571,19 +1744,19 @@ static int ext3_dx_add_entry(handle_t *h
-                       indirects = root->info.indirect_levels;
-                       dxtrace(printk("Creating new root %d\n", indirects));
-                       memcpy((char *) entries2, (char *) entries,
--                             count * sizeof(struct dx_entry));
--                      dx_set_limit(entries2, dx_node_limit(dir));
-+                             count * dx_entry_size(&path));
-+                      dx_set_limit(entries2, dx_node_limit(&path));
-                       /* Set up root */
-                       dx_set_count(entries, 1);
--                      dx_set_block(entries + 0, newblock[i]);
-+                      dx_set_block(&path, entries, newblock[i]);
-                       root->info.indirect_levels = indirects + 1;
-                       /* Shift frames in the path */
-                       memmove(frames + 2, frames + 1,
-                               (sizeof path.dp_frames) - 2 * sizeof frames[0]);
-                       /* Add new access path frame */
--                      frames[1].at = entries2 + idx;
-+                      frames[1].at = dx_entry_shift(&path, entries2, idx);
-                       frames[1].entries = entries = entries2;
-                       frames[1].bh = bh2;
-                       ++ frame;
-@@ -1594,23 +1767,30 @@ static int ext3_dx_add_entry(handle_t *h
-               } else {
-                       /* splitting non-root index node. */
-                       unsigned count1 = count/2, count2 = count - count1;
--                      unsigned hash2 = dx_get_hash(entries + count1);
-+                      unsigned hash2;
-+
-+                      dx_get_key(&path,
-+                                 dx_entry_shift(&path, entries, count1),
-+                                 &hash2);
-+
-                       dxtrace(printk("Split index %i/%i\n", count1, count2));
--                      memcpy ((char *) entries2, (char *) (entries + count1),
--                              count2 * sizeof(struct dx_entry));
-+                      memcpy ((char *) entries2,
-+                              (char *) dx_entry_shift(&path, entries, count1),
-+                              count2 * dx_entry_size(&path));
-                       dx_set_count (entries, count1);
-                       dx_set_count (entries2, count2);
--                      dx_set_limit (entries2, dx_node_limit(dir));
-+                      dx_set_limit (entries2, dx_node_limit(&path));
-                       /* Which index block gets the new entry? */
-                       if (idx >= count1) {
--                              frame->at = entries2 + idx - count1;
-+                              frame->at = dx_entry_shift(&path, entries2,
-+                                                         idx - count1);
-                               frame->entries = entries = entries2;
-                               swap(frame->bh, bh2);
-                               bh_new[i] = bh2;
-                       }
--                      dx_insert_block (frame - 1, hash2, newblock[i]);
-+                      dx_insert_block(&path, frame - 1, hash2, newblock[i]);
-                       dxtrace(dx_show_index ("node", frame->entries));
-                       dxtrace(dx_show_index ("node",
-                              ((struct dx_node *) bh2->b_data)->entries));
-@@ -1619,7 +1799,7 @@ static int ext3_dx_add_entry(handle_t *h
-                               goto journal_error;
-               }
-       }
--      de = do_split(handle, dir, &bh, --frame, &hinfo, &err);
-+      de = do_split(handle, &path, &bh, --frame, &hinfo, &err);
-       if (!de)
-               goto cleanup;
-       err = add_dirent_to_buf(handle, dentry, inode, de, bh);