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 \
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:
+ *
+ 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;
+}
+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);
+ 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);
+}
+ 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 */
+/***********************************************************************/
+ 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);
+
+ 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;
+ 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;
+}
+
+ 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;
+}
+
+ 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,
+
+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);
+}
+
+/*
+
+ 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.
+ */
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:
+ *
+ 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)
+
+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)
+ 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;
+ 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;
+
+ 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 = {
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
*/
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;
+ }
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: 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 \
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>
+ 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;
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:
+ *
+ 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);
+ 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,
+ 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;
+ 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);
+}
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__
/*
* 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);
+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__ */
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)
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;
.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)
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:
}
} 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;
}