From: nikita Date: Thu, 8 Jun 2006 22:13:29 +0000 (+0000) Subject: cleanup of iam code: add explicit states for leaves. X-Git-Tag: v1_8_0_110~486^2~1649 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=b5435bd46153e73984e02fa35cae6072fe3a458b;p=fs%2Flustre-release.git cleanup of iam code: add explicit states for leaves. --- diff --git a/lustre/kernel_patches/patches/ext3-iam-separate.patch b/lustre/kernel_patches/patches/ext3-iam-separate.patch index e6af788..0ac62184 100644 --- a/lustre/kernel_patches/patches/ext3-iam-separate.patch +++ b/lustre/kernel_patches/patches/ext3-iam-separate.patch @@ -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-08 01:08:10.000000000 +0400 ++++ iam/fs/ext3/Makefile 2006-06-08 21:50:42.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-08 01:08:07.000000000 +0400 -@@ -0,0 +1,1125 @@ ++++ iam/fs/ext3/iam.c 2006-06-08 19:42:19.000000000 +0400 +@@ -0,0 +1,1163 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * @@ -599,7 +599,7 @@ Index: iam/fs/ext3/iam.c + iam_path_fini(&it->ii_path); +} + -+int iam_path_lookup(struct iam_path *path) ++static int iam_path_lookup(struct iam_path *path) +{ + struct iam_container *c; + struct iam_descr *descr; @@ -615,8 +615,8 @@ Index: iam/fs/ext3/iam.c + 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); ++ result = iam_leaf_ops(leaf)-> ++ lookup(leaf, path->ip_key_target); + } + return result; +} @@ -629,9 +629,8 @@ Index: iam/fs/ext3/iam.c + * -ve: error. + * + * precondition: it_state(it) == IAM_IT_DETACHED -+ * postcondition: ergo(result == 0, -+ * (it_state(it) == IAM_IT_ATTACHED && -+ * it_keycmp(it, iam_it_key_get(it, *), k) < 0)) ++ * postcondition: ergo(result == 0 && it_state(it) == IAM_IT_ATTACHED, ++ * it_keycmp(it, iam_it_key_get(it, *), k) <= 0) + */ +int iam_it_get(struct iam_iterator *it, const struct iam_key *k) +{ @@ -641,14 +640,30 @@ Index: iam/fs/ext3/iam.c + it->ii_path.ip_key_target = k; + iam_it_lock(it); + result = iam_path_lookup(&it->ii_path); -+ if (result == 0 || result == -ENOENT) -+ it->ii_state = IAM_IT_ATTACHED; -+ else ++ if (result >= 0) { ++ switch (result) { ++ case IAM_LOOKUP_OK: ++ it->ii_state = IAM_IT_ATTACHED; ++ break; ++ case IAM_LOOKUP_EMPTY: ++ it->ii_state = IAM_IT_EMPTY; ++ break; ++ case IAM_LOOKUP_BEFORE: ++ it->ii_state = IAM_IT_BEFORE; ++ break; ++ default: ++ assert(0); ++ } ++ result = 0; ++ } else + iam_it_unlock(it); -+ assert(ergo(result == 0, -+ it_keycmp(it, -+ iam_it_key_get(it, it_scratch_key(it, 0)), ++ assert(ergo(result == 0 && it_state(it) == IAM_IT_ATTACHED, ++ it_keycmp(it, iam_it_key_get(it, it_scratch_key(it, 0)), + k) <= 0)); ++ /* ++ * See iam_it_get_exact() for explanation. ++ */ ++ assert(result != -ENOENT); + return result; +} + @@ -686,7 +701,7 @@ Index: iam/fs/ext3/iam.c + */ +void iam_it_put(struct iam_iterator *it) +{ -+ if (it->ii_state == IAM_IT_ATTACHED) { ++ 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); @@ -706,39 +721,44 @@ Index: iam/fs/ext3/iam.c +int iam_it_next(struct iam_iterator *it) +{ + int result; -+ struct iam_container *c; + struct iam_path *path; + struct iam_leaf *leaf; + -+ assert(it_state(it) == IAM_IT_ATTACHED && it->ii_flags&IAM_IT_MOVE); ++ assert(it->ii_flags&IAM_IT_MOVE); ++ assert(it_state(it) == IAM_IT_ATTACHED || ++ it_state(it) == IAM_IT_BEFORE || it_state(it) == IAM_IT_EMPTY); + -+ c = iam_it_container(it); + path = &it->ii_path; + leaf = &path->ip_leaf; + -+ if (!iam_leaf_at_end(leaf)) { -+ /* advance within leaf node */ -+ iam_leaf_next(leaf); -+ result = 0; ++ result = 0; ++ if (it_state(it) == IAM_IT_BEFORE) { ++ assert(!iam_leaf_at_end(leaf)); ++ it->ii_state = IAM_IT_ATTACHED; + } else { ++ if (!iam_leaf_at_end(leaf)) ++ /* advance within leaf node */ ++ iam_leaf_next(leaf); + /* + * multiple iterations may be necessary due to empty leaves. + */ -+ do { ++ while (result == 0 && iam_leaf_at_end(leaf)) { + /* advance index portion of the path */ -+ result = iam_index_next(c, path); ++ result = iam_index_next(iam_it_container(it), path); + if (result == 1) { + result = iam_leaf_load(path); + if (result == 0) + iam_leaf_start(leaf); -+ } else if (result == 0) ++ } else if (result == 0) { + /* end of container reached */ ++ it->ii_state = IAM_IT_EOC; + result = +1; ++ } + if (result < 0) + iam_it_put(it); -+ } while (result == 0 && iam_leaf_at_end(leaf)); ++ } + } -+ assert(ergo(result >= 0, it_state(it) == IAM_IT_ATTACHED)); ++ assert(ergo(result == 0, it_state(it) == IAM_IT_ATTACHED)); + return result; +} + @@ -797,12 +817,14 @@ Index: iam/fs/ext3/iam.c +/* + * Return pointer to the key under iterator. + * -+ * precondition: it_state(it) == IAM_IT_ATTACHED && it_at_rec(it) ++ * precondition: it_state(it) == IAM_IT_ATTACHED || ++ * it_state(it) == IAM_IT_BEFORE + * postcondition: it_state(it) == IAM_IT_ATTACHED + */ +struct iam_key *iam_it_key_get(const struct iam_iterator *it, struct iam_key *k) +{ -+ assert(it_state(it) == IAM_IT_ATTACHED); ++ assert(it_state(it) == IAM_IT_ATTACHED || ++ it_state(it) == IAM_IT_BEFORE); + assert(it_at_rec(it)); + return iam_leaf_key(&it->ii_path.ip_leaf, k); +} @@ -873,11 +895,18 @@ Index: iam/fs/ext3/iam.c + * Insert new record with key @k and contents from @r, shifting records to the + * right. + * -+ * precondition: it_state(it) == IAM_IT_ATTACHED && -+ * it->ii_flags&IAM_IT_WRITE && -+ * it_keycmp(it, iam_it_key_get(it, *), k) < 0 -+ * postcondition: it_state(it) == IAM_IT_ATTACHED && -+ * ergo(result == 0, ++ * precondition: it->ii_flags&IAM_IT_WRITE && ++ * (it_state(it) == IAM_IT_ATTACHED || ++ * it_state(it) == IAM_IT_BEFORE || ++ * it_state(it) == IAM_IT_EMPTY) && ++ * ergo(it_state(it) == IAM_IT_ATTACHED, ++ * it_keycmp(it, iam_it_key_get(it, it_scratch_key(it, 0)), ++ * k) < 0) && ++ * ergo(it_state(it) == IAM_IT_BEFORE, ++ * it_keycmp(it, iam_it_key_get(it, it_scratch_key(it, 0)), ++ * k) > 0)); ++ * postcondition: ergo(result == 0, ++ * it_state(it) == IAM_IT_ATTACHED && + * it_keycmp(it, iam_it_key_get(it, *), k) == 0 && + * !memcmp(iam_it_rec_get(it), r, ...)) + */ @@ -889,25 +918,20 @@ Index: iam/fs/ext3/iam.c + + path = &it->ii_path; + -+ assert(it_state(it) == IAM_IT_ATTACHED && it->ii_flags&IAM_IT_WRITE); -+ /* -+ * if insertion point is at the existing record... -+ */ -+ assert(ergo(it_at_rec(it), -+ /* -+ * this record either has the key smaller then target -+ * key... -+ */ ++ assert(it->ii_flags&IAM_IT_WRITE); ++ assert(it_state(it) == IAM_IT_ATTACHED || ++ it_state(it) == IAM_IT_BEFORE || it_state(it) == IAM_IT_EMPTY); ++ assert(ergo(it_state(it) == IAM_IT_ATTACHED, ++ it_keycmp(it, iam_it_key_get(it, it_scratch_key(it, 0)), ++ k) < 0)); ++ assert(ergo(it_state(it) == IAM_IT_BEFORE, + it_keycmp(it, iam_it_key_get(it, it_scratch_key(it, 0)), -+ k) < 0 || -+ /* -+ * or we landed into leaf where the smallest key is larger -+ * than the target key. -+ */ -+ path->ip_leaf.il_at == path->ip_leaf.il_entries)); ++ k) > 0)); + result = iam_add_rec(h, path, k, r); -+ assert(it_state(it) == IAM_IT_ATTACHED); ++ if (result == 0) ++ it->ii_state = IAM_IT_ATTACHED; + assert(ergo(result == 0, ++ it_state(it) == IAM_IT_ATTACHED && + it_keycmp(it, iam_it_key_get(it, it_scratch_key(it, 0)), + k) == 0 && + !memcmp(iam_it_rec_get(it), r, @@ -915,38 +939,46 @@ Index: iam/fs/ext3/iam.c + return result; +} + -+static int iam_leaf_rec_remove(handle_t *handle, struct iam_leaf *leaf) -+{ -+ assert(iam_leaf_check(leaf)); -+ assert(iam_path_check(iam_leaf_path(leaf))); -+ iam_rec_del(leaf); -+ assert(iam_leaf_check(leaf)); -+ assert(iam_path_check(iam_leaf_path(leaf))); -+ return iam_txn_dirty(handle, iam_leaf_path(leaf), leaf->il_bh); -+} -+ +/* + * Delete record under iterator. + * + * precondition: it_state(it) == IAM_IT_ATTACHED && + * it->ii_flags&IAM_IT_WRITE && + * it_at_rec(it) -+ * postcondition: it_state(it) == IAM_IT_ATTACHED ++ * postcondition: it_state(it) == IAM_IT_ATTACHED || it_state(it) == IAM_IT_EOC + */ +int iam_it_rec_delete(handle_t *h, struct iam_iterator *it) +{ + int result; ++ struct iam_leaf *leaf; ++ struct iam_path *path; + + assert(it_state(it) == IAM_IT_ATTACHED && it->ii_flags&IAM_IT_WRITE); + assert(it_at_rec(it)); + -+ result = iam_txn_add(h, &it->ii_path, it->ii_path.ip_leaf.il_bh); ++ path = &it->ii_path; ++ leaf = &path->ip_leaf; ++ ++ assert(iam_leaf_check(leaf)); ++ assert(iam_path_check(path)); ++ ++ result = iam_txn_add(h, path, leaf->il_bh); + /* + * no compaction for now. + */ -+ if (result == 0) -+ iam_leaf_rec_remove(h, &it->ii_path.ip_leaf); -+ ++ if (result == 0) { ++ iam_rec_del(leaf); ++ result = iam_txn_dirty(h, path, leaf->il_bh); ++ if (result == 0 && iam_leaf_at_end(leaf) && ++ it->ii_flags&IAM_IT_MOVE) { ++ result = iam_it_next(it); ++ if (result > 0) ++ result = 0; ++ } ++ } ++ assert(iam_leaf_check(leaf)); ++ assert(iam_path_check(path)); ++ assert(it_state(it) == IAM_IT_ATTACHED || it_state(it) == IAM_IT_EOC); + return result; +} + @@ -1035,10 +1067,16 @@ Index: iam/fs/ext3/iam.c +{ + return + (it->ii_state == IAM_IT_DETACHED || -+ it->ii_state == IAM_IT_ATTACHED) && ++ it->ii_state == IAM_IT_ATTACHED || ++ it->ii_state == IAM_IT_EMPTY || ++ it->ii_state == IAM_IT_BEFORE || ++ it->ii_state == IAM_IT_EOC) && + !(it->ii_flags & ~(IAM_IT_MOVE | IAM_IT_WRITE)) && -+ ergo(it->ii_state == IAM_IT_ATTACHED, -+ iam_path_invariant(&it->ii_path)); ++ ergo(it->ii_state == IAM_IT_ATTACHED || ++ it->ii_state == IAM_IT_EMPTY || ++ it->ii_state == IAM_IT_BEFORE, ++ iam_path_invariant(&it->ii_path) && ++ equi(it->ii_state == IAM_IT_EMPTY, !it_at_rec(it))); +} + +/* @@ -1144,8 +1182,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-06-08 00:36:08.000000000 +0400 -@@ -0,0 +1,610 @@ ++++ iam/fs/ext3/iam_lfix.c 2006-06-08 17:34:38.000000000 +0400 +@@ -0,0 +1,613 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * @@ -1351,11 +1389,13 @@ Index: iam/fs/ext3/iam_lfix.c + struct iam_lentry *p, *q, *m, *t; + struct iam_container *c; + int count; ++ int result; + + count = lentry_count_get(l); + if (count == 0) -+ return -ENOENT; ++ return IAM_LOOKUP_EMPTY; + ++ result = IAM_LOOKUP_OK; + c = iam_leaf_container(l); + + p = l->il_entries; @@ -1365,6 +1405,7 @@ Index: iam/fs/ext3/iam_lfix.c + * @k is less than the smallest 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 { @@ -1392,7 +1433,7 @@ Index: iam/fs/ext3/iam_lfix.c + } + assert(iam_leaf_at_rec(l)); + -+ return iam_keycmp(c, iam_leaf_key_at(l->il_at), k) != 0 ? -ENOENT : 0; ++ return result; +} + +static void iam_lfix_key_set(struct iam_leaf *l, const struct iam_key *k) @@ -3392,7 +3433,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-08 01:08:10.000000000 +0400 ++++ iam/include/linux/lustre_iam.h 2006-06-08 21:50:42.000000000 +0400 @@ -1,9 +1,68 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: diff --git a/lustre/kernel_patches/patches/ext3-iam-uapi.patch b/lustre/kernel_patches/patches/ext3-iam-uapi.patch index 8a66ab0..9209dfb 100644 --- a/lustre/kernel_patches/patches/ext3-iam-uapi.patch +++ b/lustre/kernel_patches/patches/ext3-iam-uapi.patch @@ -1,7 +1,7 @@ Index: iam/fs/ext3/Makefile =================================================================== ---- iam.orig/fs/ext3/Makefile 2006-06-08 01:08:10.000000000 +0400 -+++ iam/fs/ext3/Makefile 2006-06-08 01:08:11.000000000 +0400 +--- iam.orig/fs/ext3/Makefile 2006-06-08 21:50:42.000000000 +0400 ++++ iam/fs/ext3/Makefile 2006-06-08 21:50:42.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-06-08 01:08:10.000000000 +0400 -+++ iam/fs/ext3/file.c 2006-06-08 01:08:11.000000000 +0400 +--- iam.orig/fs/ext3/file.c 2006-06-08 21:50:42.000000000 +0400 ++++ iam/fs/ext3/file.c 2006-06-08 21:50:42.000000000 +0400 @@ -23,6 +23,7 @@ #include #include @@ -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-06-08 01:08:11.000000000 +0400 -@@ -0,0 +1,256 @@ ++++ iam/fs/ext3/iam-uapi.c 2006-06-08 21:50:42.000000000 +0400 +@@ -0,0 +1,349 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * @@ -94,6 +94,7 @@ Index: iam/fs/ext3/iam-uapi.c +struct iam_private_info { + struct iam_container ipi_bag; + struct iam_descr ipi_descr; ++ struct iam_iterator ipi_it; + struct iam_path_descr *ipi_ipd; +}; + @@ -106,6 +107,48 @@ Index: iam/fs/ext3/iam-uapi.c + return filp->private_data; +} + ++static int iam_uapi_it(int cmd, struct inode *inode, ++ struct file *filp, struct iam_uapi_it *itop) ++{ ++ struct iam_private_info *ipi; ++ struct iam_iterator *it; ++ enum iam_it_state st; ++ int result = 0; ++ ++ ipi = get_ipi(filp); ++ it = &ipi->ipi_it; ++ st = it->ii_state; ++ switch (cmd) { ++ case IAM_IOC_IT_START: ++ result = iam_it_init(it, &ipi->ipi_bag, ++ IAM_IT_MOVE, ipi->ipi_ipd); ++ if (result == 0) ++ result = iam_it_get(it, itop->iui_op.iul_key); ++ break; ++ case IAM_IOC_IT_NEXT: ++ if (st == IAM_IT_ATTACHED || ++ st == IAM_IT_BEFORE || st == IAM_IT_EMPTY) ++ result = iam_it_next(it); ++ else ++ result = -EBUSY; ++ break; ++ case IAM_IOC_IT_STOP: ++ iam_it_put(it); ++ iam_it_fini(it); ++ result = 0; ++ break; ++ } ++ st = it->ii_state; ++ if (st == IAM_IT_ATTACHED || st == IAM_IT_BEFORE) ++ iam_keycpy0(&ipi->ipi_bag, itop->iui_op.iul_key, ++ iam_it_key_get(it, itop->iui_op.iul_key)); ++ if (st == IAM_IT_ATTACHED) ++ iam_reccpy(&it->ii_path, ++ itop->iui_op.iul_rec, iam_it_rec_get(it)); ++ itop->iui_state = st; ++ return result; ++} ++ +static int iam_uapi_op(int cmd, struct inode *inode, + struct file *filp, struct iam_uapi_op *op) +{ @@ -151,6 +194,8 @@ Index: iam/fs/ext3/iam-uapi.c + struct iam_private_info *info; + + info = filp->private_data; ++ iam_it_put(&info->ipi_it); ++ iam_it_fini(&info->ipi_it); + iam_container_fini(&info->ipi_bag); + if (info->ipi_ipd != NULL) + iam_ipd_free(info->ipi_ipd); @@ -207,8 +252,9 @@ Index: iam/fs/ext3/iam-uapi.c +} + +enum outop_t { -+ KEY = 1 << 0, -+ REC = 1 << 1 ++ KEY = 1 << 0, ++ REC = 1 << 1, ++ STATE = 1 << 2 +}; + +static int outop(struct iam_uapi_op *op, struct iam_uapi_op *uop, @@ -256,15 +302,39 @@ Index: iam/fs/ext3/iam-uapi.c + return result; +} + ++static int outit(struct iam_uapi_it *it, struct iam_uapi_it *uit, ++ struct iam_descr *des, enum outop_t opt, unsigned long arg) ++{ ++ int result; ++ ++ result = outop(&it->iui_op, &uit->iui_op, des, opt); ++ if (result == 0 && (opt&STATE)) ++ result = put_user(it->iui_state, (int __user *) arg); ++ return result; ++} ++ ++static void putit(struct iam_uapi_it *it) ++{ ++ putop(&it->iui_op); ++} ++ ++static int getit(struct iam_uapi_it *it, struct iam_uapi_it *uit, ++ struct iam_descr *des, unsigned long arg) ++{ ++ return getop(&it->iui_op, &uit->iui_op, des, ++ (unsigned long)&((struct iam_uapi_it *)arg)->iui_op); ++} ++ +int iam_uapi_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int result; -+ union { -+ struct iam_uapi_info ua; -+ struct iam_uapi_op op; -+ } u; -+ struct iam_uapi_op uop; ++ struct iam_uapi_info ua; ++ struct iam_uapi_op uop; ++ struct iam_uapi_op op; ++ struct iam_uapi_it uit; ++ struct iam_uapi_it it; ++ enum outop_t opt; + + if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) + result = -EACCES; @@ -272,35 +342,58 @@ Index: iam/fs/ext3/iam-uapi.c + result = -EBADF; + else if (cmd == IAM_IOC_INIT) { + if (filp->private_data == NULL) { -+ result = getua(&u.ua, arg); ++ result = getua(&ua, arg); + if (result == 0) -+ result = iam_uapi_init(inode, filp, &u.ua); ++ result = iam_uapi_init(inode, filp, &ua); + } else + result = -EBUSY; + } else if (is_dx(inode) && filp->private_data != NULL) { + struct iam_descr *des; + ++ switch (cmd) { ++ case IAM_IOC_IT_START: ++ case IAM_IOC_IT_NEXT: ++ opt = KEY|REC|STATE; ++ break; ++ case IAM_IOC_LOOKUP: ++ opt = REC; ++ break; ++ default: ++ opt = 0; ++ break; ++ } ++ + des = &get_ipi(filp)->ipi_descr; + if (cmd == IAM_IOC_GETINFO) { -+ u.ua.iui_keysize = des->id_key_size; -+ u.ua.iui_recsize = des->id_rec_size; -+ u.ua.iui_ptrsize = des->id_ptr_size; -+ u.ua.iui_height = 0; /* not yet */ -+ memcpy(u.ua.iui_fmt_name, des->id_ops->id_name, -+ ARRAY_SIZE(u.ua.iui_fmt_name)); -+ result = putua(&u.ua, arg); ++ ua.iui_keysize = des->id_key_size; ++ ua.iui_recsize = des->id_rec_size; ++ ua.iui_ptrsize = des->id_ptr_size; ++ ua.iui_height = 0; /* not yet */ ++ memcpy(ua.iui_fmt_name, des->id_ops->id_name, ++ ARRAY_SIZE(ua.iui_fmt_name)); ++ result = putua(&ua, arg); + } else if (cmd == IAM_IOC_INSERT || cmd == IAM_IOC_LOOKUP || + cmd == IAM_IOC_DELETE) { -+ result = getop(&u.op, &uop, des, arg); ++ result = getop(&op, &uop, des, arg); ++ if (result == 0) { ++ int res2; ++ result = iam_uapi_op(cmd, inode, filp, &op); ++ ++ res2 = outop(&op, &uop, des, opt); ++ result = result ? : res2; ++ putop(&op); ++ } ++ } else if (cmd == IAM_IOC_IT_START || cmd == IAM_IOC_IT_NEXT || ++ cmd == IAM_IOC_IT_STOP) { ++ result = getit(&it, &uit, 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, REC); -+ result = result ? : res2; -+ } -+ putop(&u.op); ++ int res2; ++ ++ result = iam_uapi_it(cmd, inode, filp, &it); ++ ++ res2 = outit(&it, &uit, des, opt, arg); ++ result = result ? : res2; ++ putit(&it); + } + } else + result = -EINVAL; @@ -310,8 +403,8 @@ Index: iam/fs/ext3/iam-uapi.c +} Index: iam/include/linux/lustre_iam.h =================================================================== ---- iam.orig/include/linux/lustre_iam.h 2006-06-08 01:08:10.000000000 +0400 -+++ iam/include/linux/lustre_iam.h 2006-06-08 01:08:11.000000000 +0400 +--- iam.orig/include/linux/lustre_iam.h 2006-06-08 21:50:42.000000000 +0400 ++++ iam/include/linux/lustre_iam.h 2006-06-08 21:50:42.000000000 +0400 @@ -30,9 +30,6 @@ #ifndef __LINUX_LUSTRE_IAM_H__ #define __LINUX_LUSTRE_IAM_H__ @@ -350,7 +443,29 @@ Index: iam/include/linux/lustre_iam.h typedef __u64 iam_ptr_t; /* -@@ -131,11 +132,15 @@ struct iam_operations { +@@ -123,6 +124,21 @@ struct iam_leaf { + void *il_descr_data; + }; + ++enum iam_lookup_t { ++ /* ++ * lookup positioned leaf on some record ++ */ ++ IAM_LOOKUP_OK, ++ /* ++ * leaf was empty ++ */ ++ IAM_LOOKUP_EMPTY, ++ /* ++ * lookup positioned leaf before first record ++ */ ++ IAM_LOOKUP_BEFORE ++}; ++ + struct iam_operations { + /* + * Returns pointer (in the same sense as pointer in index entry) to +@@ -131,11 +147,15 @@ struct iam_operations { __u32 (*id_root_ptr)(struct iam_container *c); /* @@ -368,7 +483,7 @@ Index: iam/include/linux/lustre_iam.h * Initialize new node (stored in @bh) that is going to be added into * tree. */ -@@ -155,6 +160,10 @@ struct iam_operations { +@@ -155,6 +175,10 @@ struct iam_operations { * contains single record with the smallest possible key. */ int (*id_create)(struct iam_container *c); @@ -379,7 +494,7 @@ Index: iam/include/linux/lustre_iam.h /* * Format name. */ -@@ -226,7 +235,8 @@ struct iam_leaf_operations { +@@ -226,7 +250,8 @@ struct iam_leaf_operations { * split leaf node, moving some entries into @bh (the latter currently * is assumed to be empty). */ @@ -389,7 +504,22 @@ Index: iam/include/linux/lustre_iam.h }; struct iam_path *iam_leaf_path(const struct iam_leaf *leaf); -@@ -468,7 +478,7 @@ int iam_it_next(struct iam_iterator *it) +@@ -347,7 +372,13 @@ enum iam_it_state { + /* initial state */ + IAM_IT_DETACHED, + /* iterator is above particular record in the container */ +- IAM_IT_ATTACHED ++ IAM_IT_ATTACHED, ++ /* iterator landed into empty leaf */ ++ IAM_IT_EMPTY, ++ /* iterator is positioned before first record in the leaf */ ++ IAM_IT_BEFORE, ++ /* end of container reached */ ++ IAM_IT_EOC + }; + + /* +@@ -468,7 +499,7 @@ int iam_it_next(struct iam_iterator *it) /* * Return pointer to the record under iterator. * @@ -398,7 +528,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,7 +486,9 @@ struct iam_rec *iam_it_rec_get(const str +@@ -476,7 +507,9 @@ struct iam_rec *iam_it_rec_get(const str /* * Replace contents of record under iterator. * @@ -409,7 +539,7 @@ Index: iam/include/linux/lustre_iam.h * postcondition: it_state(it) == IAM_IT_ATTACHED && * ergo(result == 0, !memcmp(iam_it_rec_get(it), r, ...)) */ -@@ -485,7 +497,7 @@ int iam_it_rec_set(handle_t *h, struct i +@@ -485,7 +518,7 @@ int iam_it_rec_set(handle_t *h, struct i /* * Place key under iterator in @k, return @k * @@ -418,7 +548,7 @@ Index: iam/include/linux/lustre_iam.h * postcondition: it_state(it) == IAM_IT_ATTACHED */ struct iam_key *iam_it_key_get(const struct iam_iterator *it, -@@ -497,7 +509,8 @@ struct iam_key *iam_it_key_get(const str +@@ -497,7 +530,8 @@ struct iam_key *iam_it_key_get(const str * * precondition: it_state(it) == IAM_IT_ATTACHED && * it->ii_flags&IAM_IT_WRITE && @@ -428,7 +558,7 @@ Index: iam/include/linux/lustre_iam.h * postcondition: it_state(it) == IAM_IT_ATTACHED && * ergo(result == 0, * it_keycmp(it, iam_it_key_get(it, *), k) == 0 && -@@ -508,7 +521,9 @@ int iam_it_rec_insert(handle_t *h, struc +@@ -508,7 +542,9 @@ int iam_it_rec_insert(handle_t *h, struc /* * Delete record under iterator. * @@ -439,7 +569,7 @@ Index: iam/include/linux/lustre_iam.h * postcondition: it_state(it) == IAM_IT_ATTACHED */ int iam_it_rec_delete(handle_t *h, struct iam_iterator *it); -@@ -519,7 +534,8 @@ typedef __u64 iam_pos_t; +@@ -519,7 +555,8 @@ typedef __u64 iam_pos_t; * Convert iterator to cookie. * * precondition: it_state(it) == IAM_IT_ATTACHED && @@ -449,7 +579,25 @@ 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); -@@ -650,6 +666,15 @@ static inline unsigned dx_node_limit(str +@@ -583,6 +620,17 @@ static inline void iam_keycpy(const stru + memcpy(k1, k2, c->ic_descr->id_key_size); + } + ++/* ++ * Helper for the frequent case, where key was already placed into @k1 by ++ * callback. ++ */ ++static inline void iam_keycpy0(const struct iam_container *c, ++ struct iam_key *k1, const struct iam_key *k2) ++{ ++ if (k1 != k2) ++ iam_keycpy(c, k1, k2); ++} ++ + static inline int iam_keycmp(const struct iam_container *c, + const struct iam_key *k1, const struct iam_key *k2) + { +@@ -650,6 +698,15 @@ static inline unsigned dx_node_limit(str return entry_space / (param->id_key_size + param->id_ptr_size); } @@ -465,7 +613,7 @@ 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 +727,8 @@ void iam_insert_key(struct iam_path *pat +@@ -702,6 +759,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); @@ -474,7 +622,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); -@@ -718,5 +745,40 @@ void iam_format_register(struct iam_form +@@ -718,5 +777,48 @@ void iam_format_register(struct iam_form void iam_lfix_format_init(void); @@ -505,12 +653,20 @@ Index: iam/include/linux/lustre_iam.h + void *iul_rec; +}; + ++struct iam_uapi_it { ++ struct iam_uapi_op iui_op; ++ __u16 iui_state; ++}; ++ +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 = _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) ++ IAM_IOC_DELETE = _IOR('i', 5, struct iam_uapi_op), ++ IAM_IOC_IT_START = _IOR('i', 6, struct iam_uapi_it), ++ IAM_IOC_IT_NEXT = _IOW('i', 7, struct iam_uapi_it), ++ IAM_IOC_IT_STOP = _IOR('i', 8, struct iam_uapi_it) +}; + /* __LINUX_LUSTRE_IAM_H__ */ diff --git a/lustre/tests/iam_ut b/lustre/tests/iam_ut index 28097e9f..0143197 100755 Binary files a/lustre/tests/iam_ut and b/lustre/tests/iam_ut differ diff --git a/lustre/tests/iam_ut.c b/lustre/tests/iam_ut.c index b4a4ac2..3af3d1f 100644 --- a/lustre/tests/iam_ut.c +++ b/lustre/tests/iam_ut.c @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -61,12 +62,20 @@ struct iam_uapi_op { void *iul_rec; }; +struct iam_uapi_it { + struct iam_uapi_op iui_op; + __u16 iui_state; +}; + 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 = _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) + IAM_IOC_DELETE = _IOR('i', 5, struct iam_uapi_op), + IAM_IOC_IT_START = _IOR('i', 6, struct iam_uapi_it), + IAM_IOC_IT_NEXT = _IOW('i', 7, struct iam_uapi_it), + IAM_IOC_IT_STOP = _IOR('i', 8, struct iam_uapi_it) }; static void usage(void) @@ -89,6 +98,29 @@ static int doop(int fd, const void *key, const void *rec, return result; } +static int doit(int fd, const void *key, const void *rec, + int cmd, const char *name) +{ + int result; + + struct iam_uapi_it it = { + .iui_op = { + .iul_key = key, + .iul_rec = rec + }, + .iui_state = 0 + }; + + assert((void *)&it == (void *)&it.iui_op); + + result = ioctl(fd, cmd, &it); + if (result != 0) + fprintf(stderr, "ioctl(%s): %i/%i (%m)\n", name, result, errno); + else + result = it.iui_state; + return result; +} + static int insert(int fd, const void *key, const void *rec) { return doop(fd, key, rec, IAM_IOC_INSERT, "IAM_IOC_INSERT"); @@ -120,7 +152,10 @@ enum op { OP_TEST, OP_INSERT, OP_LOOKUP, - OP_DELETE + OP_DELETE, + OP_IT_START, + OP_IT_NEXT, + OP_IT_STOP }; int main(int argc, char **argv) @@ -130,7 +165,9 @@ int main(int argc, char **argv) int opt; int keysize; int recsize; + int N = 0x10000; int verbose = 0; + int doinit = 1; enum op op; @@ -151,7 +188,7 @@ int main(int argc, char **argv) op = OP_TEST; do { - opt = getopt(argc, argv, "vilk:r:d"); + opt = getopt(argc, argv, "vilk:N:r:dsSn"); switch (opt) { case 'v': verbose++; @@ -160,6 +197,9 @@ int main(int argc, char **argv) case 'k': key_opt = optarg; break; + case 'N': + N = atoi(optarg); + break; case 'r': rec_opt = optarg; break; @@ -172,6 +212,17 @@ int main(int argc, char **argv) case 'd': op = OP_DELETE; break; + case 's': + op = OP_IT_START; + break; + case 'S': + op = OP_IT_STOP; + doinit = 0; + break; + case 'n': + op = OP_IT_NEXT; + doinit = 0; + break; case '?': default: fprintf(stderr, "Unable to parse options."); @@ -181,10 +232,12 @@ int main(int argc, char **argv) } } while (opt != -1); - rc = ioctl(0, IAM_IOC_INIT, &ua); - if (rc != 0) { - fprintf(stderr, "ioctl(IAM_IOC_INIT): %i (%m)\n", rc); - return 1; + if (doinit) { + rc = ioctl(0, IAM_IOC_INIT, &ua); + if (rc != 0) { + fprintf(stderr, "ioctl(IAM_IOC_INIT): %i (%m)\n", rc); + return 1; + } } rc = ioctl(0, IAM_IOC_GETINFO, &ua); if (rc != 0) { @@ -212,14 +265,30 @@ int main(int argc, char **argv) strncpy(rec, rec_opt ? : "PALEFIRE", recsize + 1); if (op == OP_INSERT) - return insert(0, key, rec); + return doop(0, key, rec, IAM_IOC_INSERT, "IAM_IOC_INSERT"); else if (op == OP_DELETE) - return delete(0, key, rec); + return doop(0, key, rec, IAM_IOC_DELETE, "IAM_IOC_DELETE"); else if (op == OP_LOOKUP) { - rc = lookup(0, key, rec); + rc = doop(0, key, rec, IAM_IOC_LOOKUP, "IAM_IOC_LOOKUP"); if (rc == 0) print_rec(rec, recsize); return rc; + } else if (op == OP_IT_START) { + rc = doop(0, key, rec, IAM_IOC_IT_START, "IAM_IOC_IT_START"); + if (rc == 0) { + print_rec(key, keysize); + print_rec(rec, recsize); + } + return rc; + } else if (op == OP_IT_STOP) { + return doop(0, key, rec, IAM_IOC_IT_STOP, "IAM_IOC_IT_STOP"); + } else if (op == OP_IT_NEXT) { + rc = doop(0, key, rec, IAM_IOC_IT_NEXT, "IAM_IOC_IT_NEXT"); + if (rc == 0) { + print_rec(key, keysize); + print_rec(rec, recsize); + } + return rc; } rc = insert(0, key, rec); @@ -243,11 +312,11 @@ int main(int argc, char **argv) print_rec(rec, recsize); - for (i = 0; i < 0x10000; ++i) { + for (i = 0; i < N; ++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); + snprintf(key, keysize + 1, "y-%x-x", i); + snprintf(rec, recsize + 1, "p-%x-q", 1000 - i); rc = insert(0, key, rec); if (rc != 0) return 1;