Whamcloud - gitweb
iam: fixes of fects found by UT:
authornikita <nikita>
Fri, 2 Jun 2006 11:22:20 +0000 (11:22 +0000)
committernikita <nikita>
Fri, 2 Jun 2006 11:22:20 +0000 (11:22 +0000)
 - defect: iam_new_leaf(): fix typo in previous ext3_append() fix.

 - defect: iam_add_rec(): leaf node has to be added to transaction. 5 min.

 - defect: iam_lfix_split(): erroneously inserts physical block number instead of offset into parent node. 10 min.

 - defect: mark index node as dirty, when inserting new entry into it.

 - defect: LDISKFS_INDEX_FL flag cleared in iam_release_file() is not written to disk.

 - defect: iam_lfix_lookup(): wrong key comparison.

 - defect: iam_add_rec(): @leaf variable has to be refreshed as split may retarget path to the new leaf node.

 - defect: iam_lfix_lookup(): wrong return code (this made it impossible to remove last record in a node). 90 min.

iam-ut:

 - new IAM_IOC_DELETE ioctl command,

 - new functionality for lustre/tests/iam_ut

lustre/kernel_patches/patches/ext3-iam-separate.patch
lustre/kernel_patches/patches/ext3-iam-uapi.patch
lustre/tests/iam_ut
lustre/tests/iam_ut.c

index 92bdc58..795ac5e 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-05-31 23:32:29.000000000 +0400
++++ iam/fs/ext3/Makefile       2006-06-02 15:15:24.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-05-31 22:34:57.000000000 +0400
-@@ -0,0 +1,1016 @@
++++ iam/fs/ext3/iam.c  2006-06-01 23:33:54.000000000 +0400
+@@ -0,0 +1,1056 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
 + *
@@ -343,6 +343,7 @@ Index: iam/fs/ext3/iam.c
 +              leaf->il_bh = bh;
 +                leaf->il_path = path;
 +              err = iam_leaf_ops(leaf)->init(leaf);
++                assert(ergo(err == 0, iam_leaf_check(leaf)));
 +      }
 +      return err;
 +}
