Whamcloud - gitweb
iam: latest fixes
authornikita <nikita>
Tue, 20 Jun 2006 22:57:05 +0000 (22:57 +0000)
committernikita <nikita>
Tue, 20 Jun 2006 22:57:05 +0000 (22:57 +0000)
ldiskfs/ldiskfs/Makefile.in
lustre/kernel_patches/patches/ext3-iam-separate.patch
lustre/kernel_patches/patches/ext3-iam-uapi.patch
lustre/ldiskfs/Makefile.in
lustre/tests/iam_ut
lustre/tests/iam_ut.c

index 9c27db4..5a05bf8 100644 (file)
@@ -11,7 +11,7 @@ ext3_headers := $(wildcard @LINUX@/fs/ext3/*.h)
 linux_headers := $(wildcard @LINUX@/include/linux/ext3*.h)
 
 ext3_sources := $(filter-out %.mod.c,$(wildcard @LINUX@/fs/ext3/*.c))
-new_sources := iopen.c iopen.h extents.c mballoc.c iam.c iam_lfix.c iam-uapi.c
+new_sources := iopen.c iopen.h extents.c mballoc.c iam.c iam_lfix.c iam_htree.c iam-uapi.c
 new_headers := ext3_extents.h
 ldiskfs_patched_sources := $(notdir $(ext3_sources) $(ext3_headers)) $(new_sources) $(new_headers)
 ldiskfs_sources := $(ldiskfs_patched_sources)
index c8373e3..09815ea 100644 (file)
@@ -1,7 +1,7 @@
 Index: iam/fs/ext3/Makefile
 ===================================================================
 --- iam.orig/fs/ext3/Makefile  2006-05-31 20:24:32.000000000 +0400
-+++ iam/fs/ext3/Makefile       2006-06-16 14:39:59.000000000 +0400
++++ iam/fs/ext3/Makefile       2006-06-21 02:00:09.000000000 +0400
 @@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
  
  ext3-y        := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
@@ -14,8 +14,8 @@ Index: iam/fs/ext3/Makefile
 Index: iam/fs/ext3/iam.c
 ===================================================================
 --- iam.orig/fs/ext3/iam.c     2004-04-06 17:27:52.000000000 +0400
-+++ iam/fs/ext3/iam.c  2006-06-15 19:51:50.000000000 +0400
-@@ -0,0 +1,1246 @@
++++ iam/fs/ext3/iam.c  2006-06-21 01:19:28.000000000 +0400
+@@ -0,0 +1,1244 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
 + *
@@ -227,8 +227,6 @@ Index: iam/fs/ext3/iam.c
 +      }
 +}
 +
-+extern struct iam_descr htree_compat_param;
-+
 +void iam_path_compat_init(struct iam_path_compat *path, struct inode *inode)
 +{
 +      int i;
@@ -738,7 +736,7 @@ Index: iam/fs/ext3/iam.c
 + */
 +void iam_it_put(struct iam_iterator *it)
 +{
-+        if (it->ii_state > IAM_IT_DETACHED) {
++        if (it->ii_state != IAM_IT_DETACHED) {
 +                it->ii_state = IAM_IT_DETACHED;
 +              iam_leaf_fini(&it->ii_path.ip_leaf);
 +                iam_it_unlock(it);
@@ -1262,19 +1260,18 @@ Index: iam/fs/ext3/iam.c
 +}
 +EXPORT_SYMBOL(iam_delete);
 +
-Index: iam/fs/ext3/iam_lfix.c
+Index: iam/fs/ext3/iam_htree.c
 ===================================================================
---- iam.orig/fs/ext3/iam_lfix.c        2004-04-06 17:27:52.000000000 +0400
-+++ iam/fs/ext3/iam_lfix.c     2006-06-15 19:55:41.000000000 +0400
-@@ -0,0 +1,613 @@
+--- iam.orig/fs/ext3/iam_htree.c       2004-04-06 17:27:52.000000000 +0400
++++ iam/fs/ext3/iam_htree.c    2006-06-21 00:09:07.000000000 +0400
+@@ -0,0 +1,582 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
 + *
-+ *  iam_lfix.c
-+ *  implementation of iam format for fixed size records.
++ *  iam_htree.c
++ *  implementation of iam format for ext3/htree.
 + *
 + *  Copyright (c) 2006 Cluster File Systems, Inc.
-+ *   Author: Wang Di <wangdi@clusterfs.com>
 + *   Author: Nikita Danilov <nikita@clusterfs.com>
 + *
 + *   This file is part of the Lustre file system, http://www.lustre.org
@@ -1296,9 +1293,11 @@ Index: iam/fs/ext3/iam_lfix.c
 + *   license text for more details.
 + */
 +
++#if 0
++
 +#include <linux/types.h>
 +#include <linux/jbd.h>
-+/* ext3_error() */
++/* ext3_error(), EXT3_DIR_ROUND() */
 +#include <linux/ext3_fs.h>
 +
 +#include <linux/lustre_iam.h>
@@ -1306,32 +1305,39 @@ Index: iam/fs/ext3/iam_lfix.c
 +#include <libcfs/libcfs.h>
 +#include <libcfs/kp30.h>
 +
-+/*
-+ * Leaf operations.
-+ */
-+
-+enum {
-+        IAM_LEAF_HEADER_MAGIC = 0x1976 /* This is duplicated in
-+                                        * lustre/utils/create_iam.c */
-+};
-+
-+/* This is duplicated in lustre/utils/create_iam.c */
-+struct iam_leaf_head {
-+        __le16 ill_magic;
-+        __le16 ill_count;
++struct htree_dirent {
++        __le32 hd_ino;
++        __le16 hd_reclen;
++        u8     hd_namelen;
++        u8     hd_type;
++        char   hd_name[0];
 +};
 +
-+static inline int iam_lfix_entry_size(const struct iam_leaf *l)
++static inline struct iam_path_compat *getipc(const struct iam_leaf *folio)
 +{
-+        return iam_leaf_descr(l)->id_key_size + iam_leaf_descr(l)->id_rec_size;
++        struct iam_path *path;
++
++        path = iam_leaf_path(folio);
++        assert(dx_index_is_compat(path));
++        assert(path->ip_data != NULL);
++        return container_of(path->ip_data, struct iam_path_compat, ipc_descr);
 +}
 +
-+static inline struct iam_lentry *
-+iam_lfix_shift(const struct iam_leaf *l, struct iam_lentry *entry, int shift)
++static inline size_t recsize(const struct iam_leaf *folio, size_t namelen)
 +{
-+        return (void *)entry + shift * iam_lfix_entry_size(l);
++        return
++                namelen +
++                offsetof(struct htree_dirent, hd_name) +
++                getipc(folio)
++
++#define EXT3_DIR_REC_LEN(name_len)    (((name_len) + 8 + EXT3_DIR_ROUND) & \
++                                       ~EXT3_DIR_ROUND)
 +}
 +
++/*
++ * Leaf operations.
++ */
++
 +static inline struct iam_key *iam_leaf_key_at(struct iam_lentry *entry)
 +{
 +        return (struct iam_key *)entry;
@@ -1358,7 +1364,7 @@ Index: iam/fs/ext3/iam_lfix.c
 +
 +        free_space = iam_leaf_container(leaf)->ic_object->i_sb->s_blocksize;
 +        free_space -= sizeof(struct iam_leaf_head);
-+        return free_space / iam_lfix_entry_size(leaf);
++        return free_space / iam_htree_entry_size(leaf);
 +}
 +
 +static int lentry_count_get(const struct iam_leaf *leaf)
@@ -1372,45 +1378,45 @@ Index: iam/fs/ext3/iam_lfix.c
 +        iam_get_head(leaf)->ill_count = cpu_to_le16(count);
 +}
 +
-+static struct iam_lentry *iam_lfix_get_end(const struct iam_leaf *l);
++static struct iam_lentry *iam_htree_get_end(const struct iam_leaf *l);
 +
 +static int iam_leaf_at_rec(const struct iam_leaf *folio)
 +{
 +        return
 +                iam_get_lentries(folio) <= folio->il_at &&
-+                folio->il_at < iam_lfix_get_end(folio);
++                folio->il_at < iam_htree_get_end(folio);
 +}
 +
 +/*This func is for flat key, for those keys,
 + *which are not stored explicitly
 + *it would be decrypt in the key buffer
 + */
-+struct iam_key *iam_lfix_key(const struct iam_leaf *l, struct iam_key *key)
++struct iam_key *iam_htree_key(const struct iam_leaf *l, struct iam_key *key)
 +{
 +        void *ie = l->il_at;
 +        assert(iam_leaf_at_rec(l));
 +        return (struct iam_key*)ie;
 +}
 +
-+static void iam_lfix_start(struct iam_leaf *l)
++static void iam_htree_start(struct iam_leaf *l)
 +{
 +        l->il_at = iam_get_lentries(l);
 +}
 +
-+static inline ptrdiff_t iam_lfix_diff(const struct iam_leaf *l,
++static inline ptrdiff_t iam_htree_diff(const struct iam_leaf *l,
 +                                      const struct iam_lentry *e1,
 +                                      const struct iam_lentry *e2)
 +{
 +        ptrdiff_t diff;
 +        int esize;
 +
-+        esize = iam_lfix_entry_size(l);
++        esize = iam_htree_entry_size(l);
 +        diff = (void *)e1 - (void *)e2;
 +        assert(diff / esize * esize == diff);
 +        return diff / esize;
 +}
 +
-+static int iam_lfix_init(struct iam_leaf *l)
++static int iam_htree_init(struct iam_leaf *l)
 +{
 +        int result;
 +        struct iam_leaf_head *ill;
@@ -1440,34 +1446,34 @@ Index: iam/fs/ext3/iam_lfix.c
 +        return result;
 +}
 +
-+static void iam_lfix_fini(struct iam_leaf *l)
++static void iam_htree_fini(struct iam_leaf *l)
 +{
 +        l->il_entries = l->il_at = NULL;
 +        return;
 +}
 +
-+static struct iam_lentry *iam_lfix_get_end(const struct iam_leaf *l)
++static struct iam_lentry *iam_htree_get_end(const struct iam_leaf *l)
 +{
 +        int count = lentry_count_get(l);
-+        struct iam_lentry *ile = iam_lfix_shift(l, l->il_entries, count);
++        struct iam_lentry *ile = iam_htree_shift(l, l->il_entries, count);
 +
 +        return ile;
 +}
 +
-+struct iam_rec *iam_lfix_rec(const struct iam_leaf *l)
++struct iam_rec *iam_htree_rec(const struct iam_leaf *l)
 +{
 +        void *e = l->il_at;
 +        assert(iam_leaf_at_rec(l));
 +        return e + iam_leaf_descr(l)->id_key_size;
 +}
 +
-+static void iam_lfix_next(struct iam_leaf *l)
++static void iam_htree_next(struct iam_leaf *l)
 +{
 +        assert(iam_leaf_at_rec(l));
-+        l->il_at = iam_lfix_shift(l, l->il_at, 1);
++        l->il_at = iam_htree_shift(l, l->il_at, 1);
 +}
 +
-+static int iam_lfix_lookup(struct iam_leaf *l, const struct iam_key *k)
++static int iam_htree_lookup(struct iam_leaf *l, const struct iam_key *k)
 +{
 +        struct iam_lentry *p, *q, *m, *t;
 +        struct iam_container *c;
@@ -1482,7 +1488,7 @@ Index: iam/fs/ext3/iam_lfix.c
 +        c = iam_leaf_container(l);
 +
 +        p = l->il_entries;
-+        q = iam_lfix_shift(l, p, count - 1);
++        q = iam_htree_shift(l, p, count - 1);
 +        if (iam_keycmp(c, k, iam_leaf_key_at(p)) < 0) {
 +                /*
 +                 * @k is less than the least key in the leaf
@@ -1495,8 +1501,8 @@ Index: iam/fs/ext3/iam_lfix.c
 +                /*
 +                 * EWD1293
 +                 */
-+                while (iam_lfix_shift(l, p, 1) != q) {
-+                        m = iam_lfix_shift(l, p, iam_lfix_diff(l, q, p) / 2);
++                while (iam_htree_shift(l, p, 1) != q) {
++                        m = iam_htree_shift(l, p, iam_htree_diff(l, q, p) / 2);
 +                        assert(p < m && m < q);
 +                        (iam_keycmp(c, iam_leaf_key_at(m), k) <= 0 ? p : q) = m;
 +                }
@@ -1506,7 +1512,7 @@ Index: iam/fs/ext3/iam_lfix.c
 +                 * skip over records with duplicate keys.
 +                 */
 +                while (p > l->il_entries) {
-+                        t = iam_lfix_shift(l, p, -1);
++                        t = iam_htree_shift(l, p, -1);
 +                        if (iam_keycmp(c, iam_leaf_key_at(t), k) == 0)
 +                                p = t;
 +                        else
@@ -1519,19 +1525,19 @@ Index: iam/fs/ext3/iam_lfix.c
 +        return result;
 +}
 +
-+static void iam_lfix_key_set(struct iam_leaf *l, const struct iam_key *k)
++static void iam_htree_key_set(struct iam_leaf *l, const struct iam_key *k)
 +{
 +        assert(iam_leaf_at_rec(l));
 +        iam_keycpy(iam_leaf_container(l), iam_leaf_key_at(l->il_at), k);
 +}
 +
-+static void iam_lfix_rec_set(struct iam_leaf *l, const struct iam_rec *r)
++static void iam_htree_rec_set(struct iam_leaf *l, const struct iam_rec *r)
 +{
 +        assert(iam_leaf_at_rec(l));
-+        iam_reccpy(iam_leaf_path(l), iam_lfix_rec(l), r);
++        iam_reccpy(iam_leaf_path(l), iam_htree_rec(l), r);
 +}
 +
-+static void iam_lfix_rec_add(struct iam_leaf *leaf,
++static void iam_htree_rec_add(struct iam_leaf *leaf,
 +                             const struct iam_key *k, const struct iam_rec *r)
 +{
 +        struct iam_lentry *end;
@@ -1551,11 +1557,11 @@ Index: iam/fs/ext3/iam_lfix.c
 +         *   - empty leaf.
 +         */
 +        if (!iam_leaf_at_end(leaf)) {
-+                end   = iam_lfix_get_end(leaf);
++                end   = iam_htree_get_end(leaf);
 +                cur   = leaf->il_at;
 +                if (iam_keycmp(iam_leaf_container(leaf),
 +                               k, iam_leaf_key_at(cur)) >= 0)
-+                        iam_lfix_next(leaf);
++                        iam_htree_next(leaf);
 +                else
 +                        /*
 +                         * Another exceptional case: insertion with the key
@@ -1566,15 +1572,15 @@ Index: iam/fs/ext3/iam_lfix.c
 +                start = leaf->il_at;
 +                diff  = (void *)end - (void *)start;
 +                assert(diff >= 0);
-+                memmove(iam_lfix_shift(leaf, start, 1), start, diff);
++                memmove(iam_htree_shift(leaf, start, 1), start, diff);
 +        }
 +        lentry_count_set(leaf, count + 1);
-+        iam_lfix_key_set(leaf, k);
-+        iam_lfix_rec_set(leaf, r);
++        iam_htree_key_set(leaf, k);
++        iam_htree_rec_set(leaf, r);
 +        assert(iam_leaf_at_rec(leaf));
 +}
 +
-+static void iam_lfix_rec_del(struct iam_leaf *leaf)
++static void iam_htree_rec_del(struct iam_leaf *leaf)
 +{
 +        struct iam_lentry *next, *end;
 +        int count;
@@ -1583,26 +1589,26 @@ Index: iam/fs/ext3/iam_lfix.c
 +        assert(iam_leaf_at_rec(leaf));
 +
 +        count = lentry_count_get(leaf);
-+        end = iam_lfix_get_end(leaf);
-+        next = iam_lfix_shift(leaf, leaf->il_at, 1);
++        end = iam_htree_get_end(leaf);
++        next = iam_htree_shift(leaf, leaf->il_at, 1);
 +        diff = (void *)end - (void *)next;
 +        memmove(leaf->il_at, next, diff);
 +
 +        lentry_count_set(leaf, count - 1);
 +}
 +
-+static int iam_lfix_can_add(const struct iam_leaf *l,
++static int iam_htree_can_add(const struct iam_leaf *l,
 +                            const struct iam_key *k, const struct iam_rec *r)
 +{
 +        return lentry_count_get(l) < leaf_count_limit(l);
 +}
 +
-+static int iam_lfix_at_end(const struct iam_leaf *folio)
++static int iam_htree_at_end(const struct iam_leaf *folio)
 +{
-+        return folio->il_at == iam_lfix_get_end(folio);
++        return folio->il_at == iam_htree_get_end(folio);
 +}
 +
-+static void iam_lfix_init_new(struct iam_container *c, struct buffer_head *bh)
++static void iam_htree_init_new(struct iam_container *c, struct buffer_head *bh)
 +{
 +        struct iam_leaf_head *hdr;
 +
@@ -1611,7 +1617,7 @@ Index: iam/fs/ext3/iam_lfix.c
 +        hdr->ill_count = cpu_to_le16(0);
 +}
 +
-+static void iam_lfix_split(struct iam_leaf *l, struct buffer_head **bh,
++static void iam_htree_split(struct iam_leaf *l, struct buffer_head **bh,
 +                           iam_ptr_t new_blknr)
 +{
 +        struct iam_path      *path;
@@ -1633,8 +1639,8 @@ Index: iam/fs/ext3/iam_lfix.c
 +        count = lentry_count_get(l);
 +        split = count / 2;
 +
-+        start = iam_lfix_shift(l, iam_get_lentries(l), split);
-+        finis = iam_lfix_shift(l, iam_get_lentries(l), count);
++        start = iam_htree_shift(l, iam_get_lentries(l), split);
++        finis = iam_htree_shift(l, iam_get_lentries(l), count);
 +
 +        pivot = iam_leaf_key_at(start);
 +
@@ -1653,35 +1659,35 @@ Index: iam/fs/ext3/iam_lfix.c
 +                int shift;
 +                int result;
 +
-+                shift = iam_lfix_diff(l, l->il_at, start);
++                shift = iam_htree_diff(l, l->il_at, start);
 +                *bh = l->il_bh;
 +                l->il_bh = new_leaf;
-+                result = iam_lfix_init(l);
++                result = iam_htree_init(l);
 +                /*
 +                 * init cannot fail, as node was just initialized.
 +                 */
 +                assert(result == 0);
-+                l->il_at = iam_lfix_shift(l, iam_get_lentries(l), shift);
++                l->il_at = iam_htree_shift(l, iam_get_lentries(l), shift);
 +        }
 +
 +}
 +
-+static struct iam_leaf_operations iam_lfix_leaf_ops = {
-+        .init           = iam_lfix_init,
-+        .init_new       = iam_lfix_init_new,
-+        .fini           = iam_lfix_fini,
-+        .start          = iam_lfix_start,
-+        .next           = iam_lfix_next,
-+        .key            = iam_lfix_key,
-+        .rec            = iam_lfix_rec,
-+        .key_set        = iam_lfix_key_set,
-+        .rec_set        = iam_lfix_rec_set,
-+        .lookup         = iam_lfix_lookup,
-+        .at_end         = iam_lfix_at_end,
-+        .rec_add        = iam_lfix_rec_add,
-+        .rec_del        = iam_lfix_rec_del,
-+        .can_add        = iam_lfix_can_add,
-+        .split          = iam_lfix_split
++static struct iam_leaf_operations iam_htree_leaf_ops = {
++        .init           = iam_htree_init,
++        .init_new       = iam_htree_init_new,
++        .fini           = iam_htree_fini,
++        .start          = iam_htree_start,
++        .next           = iam_htree_next,
++        .key            = iam_htree_key,
++        .rec            = iam_htree_rec,
++        .key_set        = iam_htree_key_set,
++        .rec_set        = iam_htree_rec_set,
++        .lookup         = iam_htree_lookup,
++        .at_end         = iam_htree_at_end,
++        .rec_add        = iam_htree_rec_add,
++        .rec_del        = iam_htree_rec_del,
++        .can_add        = iam_htree_can_add,
++        .split          = iam_htree_split
 +};
 +
 +/*
@@ -1698,11 +1704,11 @@ Index: iam/fs/ext3/iam_lfix.c
 +         * For misery is trodden on by many,
 +         * And being low never relieved by any.
 +         */
-+        IAM_LFIX_ROOT_MAGIC = 0xbedabb1edULL // d01efull
++        IAM_HTREE_ROOT_MAGIC = 0xbedabb1edULL // d01efull
 +};
 +
 +/* This is duplicated in lustre/utils/create_iam.c */
-+struct iam_lfix_root {
++struct iam_htree_root {
 +        __le64  ilr_magic;
 +        __le16  ilr_keysize;
 +        __le16  ilr_recsize;
@@ -1710,26 +1716,26 @@ Index: iam/fs/ext3/iam_lfix.c
 +        __le16  ilr_indirect_levels;
 +};
 +
-+static __u32 iam_lfix_root_ptr(struct iam_container *c)
++static __u32 iam_htree_root_ptr(struct iam_container *c)
 +{
 +        return 0;
 +}
 +
-+static int iam_lfix_node_init(struct iam_container *c, struct buffer_head *bh,
++static int iam_htree_node_init(struct iam_container *c, struct buffer_head *bh,
 +                              int root)
 +{
 +        return 0;
 +}
 +
-+static void iam_lfix_root_inc(struct iam_container *c, struct iam_frame *frame)
++static void iam_htree_root_inc(struct iam_container *c, struct iam_frame *frame)
 +{
-+        struct iam_lfix_root *root;
++        struct iam_htree_root *root;
 +        root = (void *)frame->bh->b_data;
-+        assert(le64_to_cpu(root->ilr_magic) == IAM_LFIX_ROOT_MAGIC);
++        assert(le64_to_cpu(root->ilr_magic) == IAM_HTREE_ROOT_MAGIC);
 +        root->ilr_indirect_levels ++;
 +}
 +
-+static int iam_lfix_node_check(struct iam_path *path, struct iam_frame *frame)
++static int iam_htree_node_check(struct iam_path *path, struct iam_frame *frame)
 +{
 +        unsigned count;
 +        unsigned limit;
@@ -1739,10 +1745,10 @@ Index: iam/fs/ext3/iam_lfix.c
 +        entries = dx_node_get_entries(path, frame);
 +
 +        if (frame == path->ip_frames) {
-+                struct iam_lfix_root *root;
++                struct iam_htree_root *root;
 +
 +                root = (void *)frame->bh->b_data;
-+                if (le64_to_cpu(root->ilr_magic) != IAM_LFIX_ROOT_MAGIC) {
++                if (le64_to_cpu(root->ilr_magic) != IAM_HTREE_ROOT_MAGIC) {
 +                        BREAKPOINT;
 +                        return -EIO;
 +                }
@@ -1762,7 +1768,7 @@ Index: iam/fs/ext3/iam_lfix.c
 +        return 0;
 +}
 +
-+static int iam_lfix_node_load(struct iam_path *path, struct iam_frame *frame)
++static int iam_htree_node_load(struct iam_path *path, struct iam_frame *frame)
 +{
 +        struct iam_entry *entries;
 +        void *data;
@@ -1771,7 +1777,7 @@ Index: iam/fs/ext3/iam_lfix.c
 +        data = frame->bh->b_data;
 +
 +        if (frame == path->ip_frames) {
-+                struct iam_lfix_root *root;
++                struct iam_htree_root *root;
 +
 +                root = data;
 +                path->ip_indirect = le16_to_cpu(root->ilr_indirect_levels);
@@ -1780,161 +1786,753 @@ Index: iam/fs/ext3/iam_lfix.c
 +        return 0;
 +}
 +
-+static int iam_lfix_node_create(struct iam_container *c)
++static int iam_htree_node_create(struct iam_container *c)
 +{
 +        return 0;
 +}
 +
-+static int iam_lfix_keycmp(const struct iam_container *c,
++static int iam_htree_keycmp(const struct iam_container *c,
 +                           const struct iam_key *k1, const struct iam_key *k2)
 +{
 +        return memcmp(k1, k2, c->ic_descr->id_key_size);
 +}
 +
-+static struct iam_operations iam_lfix_ops = {
-+        .id_root_ptr    = iam_lfix_root_ptr,
++static struct iam_operations iam_htree_ops = {
++        .id_root_ptr    = iam_htree_root_ptr,
 +        .id_node_read   = iam_node_read,
-+        .id_node_init   = iam_lfix_node_init,
-+        .id_node_check  = iam_lfix_node_check,
-+        .id_node_load   = iam_lfix_node_load,
-+        .id_create      = iam_lfix_node_create,
-+        .id_keycmp      = iam_lfix_keycmp,
-+        .id_root_inc    = iam_lfix_root_inc,
++        .id_node_init   = iam_htree_node_init,
++        .id_node_check  = iam_htree_node_check,
++        .id_node_load   = iam_htree_node_load,
++        .id_create      = iam_htree_node_create,
++        .id_keycmp      = iam_htree_keycmp,
++        .id_root_inc    = iam_htree_root_inc,
 +        .id_name        = "lfix"
 +};
 +
-+static int iam_lfix_guess(struct iam_container *c)
++static int iam_htree_guess(struct iam_container *c)
 +{
 +        int result;
 +        struct buffer_head *bh;
-+        const struct iam_lfix_root *root;
++        const struct iam_htree_root *root;
 +
 +        assert(c->ic_object != NULL);
 +
-+        result = iam_node_read(c, iam_lfix_root_ptr(c), NULL, &bh);
++        result = iam_node_read(c, iam_htree_root_ptr(c), NULL, &bh);
 +        if (result == 0) {
 +                root = (void *)bh->b_data;
-+                if (le64_to_cpu(root->ilr_magic) == IAM_LFIX_ROOT_MAGIC) {
++                if (le64_to_cpu(root->ilr_magic) == IAM_HTREE_ROOT_MAGIC) {
 +                        struct iam_descr *descr;
 +
 +                        descr = c->ic_descr;
 +                        descr->id_key_size = le16_to_cpu(root->ilr_keysize);
 +                        descr->id_rec_size = le16_to_cpu(root->ilr_recsize);
 +                        descr->id_ptr_size = le16_to_cpu(root->ilr_ptrsize);
-+                        descr->id_root_gap = sizeof(struct iam_lfix_root);
++                        descr->id_root_gap = sizeof(struct iam_htree_root);
 +                        descr->id_node_gap = 0;
-+                        descr->id_ops      = &iam_lfix_ops;
-+                        descr->id_leaf_ops = &iam_lfix_leaf_ops;
++                        descr->id_ops      = &iam_htree_ops;
++                        descr->id_leaf_ops = &iam_htree_leaf_ops;
 +                } else
 +                        result = -EBADF;
 +        }
 +        return result;
 +}
 +
-+static struct iam_format iam_lfix_format = {
-+        .if_guess = iam_lfix_guess
++static struct iam_format iam_htree_format = {
++        .if_guess = iam_htree_guess
 +};
 +
-+void iam_lfix_format_init(void)
++void iam_htree_format_init(void)
 +{
-+        iam_format_register(&iam_lfix_format);
++        iam_format_register(&iam_htree_format);
 +}
 +
-+/*
-+ * Debugging aid.
++#endif
+Index: iam/fs/ext3/iam_lfix.c
+===================================================================
+--- iam.orig/fs/ext3/iam_lfix.c        2004-04-06 17:27:52.000000000 +0400
++++ iam/fs/ext3/iam_lfix.c     2006-06-20 23:39:51.000000000 +0400
+@@ -0,0 +1,626 @@
++/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
++ * vim:expandtab:shiftwidth=8:tabstop=8:
++ *
++ *  iam_lfix.c
++ *  implementation of iam format for fixed size records.
++ *
++ *  Copyright (c) 2006 Cluster File Systems, Inc.
++ *   Author: Wang Di <wangdi@clusterfs.com>
++ *   Author: Nikita Danilov <nikita@clusterfs.com>
++ *
++ *   This file is part of the Lustre file system, http://www.lustre.org
++ *   Lustre is a trademark of Cluster File Systems, Inc.
++ *
++ *   You may have signed or agreed to another license before downloading
++ *   this software.  If so, you are bound by the terms and conditions
++ *   of that agreement, and the following does not apply to you.  See the
++ *   LICENSE file included with this distribution for more information.
++ *
++ *   If you did not agree to a different license, then this copy of Lustre
++ *   is open source software; you can redistribute it and/or modify it
++ *   under the terms of version 2 of the GNU General Public License as
++ *   published by the Free Software Foundation.
++ *
++ *   In either case, Lustre is distributed in the hope that it will be
++ *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
++ *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   license text for more details.
 + */
 +
-+#define KEYSIZE (8)
-+#define RECSIZE (8)
-+#define PTRSIZE (4)
++#include <linux/types.h>
++#include <linux/jbd.h>
++/* ext3_error() */
++#include <linux/ext3_fs.h>
 +
-+#define LFIX_ROOT_RECNO \
-+        ((4096 - sizeof(struct iam_lfix_root)) / (KEYSIZE + PTRSIZE))
++#include <linux/lustre_iam.h>
 +
-+#define LFIX_INDEX_RECNO (4096 / (KEYSIZE + PTRSIZE))
++#include <libcfs/libcfs.h>
++#include <libcfs/kp30.h>
 +
-+#define LFIX_LEAF_RECNO \
-+        ((4096 - sizeof(struct iam_leaf_head)) / (KEYSIZE + RECSIZE))
++/*
++ * Leaf operations.
++ */
 +
-+struct lfix_root {
-+        struct iam_lfix_root lr_root;
-+        struct {
-+                char key[KEYSIZE];
-+                char ptr[PTRSIZE];
-+        } lr_entry[LFIX_ROOT_RECNO];
++enum {
++        IAM_LEAF_HEADER_MAGIC = 0x1976 /* This is duplicated in
++                                        * lustre/utils/create_iam.c */
 +};
 +
-+struct lfix_index {
-+        struct dx_countlimit li_cl;
-+        char   li_padding[KEYSIZE + PTRSIZE - sizeof(struct dx_countlimit)];
-+        struct {
-+                char key[KEYSIZE];
-+                char ptr[PTRSIZE];
-+        } li_entry[LFIX_INDEX_RECNO - 1];
++/* This is duplicated in lustre/utils/create_iam.c */
++struct iam_leaf_head {
++        __le16 ill_magic;
++        __le16 ill_count;
 +};
 +
-+struct lfix_leaf {
-+        struct iam_leaf_head ll_head;
-+        struct {
-+                char key[KEYSIZE];
-+                char rec[RECSIZE];
-+        } ll_entry[LFIX_LEAF_RECNO];
-+};
-Index: iam/fs/ext3/namei.c
-===================================================================
---- iam.orig/fs/ext3/namei.c   2006-05-31 20:24:32.000000000 +0400
-+++ iam/fs/ext3/namei.c        2006-06-12 22:12:33.000000000 +0400
-@@ -24,81 +24,6 @@
-  *    Theodore Ts'o, 2002
-  */
--/*
-- * iam: big theory statement.
-- *
-- * iam (Index Access Module) is a module providing abstraction of persistent
-- * transactional container on top of generalized ext3 htree.
-- *
-- * iam supports:
-- *
-- *     - key, pointer, and record size specifiable per container.
-- *
-- *     - trees taller than 2 index levels.
-- *
-- *     - read/write to existing ext3 htree directories as iam containers.
-- *
-- * iam container is a tree, consisting of leaf nodes containing keys and
-- * records stored in this container, and index nodes, containing keys and
-- * pointers to leaf or index nodes.
-- *
-- * iam does not work with keys directly, instead it calls user-supplied key
-- * comparison function (->dpo_keycmp()).
-- *
-- * Pointers are (currently) interpreted as logical offsets (measured in
-- * blocksful) within underlying flat file on top of which iam tree lives.
-- *
-- * On-disk format:
-- *
-- * iam mostly tries to reuse existing htree formats.
-- *
-- * Format of index node:
-- *
-- * +-----+-------+-------+-------+------+-------+------------+
-- * |     | count |       |       |      |       |            |
-- * | gap |   /   | entry | entry | .... | entry | free space |
-- * |     | limit |       |       |      |       |            |
-- * +-----+-------+-------+-------+------+-------+------------+
-- *
-- *       gap           this part of node is never accessed by iam code. It
-- *                     exists for binary compatibility with ext3 htree (that,
-- *                     in turn, stores fake struct ext2_dirent for ext2
-- *                     compatibility), and to keep some unspecified per-node
-- *                     data. Gap can be different for root and non-root index
-- *                     nodes. Gap size can be specified for each container
-- *                     (gap of 0 is allowed).
-- *
-- *       count/limit   current number of entries in this node, and the maximal
-- *                     number of entries that can fit into node. count/limit
-- *                     has the same size as entry, and is itself counted in
++static inline int iam_lfix_entry_size(const struct iam_leaf *l)
++{
++        return iam_leaf_descr(l)->id_key_size + iam_leaf_descr(l)->id_rec_size;
++}
++
++static inline struct iam_lentry *
++iam_lfix_shift(const struct iam_leaf *l, struct iam_lentry *entry, int shift)
++{
++        return (void *)entry + shift * iam_lfix_entry_size(l);
++}
++
++static inline struct iam_key *iam_leaf_key_at(struct iam_lentry *entry)
++{
++        return (struct iam_key *)entry;
++}
++
++static struct iam_leaf_head *iam_get_head(const struct iam_leaf *l)
++{
++        return (struct iam_leaf_head *)l->il_bh->b_data;
++}
++
++static struct iam_lentry *iam_entries(const struct buffer_head *bh)
++{
++        return (void *)bh->b_data + sizeof(struct iam_leaf_head);
++}
++
++static struct iam_lentry *iam_get_lentries(const struct iam_leaf *l)
++{
++        return iam_entries(l->il_bh);
++}
++
++static int leaf_count_limit(const struct iam_leaf *leaf)
++{
++        int free_space;
++
++        free_space = iam_leaf_container(leaf)->ic_object->i_sb->s_blocksize;
++        free_space -= sizeof(struct iam_leaf_head);
++        return free_space / iam_lfix_entry_size(leaf);
++}
++
++static int lentry_count_get(const struct iam_leaf *leaf)
++{
++        return le16_to_cpu(iam_get_head(leaf)->ill_count);
++}
++
++static void lentry_count_set(struct iam_leaf *leaf, unsigned count)
++{
++        assert(0 <= count && count <= leaf_count_limit(leaf));
++        iam_get_head(leaf)->ill_count = cpu_to_le16(count);
++}
++
++static struct iam_lentry *iam_lfix_get_end(const struct iam_leaf *l);
++
++static int iam_leaf_at_rec(const struct iam_leaf *folio)
++{
++        return
++                iam_get_lentries(folio) <= folio->il_at &&
++                folio->il_at < iam_lfix_get_end(folio);
++}
++
++/*This func is for flat key, for those keys,
++ *which are not stored explicitly
++ *it would be decrypt in the key buffer
++ */
++struct iam_key *iam_lfix_key(const struct iam_leaf *l, struct iam_key *key)
++{
++        void *ie = l->il_at;
++        assert(iam_leaf_at_rec(l));
++        return (struct iam_key*)ie;
++}
++
++static void iam_lfix_start(struct iam_leaf *l)
++{
++        l->il_at = iam_get_lentries(l);
++}
++
++static inline ptrdiff_t iam_lfix_diff(const struct iam_leaf *l,
++                                      const struct iam_lentry *e1,
++                                      const struct iam_lentry *e2)
++{
++        ptrdiff_t diff;
++        int esize;
++
++        esize = iam_lfix_entry_size(l);
++        diff = (void *)e1 - (void *)e2;
++        assert(diff / esize * esize == diff);
++        return diff / esize;
++}
++
++static int iam_lfix_init(struct iam_leaf *l)
++{
++        int result;
++        struct iam_leaf_head *ill;
++        int count;
++
++        assert(l->il_bh != NULL);
++
++        ill = iam_get_head(l);
++        count = le16_to_cpu(ill->ill_count);
++        if (ill->ill_magic == le16_to_cpu(IAM_LEAF_HEADER_MAGIC) &&
++            0 <= count && count <= leaf_count_limit(l)) {
++                l->il_at = l->il_entries = iam_get_lentries(l);
++                result = 0;
++        } else {
++                struct inode *obj;
++
++                obj = iam_leaf_container(l)->ic_object;
++                ext3_error(obj->i_sb, __FUNCTION__,
++                           "Wrong magic in node %llu (#%lu): %#x != %#x or "
++                           "wrong count: %i (%i)",
++                           (unsigned long long)l->il_bh->b_blocknr, obj->i_ino,
++                           ill->ill_magic, le16_to_cpu(IAM_LEAF_HEADER_MAGIC),
++                           count, leaf_count_limit(l));
++                result = -EIO;
++                BREAKPOINT;
++        }
++        return result;
++}
++
++static void iam_lfix_fini(struct iam_leaf *l)
++{
++        l->il_entries = l->il_at = NULL;
++        return;
++}
++
++static struct iam_lentry *iam_lfix_get_end(const struct iam_leaf *l)
++{
++        int count = lentry_count_get(l);
++        struct iam_lentry *ile = iam_lfix_shift(l, l->il_entries, count);
++
++        return ile;
++}
++
++struct iam_rec *iam_lfix_rec(const struct iam_leaf *l)
++{
++        void *e = l->il_at;
++        assert(iam_leaf_at_rec(l));
++        return e + iam_leaf_descr(l)->id_key_size;
++}
++
++static void iam_lfix_next(struct iam_leaf *l)
++{
++        assert(iam_leaf_at_rec(l));
++        l->il_at = iam_lfix_shift(l, l->il_at, 1);
++}
++
++static int iam_lfix_lookup(struct iam_leaf *l, const struct iam_key *k)
++{
++        struct iam_lentry *p, *q, *m, *t;
++        struct iam_container *c;
++        int count;
++        int result;
++
++        count = lentry_count_get(l);
++        if (count == 0)
++                return IAM_LOOKUP_EMPTY;
++
++        result = IAM_LOOKUP_OK;
++        c = iam_leaf_container(l);
++
++        p = l->il_entries;
++        q = iam_lfix_shift(l, p, count - 1);
++        if (iam_keycmp(c, k, iam_leaf_key_at(p)) < 0) {
++                /*
++                 * @k is less than the least key in the leaf
++                 */
++                l->il_at = p;
++                result = IAM_LOOKUP_BEFORE;
++        } else if (iam_keycmp(c, iam_leaf_key_at(q), k) <= 0) {
++                l->il_at = q;
++        } else {
++                /*
++                 * EWD1293
++                 */
++                while (iam_lfix_shift(l, p, 1) != q) {
++                        m = iam_lfix_shift(l, p, iam_lfix_diff(l, q, p) / 2);
++                        assert(p < m && m < q);
++                        (iam_keycmp(c, iam_leaf_key_at(m), k) <= 0 ? p : q) = m;
++                }
++                assert(iam_keycmp(c, iam_leaf_key_at(p), k) <= 0 &&
++                       iam_keycmp(c, k, iam_leaf_key_at(q)) < 0);
++                /*
++                 * skip over records with duplicate keys.
++                 */
++                while (p > l->il_entries) {
++                        t = iam_lfix_shift(l, p, -1);
++                        if (iam_keycmp(c, iam_leaf_key_at(t), k) == 0)
++                                p = t;
++                        else
++                                break;
++                }
++                l->il_at = p;
++        }
++        assert(iam_leaf_at_rec(l));
++
++        return result;
++}
++
++static void iam_lfix_key_set(struct iam_leaf *l, const struct iam_key *k)
++{
++        assert(iam_leaf_at_rec(l));
++        iam_keycpy(iam_leaf_container(l), iam_leaf_key_at(l->il_at), k);
++}
++
++static void iam_lfix_rec_set(struct iam_leaf *l, const struct iam_rec *r)
++{
++        assert(iam_leaf_at_rec(l));
++        iam_reccpy(iam_leaf_path(l), iam_lfix_rec(l), r);
++}
++
++static void iam_lfix_rec_add(struct iam_leaf *leaf,
++                             const struct iam_key *k, const struct iam_rec *r)
++{
++        struct iam_lentry *end;
++        struct iam_lentry *cur;
++        struct iam_lentry *start;
++        ptrdiff_t diff;
++        int count;
++
++        assert(iam_leaf_can_add(leaf, k, r));
++
++        count = lentry_count_get(leaf);
++        /*
++         * This branch handles two exceptional cases:
++         *
++         *   - leaf positioned beyond last record, and
++         *
++         *   - empty leaf.
++         */
++        if (!iam_leaf_at_end(leaf)) {
++                end   = iam_lfix_get_end(leaf);
++                cur   = leaf->il_at;
++                if (iam_keycmp(iam_leaf_container(leaf),
++                               k, iam_leaf_key_at(cur)) >= 0)
++                        iam_lfix_next(leaf);
++                else
++                        /*
++                         * Another exceptional case: insertion with the key
++                         * less than least key in the leaf.
++                         */
++                        assert(cur == leaf->il_entries);
++
++                start = leaf->il_at;
++                diff  = (void *)end - (void *)start;
++                assert(diff >= 0);
++                memmove(iam_lfix_shift(leaf, start, 1), start, diff);
++        }
++        lentry_count_set(leaf, count + 1);
++        iam_lfix_key_set(leaf, k);
++        iam_lfix_rec_set(leaf, r);
++        assert(iam_leaf_at_rec(leaf));
++}
++
++static void iam_lfix_rec_del(struct iam_leaf *leaf)
++{
++        struct iam_lentry *next, *end;
++        int count;
++        ptrdiff_t diff;
++
++        assert(iam_leaf_at_rec(leaf));
++
++        count = lentry_count_get(leaf);
++        end = iam_lfix_get_end(leaf);
++        next = iam_lfix_shift(leaf, leaf->il_at, 1);
++        diff = (void *)end - (void *)next;
++        memmove(leaf->il_at, next, diff);
++
++        lentry_count_set(leaf, count - 1);
++}
++
++static int iam_lfix_can_add(const struct iam_leaf *l,
++                            const struct iam_key *k, const struct iam_rec *r)
++{
++        return lentry_count_get(l) < leaf_count_limit(l);
++}
++
++static int iam_lfix_at_end(const struct iam_leaf *folio)
++{
++        return folio->il_at == iam_lfix_get_end(folio);
++}
++
++static void iam_lfix_init_new(struct iam_container *c, struct buffer_head *bh)
++{
++        struct iam_leaf_head *hdr;
++
++        hdr = (struct iam_leaf_head*)bh->b_data;
++        hdr->ill_magic = cpu_to_le16(IAM_LEAF_HEADER_MAGIC);
++        hdr->ill_count = cpu_to_le16(0);
++}
++
++static void iam_lfix_split(struct iam_leaf *l, struct buffer_head **bh,
++                           iam_ptr_t new_blknr)
++{
++        struct iam_path      *path;
++        struct iam_leaf_head *hdr;
++        const struct iam_key *pivot;
++        struct buffer_head   *new_leaf;
++
++        unsigned count;
++        unsigned split;
++
++        void *start;
++        void *finis;
++
++        new_leaf = *bh;
++        path = iam_leaf_path(l);
++
++        hdr = (void *)new_leaf->b_data;
++
++        count = lentry_count_get(l);
++        split = count / 2;
++
++        start = iam_lfix_shift(l, iam_get_lentries(l), split);
++        finis = iam_lfix_shift(l, iam_get_lentries(l), count);
++
++        pivot = iam_leaf_key_at(start);
++
++        memmove(iam_entries(new_leaf), start, finis - start);
++        hdr->ill_count = count - split;
++        lentry_count_set(l, split);
++        /*
++         * Insert pointer to the new node (together with the least key in
++         * the node) into index node.
++         */
++        iam_insert_key(path, path->ip_frame, pivot, new_blknr);
++        if ((void *)l->il_at >= start) {
++                /*
++                 * insertion point moves into new leaf.
++                 */
++                int shift;
++                int result;
++
++                shift = iam_lfix_diff(l, l->il_at, start);
++                *bh = l->il_bh;
++                l->il_bh = new_leaf;
++                result = iam_lfix_init(l);
++                /*
++                 * init cannot fail, as node was just initialized.
++                 */
++                assert(result == 0);
++                l->il_at = iam_lfix_shift(l, iam_get_lentries(l), shift);
++        }
++
++}
++
++static struct iam_leaf_operations iam_lfix_leaf_ops = {
++        .init           = iam_lfix_init,
++        .init_new       = iam_lfix_init_new,
++        .fini           = iam_lfix_fini,
++        .start          = iam_lfix_start,
++        .next           = iam_lfix_next,
++        .key            = iam_lfix_key,
++        .rec            = iam_lfix_rec,
++        .key_set        = iam_lfix_key_set,
++        .rec_set        = iam_lfix_rec_set,
++        .lookup         = iam_lfix_lookup,
++        .at_end         = iam_lfix_at_end,
++        .rec_add        = iam_lfix_rec_add,
++        .rec_del        = iam_lfix_rec_del,
++        .can_add        = iam_lfix_can_add,
++        .split          = iam_lfix_split
++};
++
++/*
++ * Index operations.
++ */
++
++enum {
++        /* This is duplicated in lustre/utils/create_iam.c */
++        /*
++         * Then shalt thou see the dew-BEDABBLED wretch
++         * Turn, and return, indenting with the way;
++         * Each envious brier his weary legs doth scratch,
++         * Each shadow makes him stop, each murmur stay:
++         * For misery is trodden on by many,
++         * And being low never relieved by any.
++         */
++        IAM_LFIX_ROOT_MAGIC = 0xbedabb1edULL // d01efull
++};
++
++/* This is duplicated in lustre/utils/create_iam.c */
++struct iam_lfix_root {
++        __le64  ilr_magic;
++        __le16  ilr_keysize;
++        __le16  ilr_recsize;
++        __le16  ilr_ptrsize;
++        __le16  ilr_indirect_levels;
++};
++
++static __u32 iam_lfix_root_ptr(struct iam_container *c)
++{
++        return 0;
++}
++
++static int iam_lfix_node_init(struct iam_container *c, struct buffer_head *bh,
++                              int root)
++{
++        return 0;
++}
++
++static void iam_lfix_root_inc(struct iam_container *c, struct iam_frame *frame)
++{
++        struct iam_lfix_root *root;
++        root = (void *)frame->bh->b_data;
++        assert(le64_to_cpu(root->ilr_magic) == IAM_LFIX_ROOT_MAGIC);
++        root->ilr_indirect_levels ++;
++}
++
++static int iam_lfix_node_check(struct iam_path *path, struct iam_frame *frame)
++{
++        unsigned count;
++        unsigned limit;
++        unsigned limit_correct;
++        struct iam_entry *entries;
++
++        entries = dx_node_get_entries(path, frame);
++
++        if (frame == path->ip_frames) {
++                struct iam_lfix_root *root;
++
++                root = (void *)frame->bh->b_data;
++                if (le64_to_cpu(root->ilr_magic) != IAM_LFIX_ROOT_MAGIC) {
++                        BREAKPOINT;
++                        return -EIO;
++                }
++                limit_correct = dx_root_limit(path);
++        } else
++                limit_correct = dx_node_limit(path);
++        count = dx_get_count(entries);
++        limit = dx_get_limit(entries);
++        if (count > limit) {
++                BREAKPOINT;
++                return -EIO;
++        }
++        if (limit != limit_correct) {
++                BREAKPOINT;
++                return -EIO;
++        }
++        return 0;
++}
++
++static int iam_lfix_node_load(struct iam_path *path, struct iam_frame *frame)
++{
++        struct iam_entry *entries;
++        void *data;
++        entries = dx_node_get_entries(path, frame);
++
++        data = frame->bh->b_data;
++
++        if (frame == path->ip_frames) {
++                struct iam_lfix_root *root;
++
++                root = data;
++                path->ip_indirect = le16_to_cpu(root->ilr_indirect_levels);
++        }
++        frame->entries = frame->at = entries;
++        return 0;
++}
++
++static int iam_lfix_node_create(struct iam_container *c)
++{
++        return 0;
++}
++
++static int iam_lfix_keycmp(const struct iam_container *c,
++                           const struct iam_key *k1, const struct iam_key *k2)
++{
++        return memcmp(k1, k2, c->ic_descr->id_key_size);
++}
++
++static struct iam_path_descr *iam_lfix_ipd_alloc(const struct iam_container *c)
++{
++        return iam_ipd_alloc(c->ic_descr->id_key_size);
++}
++
++static void iam_lfix_ipd_free(const struct iam_container *c,
++                              struct iam_path_descr *ipd)
++{
++        iam_ipd_free(ipd);
++}
++
++static struct iam_operations iam_lfix_ops = {
++        .id_root_ptr    = iam_lfix_root_ptr,
++        .id_node_read   = iam_node_read,
++        .id_node_init   = iam_lfix_node_init,
++        .id_node_check  = iam_lfix_node_check,
++        .id_node_load   = iam_lfix_node_load,
++        .id_create      = iam_lfix_node_create,
++        .id_keycmp      = iam_lfix_keycmp,
++        .id_root_inc    = iam_lfix_root_inc,
++        .id_ipd_alloc   = iam_lfix_ipd_alloc,
++        .id_ipd_free    = iam_lfix_ipd_free,
++        .id_name        = "lfix"
++};
++
++static int iam_lfix_guess(struct iam_container *c)
++{
++        int result;
++        struct buffer_head *bh;
++        const struct iam_lfix_root *root;
++
++        assert(c->ic_object != NULL);
++
++        result = iam_node_read(c, iam_lfix_root_ptr(c), NULL, &bh);
++        if (result == 0) {
++                root = (void *)bh->b_data;
++                if (le64_to_cpu(root->ilr_magic) == IAM_LFIX_ROOT_MAGIC) {
++                        struct iam_descr *descr;
++
++                        descr = c->ic_descr;
++                        descr->id_key_size = le16_to_cpu(root->ilr_keysize);
++                        descr->id_rec_size = le16_to_cpu(root->ilr_recsize);
++                        descr->id_ptr_size = le16_to_cpu(root->ilr_ptrsize);
++                        descr->id_root_gap = sizeof(struct iam_lfix_root);
++                        descr->id_node_gap = 0;
++                        descr->id_ops      = &iam_lfix_ops;
++                        descr->id_leaf_ops = &iam_lfix_leaf_ops;
++                } else
++                        result = -EBADF;
++        }
++        return result;
++}
++
++static struct iam_format iam_lfix_format = {
++        .if_guess = iam_lfix_guess
++};
++
++void iam_lfix_format_init(void)
++{
++        iam_format_register(&iam_lfix_format);
++}
++
++/*
++ * Debugging aid.
++ */
++
++#define KEYSIZE (8)
++#define RECSIZE (8)
++#define PTRSIZE (4)
++
++#define LFIX_ROOT_RECNO \
++        ((4096 - sizeof(struct iam_lfix_root)) / (KEYSIZE + PTRSIZE))
++
++#define LFIX_INDEX_RECNO (4096 / (KEYSIZE + PTRSIZE))
++
++#define LFIX_LEAF_RECNO \
++        ((4096 - sizeof(struct iam_leaf_head)) / (KEYSIZE + RECSIZE))
++
++struct lfix_root {
++        struct iam_lfix_root lr_root;
++        struct {
++                char key[KEYSIZE];
++                char ptr[PTRSIZE];
++        } lr_entry[LFIX_ROOT_RECNO];
++};
++
++struct lfix_index {
++        struct dx_countlimit li_cl;
++        char   li_padding[KEYSIZE + PTRSIZE - sizeof(struct dx_countlimit)];
++        struct {
++                char key[KEYSIZE];
++                char ptr[PTRSIZE];
++        } li_entry[LFIX_INDEX_RECNO - 1];
++};
++
++struct lfix_leaf {
++        struct iam_leaf_head ll_head;
++        struct {
++                char key[KEYSIZE];
++                char rec[RECSIZE];
++        } ll_entry[LFIX_LEAF_RECNO];
++};
+Index: iam/fs/ext3/namei.c
+===================================================================
+--- iam.orig/fs/ext3/namei.c   2006-05-31 20:24:32.000000000 +0400
++++ iam/fs/ext3/namei.c        2006-06-21 01:22:36.000000000 +0400
+@@ -24,81 +24,6 @@
+  *    Theodore Ts'o, 2002
+  */
+-/*
+- * iam: big theory statement.
+- *
+- * iam (Index Access Module) is a module providing abstraction of persistent
+- * transactional container on top of generalized ext3 htree.
+- *
+- * iam supports:
+- *
+- *     - key, pointer, and record size specifiable per container.
+- *
+- *     - trees taller than 2 index levels.
+- *
+- *     - read/write to existing ext3 htree directories as iam containers.
+- *
+- * iam container is a tree, consisting of leaf nodes containing keys and
+- * records stored in this container, and index nodes, containing keys and
+- * pointers to leaf or index nodes.
+- *
+- * iam does not work with keys directly, instead it calls user-supplied key
+- * comparison function (->dpo_keycmp()).
+- *
+- * Pointers are (currently) interpreted as logical offsets (measured in
+- * blocksful) within underlying flat file on top of which iam tree lives.
+- *
+- * On-disk format:
+- *
+- * iam mostly tries to reuse existing htree formats.
+- *
+- * Format of index node:
+- *
+- * +-----+-------+-------+-------+------+-------+------------+
+- * |     | count |       |       |      |       |            |
+- * | gap |   /   | entry | entry | .... | entry | free space |
+- * |     | limit |       |       |      |       |            |
+- * +-----+-------+-------+-------+------+-------+------------+
+- *
+- *       gap           this part of node is never accessed by iam code. It
+- *                     exists for binary compatibility with ext3 htree (that,
+- *                     in turn, stores fake struct ext2_dirent for ext2
+- *                     compatibility), and to keep some unspecified per-node
+- *                     data. Gap can be different for root and non-root index
+- *                     nodes. Gap size can be specified for each container
+- *                     (gap of 0 is allowed).
+- *
+- *       count/limit   current number of entries in this node, and the maximal
+- *                     number of entries that can fit into node. count/limit
+- *                     has the same size as entry, and is itself counted in
 - *                     count.
 - *
 - *       entry         index entry: consists of a key immediately followed by
@@ -2357,38 +2955,50 @@ Index: iam/fs/ext3/namei.c
  }
  
  static inline struct iam_key *iam_key_at(struct iam_path *p,
-@@ -540,85 +175,90 @@ static inline struct iam_key *iam_key_at
+@@ -540,85 +175,92 @@ static inline struct iam_key *iam_key_at
        return (struct iam_key *)entry;
  }
  
 -static inline void dx_set_key(struct iam_path *p,
 -                            struct iam_entry *entry, struct iam_key *key)
+-{
+-      memcpy(entry, key, path_descr(p)->id_key_size);
+-}
+-
+-static inline unsigned dx_get_count (struct iam_entry *entries)
+-{
+-      return le16_to_cpu(((struct dx_countlimit *) entries)->count);
+-}
+-
+-static inline unsigned dx_get_limit (struct iam_entry *entries)
 +static inline ptrdiff_t iam_entry_diff(struct iam_path *p,
 +                                     struct iam_entry *e1,
 +                                     struct iam_entry *e2)
  {
--      memcpy(entry, key, path_descr(p)->id_key_size);
+-      return le16_to_cpu(((struct dx_countlimit *) entries)->limit);
 -}
 +      ptrdiff_t diff;
  
--static inline unsigned dx_get_count (struct iam_entry *entries)
+-static inline void dx_set_count (struct iam_entry *entries, unsigned value)
 -{
--      return le16_to_cpu(((struct dx_countlimit *) entries)->count);
+-      ((struct dx_countlimit *) entries)->count = cpu_to_le16(value);
 +      diff = (void *)e1 - (void *)e2;
 +      assert(diff / iam_entry_size(p) * iam_entry_size(p) == diff);
 +      return diff / iam_entry_size(p);
  }
  
--static inline unsigned dx_get_limit (struct iam_entry *entries)
+-static inline void dx_set_limit (struct iam_entry *entries, unsigned value)
 +static inline void dx_set_limit(struct iam_entry *entries, unsigned value)
  {
--      return le16_to_cpu(((struct dx_countlimit *) entries)->limit);
-+      ((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
+       ((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
  }
  
--static inline void dx_set_count (struct iam_entry *entries, unsigned value)
+-static inline unsigned dx_root_limit(struct iam_path *p)
 -{
--      ((struct dx_countlimit *) entries)->count = cpu_to_le16(value);
+-      struct iam_descr *param = path_descr(p);
+-      unsigned entry_space = path_obj(p)->i_sb->s_blocksize -
+-              param->id_root_gap;
+-      return entry_space / (param->id_key_size + param->id_ptr_size);
 -}
 +/*
 + * Two iam_descr's are provided:
@@ -2398,9 +3008,12 @@ Index: iam/fs/ext3/namei.c
 + *
 + */
  
--static inline void dx_set_limit (struct iam_entry *entries, unsigned value)
+-static inline unsigned dx_node_limit(struct iam_path *p)
 -{
--      ((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
+-      struct iam_descr *param = path_descr(p);
+-      unsigned entry_space   = path_obj(p)->i_sb->s_blocksize -
+-              param->id_node_gap;
+-      return entry_space / (param->id_key_size + param->id_ptr_size);
 -}
 +static u32 htree_root_ptr(struct iam_container *c);
 +static int htree_node_check(struct iam_path *path, struct iam_frame *frame);
@@ -2408,14 +3021,11 @@ Index: iam/fs/ext3/namei.c
 +static int htree_keycmp(const struct iam_container *c,
 +                      const struct iam_key *k1, const struct iam_key *k2);
  
--static inline unsigned dx_root_limit(struct iam_path *p)
+-static inline int dx_index_is_compat(struct iam_path *path)
 -{
--      struct iam_descr *param = path_descr(p);
--      unsigned entry_space = path_obj(p)->i_sb->s_blocksize -
--              param->id_root_gap;
--      return entry_space / (param->id_key_size + param->id_ptr_size);
+-      return path_descr(path) == &htree_compat_param;
 -}
-+struct iam_operations htree_operation = {
++static struct iam_operations htree_operation = {
 +      .id_root_ptr   = htree_root_ptr,
 +      .id_node_check = htree_node_check,
 +      .id_node_init  = htree_node_init,
@@ -2424,12 +3034,12 @@ Index: iam/fs/ext3/namei.c
 +      .id_name       = "htree"
 +};
  
--static inline unsigned dx_node_limit(struct iam_path *p)
+-static struct iam_entry *dx_get_entries(struct iam_path *path, void *data,
+-                                     int root)
 -{
--      struct iam_descr *param = path_descr(p);
--      unsigned entry_space   = path_obj(p)->i_sb->s_blocksize -
--              param->id_node_gap;
--      return entry_space / (param->id_key_size + param->id_ptr_size);
+-      return data +
+-              (root ?
+-               path_descr(path)->id_root_gap : path_descr(path)->id_node_gap);
 -}
 +/*
 + * Parameters describing iam compatibility mode in which existing ext3 htrees
@@ -2440,31 +3050,22 @@ Index: iam/fs/ext3/namei.c
 +      .id_ptr_size = sizeof ((struct dx_map_entry *)NULL)->offs,
 +      .id_node_gap = offsetof(struct dx_node, entries),
 +      .id_root_gap = offsetof(struct dx_root, entries),
-+      .id_ops      = &htree_operation
++      .id_ops      = &htree_operation,
++//    .id_leaf_ops = &htree_leaf_operation
 +};
- static inline int dx_index_is_compat(struct iam_path *path)
- {
--      return path_descr(path) == &htree_compat_param;
--}
--
--static struct iam_entry *dx_get_entries(struct iam_path *path, void *data,
--                                     int root)
--{
--      return data +
--              (root ?
--               path_descr(path)->id_root_gap : path_descr(path)->id_node_gap);
-+      return iam_path_descr(path) == &htree_compat_param;
- }
++EXPORT_SYMBOL(htree_compat_param);
  
 -static struct iam_entry *dx_node_get_entries(struct iam_path *path,
 -                                          struct iam_frame *frame)
--{
++int dx_index_is_compat(struct iam_path *path)
+ {
 -      return dx_get_entries(path,
 -                            frame->bh->b_data, frame == path->ip_frames);
--}
++      return iam_path_descr(path) == &htree_compat_param;
+ }
  
 -static int dx_node_check(struct iam_path *p, struct iam_frame *f)
++
 +int dx_node_check(struct iam_path *p, struct iam_frame *f)
  {
        struct iam_entry     *e;
@@ -2498,7 +3099,7 @@ Index: iam/fs/ext3/namei.c
        }
        return 1;
  }
-@@ -636,13 +276,17 @@ static int htree_node_check(struct iam_p
+@@ -636,13 +278,17 @@ static int htree_node_check(struct iam_p
  
        data = frame->bh->b_data;
        entries = dx_node_get_entries(path, frame);
@@ -2518,7 +3119,7 @@ Index: iam/fs/ext3/namei.c
                if (root->info.hash_version > DX_HASH_MAX) {
                        ext3_warning(sb, __FUNCTION__,
                                     "Unrecognised inode hash code %d",
-@@ -669,15 +313,17 @@ static int htree_node_check(struct iam_p
+@@ -669,15 +315,17 @@ static int htree_node_check(struct iam_p
                                           root->info.info_length));
                assert(dx_get_limit(entries) == dx_root_limit(path));
  
@@ -2543,7 +3144,7 @@ Index: iam/fs/ext3/namei.c
                assert(dx_get_limit(entries) == dx_node_limit(path));
        }
        frame->entries = frame->at = entries;
-@@ -697,8 +343,8 @@ static int htree_node_init(struct iam_co
+@@ -697,8 +345,8 @@ static int htree_node_init(struct iam_co
        return 0;
  }
  
@@ -2554,7 +3155,7 @@ Index: iam/fs/ext3/namei.c
  {
        int result = 0;
  
-@@ -708,8 +354,8 @@ static int htree_node_read(struct iam_co
+@@ -708,8 +356,8 @@ static int htree_node_read(struct iam_co
        return result;
  }
  
@@ -2565,7 +3166,7 @@ Index: iam/fs/ext3/namei.c
  {
        __u32 p1 = le32_to_cpu(*(__u32 *)k1);
        __u32 p2 = le32_to_cpu(*(__u32 *)k2);
-@@ -800,7 +446,7 @@ struct stats dx_show_entries(struct dx_h
+@@ -800,7 +448,7 @@ struct stats dx_show_entries(struct dx_h
  }
  #endif /* DX_DEBUG */
  
@@ -2574,7 +3175,7 @@ Index: iam/fs/ext3/namei.c
  {
        u32 ptr;
        int err = 0;
-@@ -810,11 +456,11 @@ static int dx_lookup(struct iam_path *pa
+@@ -810,11 +458,11 @@ static int dx_lookup(struct iam_path *pa
        struct iam_frame *frame;
        struct iam_container *c;
  
@@ -2588,7 +3189,7 @@ Index: iam/fs/ext3/namei.c
             i <= path->ip_indirect;
             ptr = dx_get_block(path, frame->at), ++frame, ++i) {
                struct iam_entry *entries;
-@@ -823,10 +469,16 @@ static int dx_lookup(struct iam_path *pa
+@@ -823,10 +471,16 @@ static int dx_lookup(struct iam_path *pa
                struct iam_entry *m;
                unsigned count;
  
@@ -2607,7 +3208,7 @@ Index: iam/fs/ext3/namei.c
                if (err != 0)
                        break;
  
-@@ -837,12 +489,27 @@ static int dx_lookup(struct iam_path *pa
+@@ -837,12 +491,27 @@ static int dx_lookup(struct iam_path *pa
                assert(count && count <= dx_get_limit(entries));
                p = iam_entry_shift(path, entries, 1);
                q = iam_entry_shift(path, entries, count - 1);
@@ -2637,7 +3238,7 @@ Index: iam/fs/ext3/namei.c
                                q = iam_entry_shift(path, m, -1);
                        else
                                p = iam_entry_shift(path, m, +1);
-@@ -857,12 +524,12 @@ static int dx_lookup(struct iam_path *pa
+@@ -857,12 +526,12 @@ static int dx_lookup(struct iam_path *pa
                        while (n--) {
                                dxtrace(printk(","));
                                at = iam_entry_shift(path, at, +1);
@@ -2653,7 +3254,7 @@ Index: iam/fs/ext3/namei.c
                                                              path->ip_key_target));
                                        }
                                        at = iam_entry_shift(path, at, -1);
-@@ -891,508 +558,20 @@ static int dx_probe(struct dentry *dentr
+@@ -891,508 +560,20 @@ static int dx_probe(struct dentry *dentr
                    struct dx_hash_info *hinfo, struct iam_path *path)
  {
        int err;
@@ -3168,7 +3769,7 @@ Index: iam/fs/ext3/namei.c
   * This function increments the frame pointer to search the next leaf
   * block, and reads in the necessary intervening nodes if the search
   * should be necessary.  Whether or not the search is necessary is
-@@ -1409,16 +588,15 @@ EXPORT_SYMBOL(iam_update);
+@@ -1409,16 +590,15 @@ EXPORT_SYMBOL(iam_update);
   * If start_hash is non-null, it will be filled in with the starting
   * hash of the next page.
   */
@@ -3188,7 +3789,7 @@ Index: iam/fs/ext3/namei.c
        p = path->ip_frame;
        /*
         * Find the next leaf page by incrementing the frame pointer.
-@@ -1438,28 +616,34 @@ static int ext3_htree_next_block(struct 
+@@ -1438,28 +618,34 @@ static int ext3_htree_next_block(struct 
                --p;
        }
  
@@ -3239,7 +3840,7 @@ Index: iam/fs/ext3/namei.c
                if (err != 0)
                        return err; /* Failure */
                ++p;
-@@ -1471,6 +655,16 @@ static int ext3_htree_next_block(struct 
+@@ -1471,6 +657,16 @@ static int ext3_htree_next_block(struct 
        return 1;
  }
  
@@ -3256,7 +3857,7 @@ Index: iam/fs/ext3/namei.c
  
  /*
   * p is at least 6 bytes before the end of page
-@@ -1662,21 +856,30 @@ static void dx_sort_map (struct dx_map_e
+@@ -1662,21 +858,30 @@ static void dx_sort_map (struct dx_map_e
        } while(more);
  }
  
@@ -3293,7 +3894,7 @@ Index: iam/fs/ext3/namei.c
  #endif
  
  
-@@ -1897,14 +1100,15 @@ static struct buffer_head * ext3_dx_find
+@@ -1897,14 +1102,15 @@ static struct buffer_head * ext3_dx_find
                if (*err != 0)
                        return NULL;
        } else {
@@ -3312,7 +3913,7 @@ Index: iam/fs/ext3/namei.c
                if (*err != 0)
                        goto errout;
                de = (struct ext3_dir_entry_2 *) bh->b_data;
-@@ -2067,7 +1271,7 @@ static struct ext3_dir_entry_2 *do_split
+@@ -2067,7 +1273,7 @@ static struct ext3_dir_entry_2 *do_split
                        struct buffer_head **bh,struct iam_frame *frame,
                        struct dx_hash_info *hinfo, int *error)
  {
@@ -3321,7 +3922,7 @@ Index: iam/fs/ext3/namei.c
        unsigned blocksize = dir->i_sb->s_blocksize;
        unsigned count, continued;
        struct buffer_head *bh2;
-@@ -2392,18 +1596,25 @@ static int ext3_add_entry (handle_t *han
+@@ -2392,18 +1598,25 @@ static int ext3_add_entry (handle_t *han
  }
  
  #ifdef CONFIG_EXT3_INDEX
@@ -3350,7 +3951,7 @@ Index: iam/fs/ext3/namei.c
        frame = path->ip_frame;
        entries = frame->entries;
  
-@@ -2442,7 +1653,8 @@ static int split_index_node(handle_t *ha
+@@ -2442,7 +1655,8 @@ static int split_index_node(handle_t *ha
        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] ||
@@ -3360,7 +3961,7 @@ Index: iam/fs/ext3/namei.c
                        goto cleanup;
                BUFFER_TRACE(frame->bh, "get_write_access");
                err = ext3_journal_get_write_access(handle, frame->bh);
-@@ -2461,6 +1673,7 @@ static int split_index_node(handle_t *ha
+@@ -2461,6 +1675,7 @@ static int split_index_node(handle_t *ha
                unsigned count;
                int idx;
                struct buffer_head *bh2;
@@ -3368,7 +3969,7 @@ Index: iam/fs/ext3/namei.c
  
                entries = frame->entries;
                count = dx_get_count(entries);
-@@ -2469,6 +1682,7 @@ static int split_index_node(handle_t *ha
+@@ -2469,6 +1684,7 @@ static int split_index_node(handle_t *ha
                bh2 = bh_new[i];
                entries2 = dx_get_entries(path, bh2->b_data, 0);
  
@@ -3376,7 +3977,7 @@ Index: iam/fs/ext3/namei.c
                if (frame == path->ip_frames) {
                        /* splitting root node. Tricky point:
                         *
-@@ -2484,6 +1698,8 @@ static int split_index_node(handle_t *ha
+@@ -2484,6 +1700,8 @@ static int split_index_node(handle_t *ha
                        u8 indirects;
                        struct iam_frame *frames;
  
@@ -3385,7 +3986,7 @@ Index: iam/fs/ext3/namei.c
                        frames = path->ip_frames;
                        root = (struct dx_root *) frames->bh->b_data;
                        indirects = root->info.indirect_levels;
-@@ -2493,9 +1709,26 @@ static int split_index_node(handle_t *ha
+@@ -2493,9 +1711,26 @@ static int split_index_node(handle_t *ha
                        dx_set_limit(entries2, dx_node_limit(path));
  
                        /* Set up root */
@@ -3415,7 +4016,7 @@ Index: iam/fs/ext3/namei.c
  
                        /* Shift frames in the path */
                        memmove(frames + 2, frames + 1,
-@@ -2505,20 +1738,21 @@ static int split_index_node(handle_t *ha
+@@ -2505,20 +1740,21 @@ static int split_index_node(handle_t *ha
                        frames[1].entries = entries = entries2;
                        frames[1].bh = bh2;
                        assert(dx_node_check(path, frame));
@@ -3443,7 +4044,7 @@ Index: iam/fs/ext3/namei.c
  
                        dxtrace(printk("Split index %i/%i\n", count1, count2));
  
-@@ -2537,16 +1771,30 @@ static int split_index_node(handle_t *ha
+@@ -2537,16 +1773,30 @@ static int split_index_node(handle_t *ha
                                swap(frame->bh, bh2);
                                bh_new[i] = bh2;
                        }
@@ -3476,7 +4077,7 @@ Index: iam/fs/ext3/namei.c
        }
        goto cleanup;
  journal_error:
-@@ -2578,7 +1826,7 @@ static int ext3_dx_add_entry(handle_t *h
+@@ -2578,7 +1828,7 @@ static int ext3_dx_add_entry(handle_t *h
        size_t isize;
  
        iam_path_compat_init(&cpath, dir);
@@ -3485,7 +4086,7 @@ Index: iam/fs/ext3/namei.c
  
        err = dx_probe(dentry, NULL, &hinfo, path);
        if (err != 0)
-@@ -2588,8 +1836,9 @@ static int ext3_dx_add_entry(handle_t *h
+@@ -2588,8 +1838,9 @@ static int ext3_dx_add_entry(handle_t *h
        /* XXX nikita: global serialization! */
        isize = dir->i_size;
  
@@ -3497,7 +4098,7 @@ Index: iam/fs/ext3/namei.c
        if (err != 0)
                goto cleanup;
  
-@@ -2609,7 +1858,7 @@ static int ext3_dx_add_entry(handle_t *h
+@@ -2609,7 +1860,7 @@ static int ext3_dx_add_entry(handle_t *h
                goto cleanup;   
  
        /*copy split inode too*/
@@ -3506,7 +4107,7 @@ Index: iam/fs/ext3/namei.c
        if (!de)
                goto cleanup;
  
-@@ -2724,12 +1973,12 @@ static struct inode * ext3_new_inode_wan
+@@ -2724,12 +1975,12 @@ static struct inode * ext3_new_inode_wan
   * is so far negative - it has no inode.
   *
   * If the create succeeds, we fill in the inode information
@@ -3524,7 +4125,7 @@ Index: iam/fs/ext3/namei.c
 Index: iam/include/linux/lustre_iam.h
 ===================================================================
 --- iam.orig/include/linux/lustre_iam.h        2006-05-31 20:24:32.000000000 +0400
-+++ iam/include/linux/lustre_iam.h     2006-06-16 14:39:59.000000000 +0400
++++ iam/include/linux/lustre_iam.h     2006-06-21 02:00:09.000000000 +0400
 @@ -1,9 +1,68 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
index 9f1b46b..0855222 100644 (file)
@@ -1,20 +1,20 @@
 Index: iam/fs/ext3/Makefile
 ===================================================================
---- iam.orig/fs/ext3/Makefile  2006-06-16 14:39:59.000000000 +0400
-+++ iam/fs/ext3/Makefile       2006-06-16 14:40:00.000000000 +0400
+--- iam.orig/fs/ext3/Makefile  2006-06-21 02:00:09.000000000 +0400
++++ iam/fs/ext3/Makefile       2006-06-21 02:00:09.000000000 +0400
 @@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
  
  ext3-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 hash.o resize.o \
 -         extents.o mballoc.o iam.o iam_lfix.o
-+         extents.o mballoc.o iam.o iam_lfix.o iam_uapi.o
++         extents.o mballoc.o iam.o iam_lfix.o iam_htree.o iam_uapi.o
  
  ext3-$(CONFIG_EXT3_FS_XATTR)   += xattr.o xattr_user.o xattr_trusted.o
  ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
 Index: iam/fs/ext3/file.c
 ===================================================================
---- iam.orig/fs/ext3/file.c    2006-06-16 14:39:59.000000000 +0400
-+++ iam/fs/ext3/file.c 2006-06-16 14:40:00.000000000 +0400
+--- iam.orig/fs/ext3/file.c    2006-06-21 02:00:09.000000000 +0400
++++ iam/fs/ext3/file.c 2006-06-21 02:00:09.000000000 +0400
 @@ -23,6 +23,7 @@
  #include <linux/jbd.h>
  #include <linux/ext3_fs.h>
@@ -50,7 +50,7 @@ Index: iam/fs/ext3/file.c
 Index: iam/fs/ext3/iam-uapi.c
 ===================================================================
 --- iam.orig/fs/ext3/iam-uapi.c        2004-04-06 17:27:52.000000000 +0400
-+++ iam/fs/ext3/iam-uapi.c     2006-06-16 14:40:00.000000000 +0400
++++ iam/fs/ext3/iam-uapi.c     2006-06-21 02:00:09.000000000 +0400
 @@ -0,0 +1,348 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
@@ -402,8 +402,8 @@ Index: iam/fs/ext3/iam-uapi.c
 +}
 Index: iam/include/linux/lustre_iam.h
 ===================================================================
---- iam.orig/include/linux/lustre_iam.h        2006-06-16 14:39:59.000000000 +0400
-+++ iam/include/linux/lustre_iam.h     2006-06-16 14:40:00.000000000 +0400
+--- iam.orig/include/linux/lustre_iam.h        2006-06-21 02:00:09.000000000 +0400
++++ iam/include/linux/lustre_iam.h     2006-06-21 02:00:09.000000000 +0400
 @@ -30,9 +30,6 @@
  #ifndef __LINUX_LUSTRE_IAM_H__
  #define __LINUX_LUSTRE_IAM_H__
@@ -488,7 +488,7 @@ Index: iam/include/linux/lustre_iam.h
         * Initialize new node (stored in @bh) that is going to be added into
         * tree.
         */
-@@ -152,15 +178,25 @@ struct iam_operations {
+@@ -152,15 +178,29 @@ struct iam_operations {
         * Create new container.
         *
         * Newly created container has a root node and a single leaf. Leaf
@@ -500,6 +500,10 @@ Index: iam/include/linux/lustre_iam.h
 +         * Modify root node when tree height increases.
 +       */
 +      void (*id_root_inc)(struct iam_container *c, struct iam_frame *frame);
++
++        struct iam_path_descr *(*id_ipd_alloc)(const struct iam_container *c);
++        void (*id_ipd_free)(const struct iam_container *c,
++                            struct iam_path_descr *ipd);
          /*
           * Format name.
           */
@@ -515,7 +519,7 @@ Index: iam/include/linux/lustre_iam.h
  struct iam_leaf_operations {
          /*
           * leaf operations.
-@@ -226,7 +262,8 @@ struct iam_leaf_operations {
+@@ -226,7 +266,8 @@ struct iam_leaf_operations {
           * split leaf node, moving some entries into @bh (the latter currently
           * is assumed to be empty).
           */
@@ -525,7 +529,7 @@ Index: iam/include/linux/lustre_iam.h
  };
  
  struct iam_path *iam_leaf_path(const struct iam_leaf *leaf);
-@@ -264,6 +301,9 @@ struct iam_descr {
+@@ -264,6 +305,9 @@ struct iam_descr {
          struct iam_leaf_operations      *id_leaf_ops;
  };
  
@@ -535,7 +539,7 @@ Index: iam/include/linux/lustre_iam.h
  struct iam_container {
        /*
         * Underlying flat file. IO against this object is issued to
-@@ -347,7 +387,9 @@ enum iam_it_state {
+@@ -347,7 +391,9 @@ enum iam_it_state {
        /* initial state */
        IAM_IT_DETACHED,
        /* iterator is above particular record in the container */
@@ -546,7 +550,7 @@ Index: iam/include/linux/lustre_iam.h
  };
  
  /*
-@@ -355,7 +397,7 @@ enum iam_it_state {
+@@ -355,7 +401,7 @@ enum iam_it_state {
   */
  enum iam_it_flags {
        /*
@@ -555,7 +559,7 @@ Index: iam/include/linux/lustre_iam.h
         */
        IAM_IT_MOVE  = (1 << 0),
        /*
-@@ -372,15 +414,26 @@ enum iam_it_flags {
+@@ -372,15 +418,26 @@ enum iam_it_flags {
   * doesn't point to any particular record in this container.
   *
   * After successful call to iam_it_get() and until corresponding call to
@@ -585,7 +589,7 @@ Index: iam/include/linux/lustre_iam.h
   *
   */
  struct iam_iterator {
-@@ -390,7 +443,8 @@ struct iam_iterator {
+@@ -390,7 +447,8 @@ struct iam_iterator {
        __u32                 ii_flags;
        enum iam_it_state     ii_state;
        /*
@@ -595,7 +599,7 @@ Index: iam/include/linux/lustre_iam.h
         */
        struct iam_path       ii_path;
  };
-@@ -420,27 +474,37 @@ int  iam_it_init(struct iam_iterator *it
+@@ -420,27 +478,37 @@ int  iam_it_init(struct iam_iterator *it
  void iam_it_fini(struct iam_iterator *it);
  
  /*
@@ -640,7 +644,7 @@ Index: iam/include/linux/lustre_iam.h
   *                     iam_it_rec_get(dst) == iam_it_rec_get(src) &&
   *                     iam_it_key_get(dst, *1) == iam_it_key_get(src, *2))
   */
-@@ -460,15 +524,17 @@ void iam_it_put(struct iam_iterator *it)
+@@ -460,15 +528,17 @@ void iam_it_put(struct iam_iterator *it)
   *              +1: end of container reached
   *             -ve: error
   *
@@ -661,7 +665,7 @@ Index: iam/include/linux/lustre_iam.h
   * postcondition: it_state(it) == IAM_IT_ATTACHED
   */
  struct iam_rec *iam_it_rec_get(const struct iam_iterator *it);
-@@ -476,14 +542,15 @@ struct iam_rec *iam_it_rec_get(const str
+@@ -476,14 +546,15 @@ struct iam_rec *iam_it_rec_get(const str
  /*
   * Replace contents of record under iterator.
   *
@@ -679,7 +683,7 @@ Index: iam/include/linux/lustre_iam.h
   *
   * precondition:  it_state(it) == IAM_IT_ATTACHED
   * postcondition: it_state(it) == IAM_IT_ATTACHED
-@@ -495,11 +562,17 @@ struct iam_key *iam_it_key_get(const str
+@@ -495,11 +566,17 @@ struct iam_key *iam_it_key_get(const str
   * Insert new record with key @k and contents from @r, shifting records to the
   * right.
   *
@@ -702,7 +706,7 @@ Index: iam/include/linux/lustre_iam.h
   *                     it_keycmp(it, iam_it_key_get(it, *), k) == 0 &&
   *                     !memcmp(iam_it_rec_get(it), r, ...))
   */
-@@ -508,8 +581,10 @@ int iam_it_rec_insert(handle_t *h, struc
+@@ -508,8 +585,10 @@ int iam_it_rec_insert(handle_t *h, struc
  /*
   * Delete record under iterator.
   *
@@ -715,7 +719,7 @@ Index: iam/include/linux/lustre_iam.h
   */
  int iam_it_rec_delete(handle_t *h, struct iam_iterator *it);
  
-@@ -519,7 +594,7 @@ typedef __u64 iam_pos_t;
+@@ -519,7 +598,7 @@ typedef __u64 iam_pos_t;
   * Convert iterator to cookie.
   *
   * precondition:  it_state(it) == IAM_IT_ATTACHED &&
@@ -724,7 +728,7 @@ Index: iam/include/linux/lustre_iam.h
   * postcondition: it_state(it) == IAM_IT_ATTACHED
   */
  iam_pos_t iam_it_store(const struct iam_iterator *it);
-@@ -527,8 +602,9 @@ iam_pos_t iam_it_store(const struct iam_
+@@ -527,8 +606,9 @@ iam_pos_t iam_it_store(const struct iam_
  /*
   * Restore iterator from cookie.
   *
@@ -736,7 +740,7 @@ Index: iam/include/linux/lustre_iam.h
   * postcondition: ergo(result == 0, it_state(it) == IAM_IT_ATTACHED &&
   *                                  iam_it_store(it) == pos)
   */
-@@ -583,6 +659,17 @@ static inline void iam_keycpy(const stru
+@@ -583,6 +663,17 @@ static inline void iam_keycpy(const stru
        memcpy(k1, k2, c->ic_descr->id_key_size);
  }
  
@@ -754,7 +758,7 @@ Index: iam/include/linux/lustre_iam.h
  static inline int iam_keycmp(const struct iam_container *c,
                             const struct iam_key *k1, const struct iam_key *k2)
  {
-@@ -650,6 +737,15 @@ static inline unsigned dx_node_limit(str
+@@ -650,6 +741,15 @@ static inline unsigned dx_node_limit(str
        return entry_space / (param->id_key_size + param->id_ptr_size);
  }
  
@@ -770,7 +774,25 @@ Index: iam/include/linux/lustre_iam.h
  static inline struct iam_entry *dx_get_entries(struct iam_path *path,
                                               void *data, int root)
  {
-@@ -702,6 +798,8 @@ void iam_insert_key(struct iam_path *pat
+@@ -674,6 +774,7 @@ static inline struct iam_key *iam_path_k
+ int dx_lookup(struct iam_path *path);
+ void dx_insert_block(struct iam_path *path, struct iam_frame *frame,
+                    u32 hash, u32 block);
++int dx_index_is_compat(struct iam_path *path);
+ int ext3_htree_next_block(struct inode *dir, __u32 hash,
+                         struct iam_path *path, __u32 *start_hash);
+@@ -682,6 +783,9 @@ struct buffer_head *ext3_append(handle_t
+                               u32 *block, int *err);
+ int split_index_node(handle_t *handle, struct iam_path *path);
++extern struct iam_descr htree_compat_param;
++
++
+ /*
+  * external
+  */
+@@ -702,6 +806,8 @@ void iam_insert_key(struct iam_path *pat
  
  int  iam_leaf_at_end(const struct iam_leaf *l);
  void iam_leaf_next(struct iam_leaf *folio);
@@ -779,7 +801,7 @@ Index: iam/include/linux/lustre_iam.h
  
  struct iam_path *iam_leaf_path(const struct iam_leaf *leaf);
  struct iam_container *iam_leaf_container(const struct iam_leaf *leaf);
-@@ -709,8 +807,23 @@ struct iam_descr *iam_leaf_descr(const s
+@@ -709,8 +815,23 @@ struct iam_descr *iam_leaf_descr(const s
  struct iam_leaf_operations *iam_leaf_ops(const struct iam_leaf *leaf);
  
  
@@ -803,7 +825,7 @@ Index: iam/include/linux/lustre_iam.h
          struct list_head if_linkage;
  };
  
-@@ -718,5 +831,48 @@ void iam_format_register(struct iam_form
+@@ -718,5 +839,48 @@ void iam_format_register(struct iam_form
  
  void iam_lfix_format_init(void);
  
index 9c27db4..5a05bf8 100644 (file)
@@ -11,7 +11,7 @@ ext3_headers := $(wildcard @LINUX@/fs/ext3/*.h)
 linux_headers := $(wildcard @LINUX@/include/linux/ext3*.h)
 
 ext3_sources := $(filter-out %.mod.c,$(wildcard @LINUX@/fs/ext3/*.c))
-new_sources := iopen.c iopen.h extents.c mballoc.c iam.c iam_lfix.c iam-uapi.c
+new_sources := iopen.c iopen.h extents.c mballoc.c iam.c iam_lfix.c iam_htree.c iam-uapi.c
 new_headers := ext3_extents.h
 ldiskfs_patched_sources := $(notdir $(ext3_sources) $(ext3_headers)) $(new_sources) $(new_headers)
 ldiskfs_sources := $(ldiskfs_patched_sources)
index 0143197..958c0f4 100755 (executable)
Binary files a/lustre/tests/iam_ut and b/lustre/tests/iam_ut differ
index 3af3d1f..e85de08 100644 (file)
@@ -158,6 +158,31 @@ enum op {
         OP_IT_STOP
 };
 
+unsigned char hex2dec(unsigned char hex)
+{
+        if ('0' <= hex && hex <= '9')
+                return hex - '0';
+        else if ('a' <= hex && hex <= 'f')
+                return hex - 'a';
+        else {
+                fprintf(stderr, "Wrong hex digit '%c'\n", hex);
+                exit(1);
+        }
+}
+
+unsigned char *packdigit(unsigned char *number)
+{
+        unsigned char *area;
+        unsigned char *scan;
+
+        area = calloc(strlen(number) / 2 + 2, sizeof area[0]);
+        if (area != NULL) {
+                for (scan = area; *number; number += 2, scan++)
+                        *scan = (hex2dec(number[0]) << 4) | hex2dec(number[1]);
+        }
+        return area;
+}
+
 int main(int argc, char **argv)
 {
         int i;
@@ -188,18 +213,24 @@ int main(int argc, char **argv)
         op = OP_TEST;
 
         do {
-                opt = getopt(argc, argv, "vilk:N:r:dsSn");
+                opt = getopt(argc, argv, "vilk:K:N:r:R:dsSn");
                 switch (opt) {
                 case 'v':
                         verbose++;
                 case -1:
                         break;
+                case 'K':
+                        key_opt = packdigit(optarg);
+                        break;
                 case 'k':
                         key_opt = optarg;
                         break;
                 case 'N':
                         N = atoi(optarg);
                         break;
+                case 'R':
+                        rec_opt = packdigit(optarg);
+                        break;
                 case 'r':
                         rec_opt = optarg;
                         break;
@@ -257,12 +288,12 @@ int main(int argc, char **argv)
         rec = calloc(recsize + 1, sizeof rec[0]);
 
         if (key == NULL || rec == NULL) {
-                fprintf(stderr, "cannot allocte memory\n");
+                fprintf(stderr, "cannot allocate memory\n");
                 return 1;
         }
 
-        strncpy(key, key_opt ? : "RIVERRUN", keysize + 1);
-        strncpy(rec, rec_opt ? : "PALEFIRE", recsize + 1);
+        memcpy(key, key_opt ? : "RIVERRUN", keysize + 1);
+        memcpy(rec, rec_opt ? : "PALEFIRE", recsize + 1);
 
         if (op == OP_INSERT)
                 return doop(0, key, rec, IAM_IOC_INSERT, "IAM_IOC_INSERT");