From 31640f2ee45004d76f81208a3d71f07b50058b1e Mon Sep 17 00:00:00 2001 From: nikita Date: Tue, 20 Jun 2006 22:57:05 +0000 Subject: [PATCH] iam: latest fixes --- ldiskfs/ldiskfs/Makefile.in | 2 +- .../kernel_patches/patches/ext3-iam-separate.patch | 1151 +++++++++++++++----- lustre/kernel_patches/patches/ext3-iam-uapi.patch | 76 +- lustre/ldiskfs/Makefile.in | 2 +- lustre/tests/iam_ut | Bin 61622 -> 62539 bytes lustre/tests/iam_ut.c | 39 +- 6 files changed, 962 insertions(+), 308 deletions(-) diff --git a/ldiskfs/ldiskfs/Makefile.in b/ldiskfs/ldiskfs/Makefile.in index 9c27db4..5a05bf8 100644 --- a/ldiskfs/ldiskfs/Makefile.in +++ b/ldiskfs/ldiskfs/Makefile.in @@ -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) diff --git a/lustre/kernel_patches/patches/ext3-iam-separate.patch b/lustre/kernel_patches/patches/ext3-iam-separate.patch index c8373e3..09815ea 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-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 + * Author: Nikita Danilov + * + * 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 +#include -+/* ext3_error() */ ++/* ext3_error(), EXT3_DIR_ROUND() */ +#include + +#include @@ -1306,32 +1305,39 @@ Index: iam/fs/ext3/iam_lfix.c +#include +#include + -+/* -+ * 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 ++ * Author: Nikita Danilov ++ * ++ * 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 ++#include ++/* ext3_error() */ ++#include + -+#define LFIX_ROOT_RECNO \ -+ ((4096 - sizeof(struct iam_lfix_root)) / (KEYSIZE + PTRSIZE)) ++#include + -+#define LFIX_INDEX_RECNO (4096 / (KEYSIZE + PTRSIZE)) ++#include ++#include + -+#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: diff --git a/lustre/kernel_patches/patches/ext3-iam-uapi.patch b/lustre/kernel_patches/patches/ext3-iam-uapi.patch index 9f1b46b..0855222 100644 --- a/lustre/kernel_patches/patches/ext3-iam-uapi.patch +++ b/lustre/kernel_patches/patches/ext3-iam-uapi.patch @@ -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 #include @@ -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); diff --git a/lustre/ldiskfs/Makefile.in b/lustre/ldiskfs/Makefile.in index 9c27db4..5a05bf8 100644 --- a/lustre/ldiskfs/Makefile.in +++ b/lustre/ldiskfs/Makefile.in @@ -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) diff --git a/lustre/tests/iam_ut b/lustre/tests/iam_ut index 01431972946d55c18b2d85d4a8a7f4a00ab5a89a..958c0f451b50fbb42e87bed663e161dce42f0d2b 100755 GIT binary patch delta 25572 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 CD4kXS delta 24524 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 diff --git a/lustre/tests/iam_ut.c b/lustre/tests/iam_ut.c index 3af3d1f..e85de08 100644 --- a/lustre/tests/iam_ut.c +++ b/lustre/tests/iam_ut.c @@ -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"); -- 1.8.3.1