@@ -350,6 +351,7 @@ Index: iam/fs/ext3/iam.c
 +static void iam_leaf_fini(struct iam_leaf *leaf)
 +{
 +        if (leaf->il_path != NULL) {
++                assert(ergo(leaf->il_bh != NULL, iam_leaf_check(leaf)));
 +                iam_leaf_ops(leaf)->fini(leaf);
 +                if (leaf->il_bh) {
 +                        brelse(leaf->il_bh);
@@ -368,8 +370,8 @@ Index: iam/fs/ext3/iam.c
 +      iam_leaf_ops(folio)->next(folio);
 +}
 +
-+static void iam_rec_add(struct iam_leaf *leaf, struct iam_key *key,
-+                        struct iam_rec *rec)
++static void iam_leaf_rec_add(struct iam_leaf *leaf, const struct iam_key *key,
++                             const struct iam_rec *rec)
 +{
 +        iam_leaf_ops(leaf)->rec_add(leaf, key, rec);
 +}
@@ -384,17 +386,72 @@ Index: iam/fs/ext3/iam.c
 +        return iam_leaf_ops(leaf)->at_end(leaf);
 +}
 +
-+void iam_leaf_split(struct iam_leaf *l, struct buffer_head *bh)
++void iam_leaf_split(struct iam_leaf *l, struct buffer_head **bh, iam_ptr_t nr)
 +{
-+        iam_leaf_ops(l)->split(l, bh);
++        iam_leaf_ops(l)->split(l, bh, nr);
 +}
 +
-+static int iam_leaf_can_add(const struct iam_leaf *l,
-+                            const struct iam_key *k, const struct iam_rec *r)
++int iam_leaf_can_add(const struct iam_leaf *l,
++                     const struct iam_key *k, const struct iam_rec *r)
 +{
 +        return iam_leaf_ops(l)->can_add(l, k, r);
 +}
 +
++static int iam_leaf_check(struct iam_leaf *leaf)
++{
++        struct iam_lentry    *orig;
++        struct iam_path      *path;
++        struct iam_container *bag;
++        struct iam_key       *k0;
++        struct iam_key       *k1;
++        int result;
++        int first;
++
++        orig = leaf->il_at;
++        path = iam_leaf_path(leaf);
++        bag  = iam_leaf_container(leaf);
++
++        result = iam_leaf_ops(leaf)->init(leaf);
++        if (result != 0)
++                return result;
++
++        first = 1;
++        k0 = iam_path_key(path, 0);
++        k1 = iam_path_key(path, 1);
++        while (!iam_leaf_at_end(leaf)) {
++              iam_keycpy(bag, k0, k1);
++              iam_keycpy(bag, k1, iam_leaf_key(leaf, k1));
++                if (!first && iam_keycmp(bag, k0, k1) > 0)
++                        return 0;
++                first = 0;
++                iam_leaf_next(leaf);
++        }
++        leaf->il_at = orig;
++        return 1;
++}
++
++static int iam_txn_dirty(handle_t *handle,
++                         struct iam_path *path, struct buffer_head *bh)
++{
++        int result;
++
++        result = ext3_journal_dirty_metadata(handle, bh);
++        if (result != 0)
++                ext3_std_error(iam_path_obj(path)->i_sb, result);
++        return result;
++}
++
++static int iam_txn_add(handle_t *handle,
++                       struct iam_path *path, struct buffer_head *bh)
++{
++        int result;
++
++        result = ext3_journal_get_write_access(handle, bh);
++        if (result != 0)
++                ext3_std_error(iam_path_obj(path)->i_sb, result);
++        return result;
++}
++
 +/***********************************************************************/
 +/* iterator interface                                                  */
 +/***********************************************************************/
@@ -520,6 +577,7 @@ Index: iam/fs/ext3/iam.c
 +      result = dx_lookup(path);
 +      if (result == 0) {
 +              result = iam_leaf_load(path);
++                assert(ergo(result == 0, iam_leaf_check(leaf)));
 +              if (result == 0)
 +                      result = iam_leaf_ops(leaf)->lookup(leaf,
 +                                                            path->ip_key_target);
@@ -685,7 +743,7 @@ Index: iam/fs/ext3/iam.c
 +
 +        assert(it_state(it) == IAM_IT_ATTACHED && it->ii_flags&IAM_IT_WRITE);
 +
-+        result = ext3_journal_get_write_access(h, it->ii_path.ip_leaf.il_bh);
++        result = iam_txn_add(h, &it->ii_path, it->ii_path.ip_leaf.il_bh);
 +        if (result == 0)
 +                iam_it_reccpy(it, r);
 +        return result;
@@ -703,47 +761,28 @@ Index: iam/fs/ext3/iam.c
 +        return iam_leaf_key(&it->ii_path.ip_leaf, k);
 +}
 +
-+static int iam_leaf_rec_add(handle_t *handle, struct iam_path *path)
-+{
-+        int err;
-+
-+        err = ext3_journal_get_write_access(handle, path->ip_leaf.il_bh);
-+        if (err)
-+                goto journal_error;
-+        iam_rec_add(&path->ip_leaf, NULL, NULL);
-+      err = ext3_journal_dirty_metadata(handle, path->ip_leaf.il_bh);
-+journal_error:
-+      if (err)
-+                ext3_std_error(iam_path_obj(path)->i_sb, err);
-+      return err;
-+}
-+
 +static int iam_new_leaf(handle_t *handle, struct iam_leaf *leaf)
 +{
 +        int err;
-+        int err2;
 +        u32 blknr; /* XXX 32bit block size */
 +        struct buffer_head   *new_leaf;
 +        struct iam_container *c;
++        struct inode         *obj;
++
++        assert(iam_leaf_check(leaf));
 +
 +        c = iam_leaf_container(leaf);
-+        err = ext3_journal_get_write_access(handle, leaf->il_bh);
-+        if (err == 0) {
-+                struct inode *obj;
 +
-+                obj = c->ic_object;
-+                new_leaf = ext3_append(handle, c->ic_object, &blknr, &err);
-+                if (new_leaf != NULL) {
-+                        iam_leaf_ops(leaf)->init_new(c, new_leaf);
-+                        iam_leaf_ops(leaf)->split(leaf, new_leaf);
-+                        err = ext3_journal_dirty_metadata(handle, new_leaf);
-+                        err2 = ext3_journal_dirty_metadata(handle, leaf->il_bh);
-+                        err = err ? : err2;
-+                        if (err)
-+                                ext3_std_error(obj->i_sb, err);
-+                        brelse(new_leaf);
-+                }
++        obj = c->ic_object;
++        new_leaf = ext3_append(handle, c->ic_object, &blknr, &err);
++        if (new_leaf != NULL) {
++                iam_leaf_ops(leaf)->init_new(c, new_leaf);
++                iam_leaf_split(leaf, &new_leaf, blknr);
++                err = iam_txn_dirty(handle, iam_leaf_path(leaf), new_leaf);
++                brelse(new_leaf);
 +        }
++        assert(iam_leaf_check(leaf));
++        assert(iam_leaf_check(&iam_leaf_path(leaf)->ip_leaf));
 +        return err;
 +}
 +
@@ -751,21 +790,35 @@ Index: iam/fs/ext3/iam.c
 +                       const struct iam_key *k, const struct iam_rec *r)
 +{
 +      int err;
++        struct iam_leaf *leaf;
 +
-+      if (iam_leaf_can_add(&path->ip_leaf, k, r)) {
-+              err = iam_leaf_rec_add(handle, path);
-+      } else {
-+              err = split_index_node(handle, path);
-+              if (err == 0) {
-+                        err = iam_new_leaf(handle, &path->ip_leaf);
-+                        /*
-+                         * XXX: if insertion point moved into new leaf, path
-+                         * and path->ip_leaf have to be updated.
-+                         */
-+                      if (err == 0)
-+                              err = iam_leaf_rec_add(handle, path);
-+              }
-+      }
++        leaf = &path->ip_leaf;
++        assert(iam_leaf_check(leaf));
++        err = iam_txn_add(handle, path, leaf->il_bh);
++        if (err == 0) {
++                if (!iam_leaf_can_add(leaf, k, r)) {
++                        err = split_index_node(handle, path);
++                        if (err == 0) {
++                                err = iam_new_leaf(handle, leaf);
++                                /*
++                                 * refresh @leaf, as split may retarget path
++                                 * to the new leaf node.
++                                 */
++                                leaf = &path->ip_leaf;
++                                if (err == 0)
++                                        err = iam_txn_dirty(handle, path,
++                                                            path->ip_frame->bh);
++                        }
++                } else
++                        err = 0;
++
++                if (err == 0) {
++                        iam_leaf_rec_add(leaf, k, r);
++                        err = iam_txn_dirty(handle, path, leaf->il_bh);
++                }
++        }
++        assert(iam_leaf_check(leaf));
++        assert(iam_leaf_check(&path->ip_leaf));
 +      return err;
 +}
 +
@@ -789,16 +842,6 @@ Index: iam/fs/ext3/iam.c
 +        assert(it_state(it) == IAM_IT_ATTACHED && it->ii_flags&IAM_IT_WRITE);
 +        assert(it_keycmp(it, iam_it_key_get(it, it_scratch_key(it, 0)), k) < 0);
 +      result = iam_add_rec(h, &it->ii_path, k, r);
-+      if (result == 0) {
-+              /* place record and key info freed space. Leaf node is already
-+               * in transaction. */
-+              iam_it_reccpy(it, r);
-+                iam_it_keycpy(it, k);
-+                iam_keycpy(it->ii_path.ip_container, it_scratch_key(it, 0), k);
-+                /*
-+               * XXX TBD.
-+               */
-+        }
 +        assert(it_state(it) == IAM_IT_ATTACHED);
 +        assert(ergo(result == 0,
 +                    it_keycmp(it,
@@ -811,13 +854,10 @@ Index: iam/fs/ext3/iam.c
 +
 +static int iam_leaf_rec_remove(handle_t *handle, struct iam_leaf *leaf)
 +{
-+      int err;
-+
++        assert(iam_leaf_check(leaf));
 +        iam_rec_del(leaf);
-+      err = ext3_journal_dirty_metadata(handle, leaf->il_bh);
-+      if (err)
-+              ext3_std_error(iam_path_obj(iam_leaf_path(leaf))->i_sb, err);
-+      return err;
++        assert(iam_leaf_check(leaf));
++      return iam_txn_dirty(handle, iam_leaf_path(leaf), leaf->il_bh);
 +}
 +
 +/*
@@ -832,7 +872,7 @@ Index: iam/fs/ext3/iam.c
 +
 +        assert(it_state(it) == IAM_IT_ATTACHED && it->ii_flags&IAM_IT_WRITE);
 +
-+        result = ext3_journal_get_write_access(h, it->ii_path.ip_leaf.il_bh);
++        result = iam_txn_add(h, &it->ii_path, it->ii_path.ip_leaf.il_bh);
 +        /*
 +         * no compaction for now.
 +         */
@@ -1035,8 +1075,8 @@ Index: iam/fs/ext3/iam.c
 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-05-31 23:32:16.000000000 +0400
-@@ -0,0 +1,451 @@
++++ iam/fs/ext3/iam_lfix.c     2006-06-01 23:51:13.000000000 +0400
+@@ -0,0 +1,470 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
 + *
@@ -1230,35 +1270,45 @@ Index: iam/fs/ext3/iam_lfix.c
 +                        p = iam_lfix_shift(l, m, +1);
 +        }
 +        l->il_at = iam_lfix_shift(l, p, -1);
-+        iam_keycpy(c, iam_path_key(iam_leaf_path(l), 0), iam_leaf_key_at(q));
 +
-+        if (l->il_at == l->il_entries ||
-+            iam_keycmp(c, iam_leaf_key_at(q), k) != 0)
-+                return -ENOENT;
-+        else
-+                return 0;
++        assert(!iam_leaf_at_end(l));
++
++        return iam_keycmp(c, iam_leaf_key_at(l->il_at), k) != 0 ? -ENOENT : 0;
++}
++
++static void iam_lfix_key_set(struct iam_leaf *l, const struct iam_key *k)
++{
++        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)
++{
++        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, *next, *cur, *nnext;
++        struct iam_lentry *end;
++        struct iam_lentry *cur;
++        struct iam_lentry *next;
 +        ptrdiff_t diff;
 +        int count;
 +
++        assert(!iam_leaf_at_end(leaf));
++        assert(iam_leaf_can_add(leaf, k, r));
++
 +        count = lentry_count_get(leaf);
-+        end = iam_lfix_get_end(leaf);
-+        cur = leaf->il_at;
-+        if (cur != end) {
-+                next = iam_lfix_shift(leaf, cur, 1);
-+                if (next != end) {
-+                        nnext = iam_lfix_shift(leaf, next, 1);
-+                        diff = (void *)end - (void *)next;
-+                        memmove(nnext, next, diff);
-+                }
-+                iam_lfix_next(leaf);
-+        }
++        end   = iam_lfix_get_end(leaf);
++        cur   = leaf->il_at;
++        next  = iam_lfix_shift(leaf, cur, 1);
++        diff  = (void *)end - (void *)next;
++        memmove(iam_lfix_shift(leaf, next, 1), next, diff);
++        iam_lfix_next(leaf);
++        iam_lfix_key_set(leaf, k);
++        iam_lfix_rec_set(leaf, r);
 +        lentry_count_set(leaf, count + 1);
++        assert(!iam_leaf_at_end(leaf));
 +}
 +
 +static void iam_lfix_rec_del(struct iam_leaf *leaf)
@@ -1299,9 +1349,7 @@ Index: iam/fs/ext3/iam_lfix.c
 +
 +static int iam_lfix_at_end(const struct iam_leaf *folio)
 +{
-+        struct iam_lentry *ile = iam_lfix_get_end(folio);
-+
-+        return (folio->il_at == ile);
++        return folio->il_at == iam_lfix_get_end(folio);
 +}
 +
 +static void iam_lfix_init_new(struct iam_container *c, struct buffer_head *bh)
@@ -1313,11 +1361,13 @@ 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_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;
@@ -1325,9 +1375,10 @@ Index: iam/fs/ext3/iam_lfix.c
 +        void *start;
 +        void *finis;
 +
++        new_leaf = *bh;
 +        path = iam_leaf_path(l);
 +
-+        hdr = (void *)bh->b_data;
++        hdr = (void *)new_leaf->b_data;
 +
 +        count = lentry_count_get(l);
 +        split = count / 2;
@@ -1337,24 +1388,32 @@ Index: iam/fs/ext3/iam_lfix.c
 +
 +        pivot = iam_leaf_key_at(start);
 +
-+        memmove(iam_entries(bh), start, finis - 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 smallest key in
 +         * the node) into index node.
 +         */
-+        iam_insert_key(path, path->ip_frame, pivot, bh->b_blocknr);
-+}
++        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;
 +
-+static void iam_lfix_key_set(struct iam_leaf *l, const struct iam_key *k)
-+{
-+        iam_keycpy(iam_leaf_container(l), iam_leaf_key_at(l->il_at), k);
-+}
++                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 void iam_lfix_rec_set(struct iam_leaf *l, const struct iam_rec *r)
-+{
-+        iam_reccpy(iam_leaf_path(l), iam_lfix_rec(l), r);
 +}
 +
 +static struct iam_leaf_operations iam_lfix_leaf_ops = {
@@ -1491,7 +1550,7 @@ Index: iam/fs/ext3/iam_lfix.c
 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-05-31 20:26:49.000000000 +0400
++++ iam/fs/ext3/namei.c        2006-06-01 19:56:08.000000000 +0400
 @@ -24,81 +24,6 @@
   *    Theodore Ts'o, 2002
   */
@@ -1605,7 +1664,7 @@ Index: iam/fs/ext3/namei.c
                EXT3_I(inode)->i_disksize = inode->i_size;
 -              ext3_journal_get_write_access(handle,bh);
 +              *err = ext3_journal_get_write_access(handle, bh);
-+              if (err != 0) {
++              if (*err != 0) {
 +                      brelse(bh);
 +                      bh = NULL;
 +              }
@@ -3001,7 +3060,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-05-31 23:32:29.000000000 +0400
++++ iam/include/linux/lustre_iam.h     2006-06-02 15:15:24.000000000 +0400
 @@ -1,9 +1,68 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
index 5175757..56686db 100644 (file)
@@ -1,7 +1,7 @@
 Index: iam/fs/ext3/Makefile
 ===================================================================
---- iam.orig/fs/ext3/Makefile  2006-05-31 23:32:29.000000000 +0400
-+++ iam/fs/ext3/Makefile       2006-05-31 23:32:36.000000000 +0400
+--- iam.orig/fs/ext3/Makefile  2006-06-02 15:15:24.000000000 +0400
++++ iam/fs/ext3/Makefile       2006-06-02 15:15:25.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 \
@@ -13,8 +13,8 @@ Index: iam/fs/ext3/Makefile
  ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
 Index: iam/fs/ext3/file.c
 ===================================================================
---- iam.orig/fs/ext3/file.c    2006-05-31 23:32:29.000000000 +0400
-+++ iam/fs/ext3/file.c 2006-05-31 23:32:36.000000000 +0400
+--- iam.orig/fs/ext3/file.c    2006-06-02 15:15:24.000000000 +0400
++++ iam/fs/ext3/file.c 2006-06-02 15:15:25.000000000 +0400
 @@ -23,6 +23,7 @@
  #include <linux/jbd.h>
  #include <linux/ext3_fs.h>
@@ -33,7 +33,7 @@ Index: iam/fs/ext3/file.c
 +              if (S_ISDIR(inode->i_mode))
 +                      ext3_htree_free_dir_info(filp->private_data);
 +              else
-+                      ext3_iam_free_info(filp->private_data);
++                      ext3_iam_release(filp, inode);
 +      }
  
        return 0;
@@ -50,8 +50,8 @@ 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-05-31 23:32:36.000000000 +0400
-@@ -0,0 +1,246 @@
++++ iam/fs/ext3/iam-uapi.c     2006-06-02 15:15:25.000000000 +0400
+@@ -0,0 +1,256 @@
 +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
 + * vim:expandtab:shiftwidth=8:tabstop=8:
 + *
@@ -113,13 +113,18 @@ Index: iam/fs/ext3/iam-uapi.c
 +        struct iam_private_info *ipi;
 +
 +        ipi = get_ipi(filp);
-+        if (cmd == IAM_IOC_INSERT) {
++        if (cmd == IAM_IOC_INSERT || cmd == IAM_IOC_DELETE) {
 +                handle_t *h;
 +
 +                h = ext3_journal_start(inode, IAM_INSERT_CREDITS);
 +                if (!IS_ERR(h)) {
-+                        result = iam_insert(h, &ipi->ipi_bag, op->iul_key,
-+                                            op->iul_rec, ipi->ipi_ipd);
++                        if (cmd == IAM_IOC_INSERT)
++                                result = iam_insert(h, &ipi->ipi_bag,
++                                                    op->iul_key,
++                                                    op->iul_rec, ipi->ipi_ipd);
++                        else
++                                result = iam_delete(h, &ipi->ipi_bag,
++                                                    op->iul_key, ipi->ipi_ipd);
 +                        ext3_journal_stop(h);
 +                } else {
 +                        result = PTR_ERR(h);
@@ -141,13 +146,17 @@ Index: iam/fs/ext3/iam-uapi.c
 +        return info;
 +}
 +
-+void ext3_iam_free_info(struct iam_private_info *info)
++void ext3_iam_release(struct file *filp, struct inode *inode)
 +{
++        struct iam_private_info *info;
++
++        info = filp->private_data;
 +        iam_container_fini(&info->ipi_bag);
 +        if (info->ipi_ipd != NULL)
 +                iam_ipd_free(info->ipi_ipd);
 +
 +        kfree(info);
++        EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
 +}
 +
 +static int iam_uapi_init(struct inode *inode,
@@ -262,13 +271,13 @@ Index: iam/fs/ext3/iam-uapi.c
 +        else if (!S_ISREG(inode->i_mode))
 +                result = -EBADF;
 +        else if (cmd == IAM_IOC_INIT) {
-+                if (!is_dx(inode)) {
++                if (filp->private_data == NULL) {
 +                        result = getua(&u.ua, arg);
 +                        if (result == 0)
 +                                result = iam_uapi_init(inode, filp, &u.ua);
 +                } else
 +                        result = -EBUSY;
-+        } else if (is_dx(inode)) {
++        } else if (is_dx(inode) && filp->private_data != NULL) {
 +                struct iam_descr *des;
 +
 +                des = &get_ipi(filp)->ipi_descr;
@@ -280,14 +289,15 @@ Index: iam/fs/ext3/iam-uapi.c
 +                        memcpy(u.ua.iui_fmt_name, des->id_ops->id_name,
 +                               ARRAY_SIZE(u.ua.iui_fmt_name));
 +                        result = putua(&u.ua, arg);
-+                } else if (cmd == IAM_IOC_INSERT || cmd == IAM_IOC_LOOKUP) {
++                } else if (cmd == IAM_IOC_INSERT || cmd == IAM_IOC_LOOKUP ||
++                           cmd == IAM_IOC_DELETE) {
 +                        result = getop(&u.op, &uop, des, arg);
 +                        if (result == 0) {
 +                                result = iam_uapi_op(cmd, inode, filp, &u.op);
 +                                if (cmd == IAM_IOC_LOOKUP) {
 +                                        int res2;
 +
-+                                        res2 = outop(&u.op, &uop, des, KEY);
++                                        res2 = outop(&u.op, &uop, des, REC);
 +                                        result = result ? : res2;
 +                                }
 +                                putop(&u.op);
@@ -300,8 +310,8 @@ Index: iam/fs/ext3/iam-uapi.c
 +}
 Index: iam/include/linux/lustre_iam.h
 ===================================================================
---- iam.orig/include/linux/lustre_iam.h        2006-05-31 23:32:29.000000000 +0400
-+++ iam/include/linux/lustre_iam.h     2006-05-31 23:32:36.000000000 +0400
+--- iam.orig/include/linux/lustre_iam.h        2006-06-02 15:15:24.000000000 +0400
++++ iam/include/linux/lustre_iam.h     2006-06-02 15:15:25.000000000 +0400
 @@ -30,9 +30,6 @@
  #ifndef __LINUX_LUSTRE_IAM_H__
  #define __LINUX_LUSTRE_IAM_H__
@@ -323,13 +333,32 @@ Index: iam/include/linux/lustre_iam.h
  /*
   * Entry within index tree node. Consists of a key immediately followed
   * (without padding) by a pointer to the child node.
-@@ -718,5 +719,39 @@ void iam_format_register(struct iam_form
+@@ -226,7 +227,8 @@ struct iam_leaf_operations {
+          * split leaf node, moving some entries into @bh (the latter currently
+          * is assumed to be empty).
+          */
+-        void (*split)(struct iam_leaf *l, struct buffer_head *bh);
++        void (*split)(struct iam_leaf *l, struct buffer_head **bh,
++                      iam_ptr_t newblknr);
+ };
+ struct iam_path *iam_leaf_path(const struct iam_leaf *leaf);
+@@ -702,6 +704,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);
++int iam_leaf_can_add(const struct iam_leaf *l,
++                     const struct iam_key *k, const struct iam_rec *r);
+ struct iam_path *iam_leaf_path(const struct iam_leaf *leaf);
+ struct iam_container *iam_leaf_container(const struct iam_leaf *leaf);
+@@ -718,5 +722,40 @@ void iam_format_register(struct iam_form
  
  void iam_lfix_format_init(void);
  
 +struct iam_private_info;
 +
-+void ext3_iam_free_info(struct iam_private_info *info);
++void ext3_iam_release(struct file *filp, struct inode *inode);
 +
 +int iam_uapi_ioctl(struct inode * inode, struct file * filp, unsigned int cmd,
 +                   unsigned long arg);
@@ -357,8 +386,9 @@ Index: iam/include/linux/lustre_iam.h
 +enum iam_ioctl_cmd {
 +        IAM_IOC_INIT     = _IOW('i', 1, struct iam_uapi_info),
 +        IAM_IOC_GETINFO  = _IOR('i', 2, struct iam_uapi_info),
-+        IAM_IOC_INSERT   = _IOWR('i', 3, struct iam_uapi_op),
-+        IAM_IOC_LOOKUP   = _IOWR('i', 4, struct iam_uapi_op)
++        IAM_IOC_INSERT   = _IOR('i', 3, struct iam_uapi_op),
++        IAM_IOC_LOOKUP   = _IOWR('i', 4, struct iam_uapi_op),
++        IAM_IOC_DELETE   = _IOR('i', 5, struct iam_uapi_op)
 +};
 +
  /* __LINUX_LUSTRE_IAM_H__ */
index b83bf49..fd54635 100755 (executable)
Binary files a/lustre/tests/iam_ut and b/lustre/tests/iam_ut differ
index 867e020..5320c8d 100644 (file)
@@ -64,8 +64,9 @@ struct iam_uapi_op {
 enum iam_ioctl_cmd {
         IAM_IOC_INIT     = _IOW('i', 1, struct iam_uapi_info),
         IAM_IOC_GETINFO  = _IOR('i', 2, struct iam_uapi_info),
-        IAM_IOC_INSERT   = _IOWR('i', 3, struct iam_uapi_op),
-        IAM_IOC_LOOKUP   = _IOWR('i', 4, struct iam_uapi_op)
+        IAM_IOC_INSERT   = _IOR('i', 3, struct iam_uapi_op),
+        IAM_IOC_LOOKUP   = _IOWR('i', 4, struct iam_uapi_op),
+        IAM_IOC_DELETE   = _IOR('i', 5, struct iam_uapi_op)
 };
 
 static void usage(void)
@@ -73,7 +74,8 @@ static void usage(void)
         printf("usage: iam_ut [-v] [-h] file\n");
 }
 
-static int insert(int fd, const void *key, const void *rec)
+static int doop(int fd, const void *key, const void *rec,
+                int cmd, const char *name)
 {
         int result;
 
@@ -81,24 +83,25 @@ static int insert(int fd, const void *key, const void *rec)
                 .iul_key = key,
                 .iul_rec = rec
         };
-        result = ioctl(fd, IAM_IOC_INSERT, &op);
+        result = ioctl(fd, cmd, &op);
         if (result != 0)
-                fprintf(stderr, "ioctl(IAM_IOC_INSERT): %i (%m)\n", result);
+                fprintf(stderr, "ioctl(%s): %i/%i (%m)\n", name, result, errno);
         return result;
 }
 
+static int insert(int fd, const void *key, const void *rec)
+{
+        return doop(fd, key, rec, IAM_IOC_INSERT, "IAM_IOC_INSERT");
+}
+
 static int lookup(int fd, const void *key, void *rec)
 {
-        int result;
+        return doop(fd, key, rec, IAM_IOC_LOOKUP, "IAM_IOC_LOOKUP");
+}
 
-        struct iam_uapi_op op = {
-                .iul_key = key,
-                .iul_rec = rec
-        };
-        result = ioctl(fd, IAM_IOC_LOOKUP, &op);
-        if (result != 0)
-                fprintf(stderr, "ioctl(IAM_IOC_LOOKUP): %i (%m)\n", result);
-        return result;
+static int delete(int fd, const void *key, void *rec)
+{
+        return doop(fd, key, rec, IAM_IOC_DELETE, "IAM_IOC_DELETE");
 }
 
 static void print_rec(const unsigned char *rec, int nr)
@@ -113,31 +116,61 @@ static void print_rec(const unsigned char *rec, int nr)
         printf("\n");
 }
 
+enum op {
+        OP_TEST,
+        OP_INSERT,
+        OP_LOOKUP,
+        OP_DELETE
+};
+
 int main(int argc, char **argv)
 {
+        int i;
         int rc;
-        int fd;
         int opt;
-        int blocksize = 4096;
-        int keysize   = 8;
-        int recsize   = 8;
-        int ptrsize   = 4;
-        int verbose   = 0;
+        int keysize;
+        int recsize;
+        int verbose = 0;
+
+        enum op op;
+
+        char *key;
+        char *rec;
 
-        char *name;
-        char rec[8];
+        char *key_opt;
+        char *rec_opt;
 
         struct iam_uapi_info ua;
 
+        setbuf(stdout, NULL);
+        setbuf(stderr, NULL);
+
+        key_opt = NULL;
+        rec_opt = NULL;
+
+        op = OP_TEST;
+
         do {
-                opt = getopt(argc, argv, "v");
+                opt = getopt(argc, argv, "vilk:r:d");
                 switch (opt) {
                 case 'v':
                         verbose++;
                 case -1:
                         break;
-                case 'b':
-                        /* blocksize = atoi(optarg); */
+                case 'k':
+                        key_opt = optarg;
+                        break;
+                case 'r':
+                        rec_opt = optarg;
+                        break;
+                case 'i':
+                        op = OP_INSERT;
+                        break;
+                case 'l':
+                        op = OP_LOOKUP;
+                        break;
+                case 'd':
+                        op = OP_DELETE;
                         break;
                 case '?':
                 default:
@@ -148,52 +181,79 @@ int main(int argc, char **argv)
                 }
         } while (opt != -1);
 
-        if (optind >= argc) {
-                fprintf(stderr, "filename missed\n");
-                usage();
-                return 1;
-        }
-        name = argv[optind];
-        fd = open(name, O_RDWR);
-        if (fd == -1) {
-                fprintf(stderr, "open(%s): (%m)", name);
+        rc = ioctl(0, IAM_IOC_INIT, &ua);
+        if (rc != 0) {
+                fprintf(stderr, "ioctl(IAM_IOC_INIT): %i (%m)\n", rc);
                 return 1;
         }
-        rc = ioctl(fd, IAM_IOC_INIT, &ua);
+        rc = ioctl(0, IAM_IOC_GETINFO, &ua);
         if (rc != 0) {
-                fprintf(stderr, "ioctl(IAM_IOC_INIT): %i (%m)", rc);
+                fprintf(stderr, "ioctl(IAM_IOC_GETATTR): %i (%m)\n", rc);
                 return 1;
         }
-        rc = ioctl(fd, IAM_IOC_GETINFO, &ua);
-        if (rc != 0) {
-                fprintf(stderr, "ioctl(IAM_IOC_GETATTR): %i (%m)", rc);
+
+        keysize = ua.iui_keysize;
+        recsize = ua.iui_recsize;
+        if (verbose > 0)
+                printf("keysize: %i, recsize: %i, ptrsize: %i, "
+                       "height: %i, name: %s\n",
+                       keysize, recsize, ua.iui_ptrsize,
+                       ua.iui_height, ua.iui_fmt_name);
+
+        key = calloc(keysize + 1, sizeof key[0]);
+        rec = calloc(recsize + 1, sizeof rec[0]);
+
+        if (key == NULL || rec == NULL) {
+                fprintf(stderr, "cannot allocte memory\n");
                 return 1;
         }
 
-        printf("keysize: %i, recsize: %i, ptrsize: %i, height: %i, name: %s\n",
-               ua.iui_keysize, ua.iui_recsize, ua.iui_ptrsize,
-               ua.iui_height, ua.iui_fmt_name);
+        strncpy(key, key_opt ? : "RIVERRUN", keysize + 1);
+        strncpy(rec, rec_opt ? : "PALEFIRE", recsize + 1);
 
-        rc = insert(fd, "RIVERRUN", "PALEFIRE");
+        if (op == OP_INSERT)
+                return insert(0, key, rec);
+        else if (op == OP_DELETE)
+                return delete(0, key, rec);
+        else if (op == OP_LOOKUP) {
+                rc = lookup(0, key, rec);
+                if (rc == 0)
+                        print_rec(rec, recsize);
+                return rc;
+        }
+
+        rc = insert(0, key, rec);
         if (rc != 0)
                 return 1;
 
-        rc = insert(fd, "DAEDALUS", "FINNEGAN");
+        rc = insert(0, "DAEDALUS", "FINNEGAN");
         if (rc != 0)
                 return 1;
 
-        rc = insert(fd, "DAEDALUS", "FINNEGAN");
+        rc = insert(0, "DAEDALUS", "FINNEGAN");
         if (errno != EEXIST) {
                 if (rc == 0)
                         fprintf(stderr, "Duplicate key not detected!\n");
                 return 1;
         }
 
-        rc = lookup(fd, "RIVERRUN", rec);
+        rc = lookup(0, "RIVERRUN", rec);
         if (rc != 0)
                 return 1;
 
-        print_rec(rec, 8);
+        print_rec(rec, recsize);
+
+        for (i = 0; i < 1000; ++i) {
+                memset(key, 0, keysize + 1);
+                memset(rec, 0, recsize + 1);
+                snprintf(key, keysize, "y-%x-x", i);
+                snprintf(rec, recsize, "p-%x-q", 1000 - i);
+                rc = insert(0, key, rec);
+                if (rc != 0)
+                        return 1;
+                if (verbose > 1)
+                        printf("key %i inserted\n", i);
+        }
 
         return 0;
 }