-Index: linux-stage/fs/ext3/Makefile
+Index: iam/fs/ext3/Makefile
===================================================================
---- linux-stage.orig/fs/ext3/Makefile 2006-09-27 15:48:48.000000000 +0800
-+++ linux-stage/fs/ext3/Makefile 2006-09-27 15:49:15.000000000 +0800
-@@ -6,7 +6,7 @@
+--- iam.orig/fs/ext3/Makefile 2006-09-28 22:11:14.000000000 +0400
++++ iam/fs/ext3/Makefile 2006-10-03 00:15:55.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 \
ext3-$(CONFIG_EXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
-Index: linux-stage/fs/ext3/iam.c
+Index: iam/fs/ext3/iam.c
===================================================================
---- linux-stage.orig/fs/ext3/iam.c 2006-05-31 09:15:07.000000000 +0800
-+++ linux-stage/fs/ext3/iam.c 2006-09-27 15:49:15.000000000 +0800
-@@ -0,0 +1,1325 @@
+--- iam.orig/fs/ext3/iam.c 2004-04-06 17:27:52.000000000 +0400
++++ iam/fs/ext3/iam.c 2006-10-02 19:59:04.000000000 +0400
+@@ -0,0 +1,1326 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ if (err == 0) {
+ if (!iam_leaf_can_add(leaf, k, r)) {
+ err = split_index_node(handle, path);
++ assert(iam_path_check(path));
+ if (err == 0) {
+ err = iam_new_leaf(handle, leaf);
+ /*
+}
+EXPORT_SYMBOL(iam_delete);
+
-Index: linux-stage/fs/ext3/iam_htree.c
+Index: iam/fs/ext3/iam_htree.c
===================================================================
---- linux-stage.orig/fs/ext3/iam_htree.c 2006-05-31 09:15:07.000000000 +0800
-+++ linux-stage/fs/ext3/iam_htree.c 2006-09-27 15:49:15.000000000 +0800
+--- iam.orig/fs/ext3/iam_htree.c 2004-04-06 17:27:52.000000000 +0400
++++ iam/fs/ext3/iam_htree.c 2006-09-28 22:11:15.000000000 +0400
@@ -0,0 +1,665 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+{
+ iam_format_register(&iam_htree_format);
+}
-Index: linux-stage/fs/ext3/iam_lfix.c
+Index: iam/fs/ext3/iam_lfix.c
===================================================================
---- linux-stage.orig/fs/ext3/iam_lfix.c 2006-05-31 09:15:07.000000000 +0800
-+++ linux-stage/fs/ext3/iam_lfix.c 2006-09-27 15:49:15.000000000 +0800
-@@ -0,0 +1,670 @@
+--- iam.orig/fs/ext3/iam_lfix.c 2004-04-06 17:27:52.000000000 +0400
++++ iam/fs/ext3/iam_lfix.c 2006-10-02 16:34:29.000000000 +0400
+@@ -0,0 +1,673 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ root = (void *)frame->bh->b_data;
+ assert(le64_to_cpu(root->ilr_magic) == IAM_LFIX_ROOT_MAGIC);
+ root->ilr_indirect_levels ++;
-+ return iam_entry_shift(path, entries, 1);
++ frame->at = entries = iam_entry_shift(path, entries, 1);
++ memset(iam_ikey_at(path, entries), 0,
++ iam_path_descr(path)->id_ikey_size);
++ return entries;
+}
+
+static int iam_lfix_node_check(struct iam_path *path, struct iam_frame *frame)
+ char rec[RECSIZE];
+ } ll_entry[LFIX_LEAF_RECNO];
+};
-Index: linux-stage/fs/ext3/iam_lvar.c
+Index: iam/fs/ext3/iam_lvar.c
===================================================================
---- linux-stage.orig/fs/ext3/iam_lvar.c 2006-05-31 09:15:07.000000000 +0800
-+++ linux-stage/fs/ext3/iam_lvar.c 2006-09-27 15:51:04.000000000 +0800
-@@ -0,0 +1,897 @@
+--- iam.orig/fs/ext3/iam_lvar.c 2004-04-06 17:27:52.000000000 +0400
++++ iam/fs/ext3/iam_lvar.c 2006-10-02 16:33:55.000000000 +0400
+@@ -0,0 +1,900 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+{
+ lvar_hash_t hash;
+ const char *name;
-+
++
+ name = kchar(k);
-+
++
+ hash = get_hash(iam_leaf_container(l), name, strlen(name));
+ return e_cmp(l, n_cur(l), hash);
+}
+ root = (void *)frame->bh->b_data;
+ assert(le64_to_cpu(root->vr_magic) == IAM_LVAR_ROOT_MAGIC);
+ root->vr_indirect_levels ++;
-+ return iam_entry_shift(path, entries, 1);
++ frame->at = entries = iam_entry_shift(path, entries, 1);
++ memset(iam_ikey_at(path, entries), 0,
++ iam_path_descr(path)->id_ikey_size);
++ return entries;
+}
+
+static int lvar_node_check(struct iam_path *path, struct iam_frame *frame)
+ iam_format_register(&lvar_format);
+}
+
-Index: linux-stage/fs/ext3/namei.c
+Index: iam/fs/ext3/namei.c
===================================================================
---- linux-stage.orig/fs/ext3/namei.c 2006-09-27 15:49:15.000000000 +0800
-+++ linux-stage/fs/ext3/namei.c 2006-09-27 15:49:15.000000000 +0800
+--- iam.orig/fs/ext3/namei.c 2006-09-28 22:11:15.000000000 +0400
++++ iam/fs/ext3/namei.c 2006-10-02 22:39:52.000000000 +0400
@@ -24,81 +24,6 @@
* Theodore Ts'o, 2002
*/
{
struct buffer_head *bh;
-@@ -136,14 +61,15 @@
+@@ -136,14 +61,15 @@ static struct buffer_head *ext3_append(h
if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
inode->i_size += inode->i_sb->s_blocksize;
EXT3_I(inode)->i_disksize = inode->i_size;
#ifndef swap
#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
-@@ -155,293 +81,10 @@
+@@ -155,293 +81,10 @@ static struct buffer_head *ext3_append(h
#define dxtrace(command)
#endif
static unsigned dx_get_limit(struct iam_entry *entries);
static void dx_set_count(struct iam_entry *entries, unsigned value);
static void dx_set_limit(struct iam_entry *entries, unsigned value);
-@@ -457,264 +100,52 @@
+@@ -457,264 +100,53 @@ static void dx_sort_map(struct dx_map_en
static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
struct dx_map_entry *offsets, int count);
static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
e = dx_node_get_entries(p, f);
count = dx_get_count(e);
e = iam_entry_shift(p, e, 1);
++
+ inode = iam_path_obj(p);
for (i = 0; i < count - 1; ++i, e = iam_entry_shift(p, e, 1)) {
- keycpy(c, p->ip_key_scratch[0], p->ip_key_scratch[1]);
}
/*
-@@ -800,598 +231,132 @@
- }
- #endif /* DX_DEBUG */
-
+@@ -796,602 +228,120 @@ struct stats dx_show_entries(struct dx_h
+ if (bcount)
+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ",
+ names, space/bcount,(space/bcount)*100/blocksize);
+- return (struct stats) { names, space, bcount};
+-}
+-#endif /* DX_DEBUG */
+-
-static int dx_lookup(struct iam_path *path)
-{
- u32 ptr;
- .hinfo = &hinfo
- };
- int err, i;
-+int dx_lookup(struct iam_path *path)
-+{
-+ u32 ptr;
-+ int err = 0;
-+ int i;
-
+-
- iam_path_init(path, c, &hc);
- for (i = 0; i < ARRAY_SIZE(path->ip_key_scratch); ++i)
- path->ip_key_scratch[i] =
- err = dx_lookup(path);
- if (err)
- goto errout;
+-
+- err = iam_leaf_insert(handle, path, k, r);
+-
+- if (err != -ENOSPC)
+- goto errout;
+-
+- err = split_index_node(handle, path);
+- if (err)
+- goto errout;
+-
+- err = split_leaf_node(handle, path);
+- if (err)
+- goto errout;
+-
+- err = iam_leaf_insert(handle, path, k, r);
+-errout:
+- iam_path_fini(path);
+- return(err);
++ return (struct stats) { names, space, bcount};
+ }
++#endif /* DX_DEBUG */
+
+-EXPORT_SYMBOL(iam_insert);
+-static int iam_leaf_delete(handle_t *handle, struct iam_path *path,
+- struct iam_key *k)
++int dx_lookup(struct iam_path *path)
+ {
+- struct iam_leaf leaf;
+- struct iam_leaf_entry *p, *q;
+- int err, count;
+-
+- err = iam_leaf_init(path, &leaf);
+- if (err)
+- goto errout;
+-
+- err = iam_leaf_lookup(path, &leaf, k);
+- if (err)
+- goto errout;
+-
+- count = dx_get_count((struct iam_entry*)leaf.entries);
+- /*delete the k to leaf entries*/
+- p = iam_leaf_entry_shift(path, leaf.at, 1);
+- q = iam_leaf_entry_shift(path, leaf.entries, count - 1);
+- while (p < q) {
+- memcpy(p, iam_leaf_entry_shift(path, p, 1), iam_leaf_entry_size(path));
+- p = iam_leaf_entry_shift(path, p, 1);
+- }
+- dx_set_count((struct iam_entry*)leaf.entries, count - 1);
++ u32 ptr;
++ int err = 0;
++ int i;
+
+- err = ext3_journal_dirty_metadata(handle, leaf.bh);
+- if (err)
+- ext3_std_error(path_obj(path)->i_sb, err);
+-errout:
+- iam_leaf_fini(&leaf);
+- return err;
+-}
+ struct iam_descr *param;
+ struct iam_frame *frame;
+ struct iam_container *c;
-- err = iam_leaf_insert(handle, path, k, r);
+-/*
+- * Delete existing record with key @k.
+- *
+- * Return values: 0: success, -ENOENT: not-found, -ve: other error.
+- *
+- * postcondition: ergo(result == 0 || result == -ENOENT,
+- * !iam_lookup(c, k, *));
+- */
+-int iam_delete(handle_t *h, struct iam_container *c, struct iam_key *k)
+-{
+- struct dx_hash_info hinfo;
+- struct iam_path_compat cpath;
+- struct iam_path *path = &cpath.ipc_path;
+- struct htree_cookie hc = {
+- .hinfo = &hinfo
+- };
+- int err, i;
+ param = iam_path_descr(path);
+ c = path->ip_container;
-
-- if (err != -ENOSPC)
-- goto errout;
++
+ for (frame = path->ip_frames, i = 0,
+ ptr = param->id_ops->id_root_ptr(c);
+ i <= path->ip_indirect;
+ struct iam_entry *m;
+ unsigned count;
-- err = split_index_node(handle, path);
+- iam_path_init(path, c, &hc);
+- for (i = 0; i < ARRAY_SIZE(path->ip_key_scratch); ++i)
+- path->ip_key_scratch[i] =
+- (struct iam_key *)&cpath.ipc_scrach[i];
+- err = dx_lookup(path);
- if (err)
-- goto errout;
+- goto errout;
+ err = param->id_ops->id_node_read(c, (iam_ptr_t)ptr, NULL,
+ &frame->bh);
+ if (err != 0)
+ break;
-- err = split_leaf_node(handle, path);
-- if (err)
-- goto errout;
--
-- err = iam_leaf_insert(handle, path, k, r);
+- err = iam_leaf_delete(h, path, k);
-errout:
- iam_path_fini(path);
-- return(err);
+- return err;
-}
+ err = param->id_ops->id_node_check(path, frame);
+ if (err != 0)
+ break;
--EXPORT_SYMBOL(iam_insert);
--static int iam_leaf_delete(handle_t *handle, struct iam_path *path,
-- struct iam_key *k)
--{
-- struct iam_leaf leaf;
-- struct iam_leaf_entry *p, *q;
-- int err, count;
+-EXPORT_SYMBOL(iam_delete);
+ err = param->id_ops->id_node_load(path, frame);
+ if (err != 0)
+ break;
+-static int iam_leaf_update(handle_t *handle, struct iam_path *path,
+- struct iam_key *k, struct iam_rec *r)
+-{
+- struct iam_leaf leaf;
+- int err;
++ assert(dx_node_check(path, frame));
+
- err = iam_leaf_init(path, &leaf);
- if (err)
- goto errout;
- err = iam_leaf_lookup(path, &leaf, k);
- if (err)
- goto errout;
-+ assert(dx_node_check(path, frame));
-
-- count = dx_get_count((struct iam_entry*)leaf.entries);
-- /*delete the k to leaf entries*/
-- p = iam_leaf_entry_shift(path, leaf.at, 1);
-- q = iam_leaf_entry_shift(path, leaf.entries, count - 1);
-- while (p < q) {
-- memcpy(p, iam_leaf_entry_shift(path, p, 1), iam_leaf_entry_size(path));
-- p = iam_leaf_entry_shift(path, p, 1);
-- }
-- dx_set_count((struct iam_entry*)leaf.entries, count - 1);
+ entries = frame->entries;
+ count = dx_get_count(entries);
+ assert(count && count <= dx_get_limit(entries));
+ p = iam_entry_shift(path, entries, 1);
+ q = iam_entry_shift(path, entries, count - 1);
-+ /*
-+ * Sanity check: target key is larger or equal to the leftmost
-+ * key in the node.
-+ */
-+ if (!dx_index_is_compat(path) &&
-+ iam_ikeycmp(c, iam_ikey_at(path, p),
-+ path->ip_ikey_target) > 0) {
-+ struct inode *obj;
-+
-+ obj = c->ic_object;
-+ ext3_error(obj->i_sb, __FUNCTION__,
-+ "corrupted search tree #%lu", obj->i_ino);
-+ err = -EIO;
-+ break;
-+
-+ }
+ while (p <= q) {
+ m = iam_entry_shift(path,
+ p, iam_entry_diff(path, q, p) / 2);
+ p = iam_entry_shift(path, m, +1);
+ }
+- memcpy(iam_leaf_entry_at(path, leaf.at), r, path_descr(path)->id_rec_size);
+- memcpy(iam_leaf_key_at(path, leaf.at), k, path_descr(path)->id_key_size);
++ frame->at = iam_entry_shift(path, p, -1);
++ if (1) { // linear search cross check
++ unsigned n = count - 1;
++ struct iam_entry *at;
+
- err = ext3_journal_dirty_metadata(handle, leaf.bh);
- if (err)
- ext3_std_error(path_obj(path)->i_sb, err);
-errout:
- iam_leaf_fini(&leaf);
-+ frame->at = iam_entry_shift(path, p, -1);
-+ if (1) { // linear search cross check
-+ unsigned n = count - 1;
-+ struct iam_entry *at;
-+
+ at = entries;
+ while (n--) {
+ dxtrace(printk(","));
+ path->ip_frame = --frame;
return err;
}
-
++
/*
-- * Delete existing record with key @k.
+- * Replace existing record with key @k, or insert new one. New record data are
+- * in @r.
- *
-- * Return values: 0: success, -ENOENT: not-found, -ve: other error.
+- * Return values: 0: success, -ve: error.
+ * Probe for a directory leaf block to search.
*
-- * postcondition: ergo(result == 0 || result == -ENOENT,
-- * !iam_lookup(c, k, *));
+- * postcondition: ergo(result == 0, iam_lookup(c, k, r2) > 0 &&
+- * !memcmp(r, r2, c->ic_descr->id_rec_size));
+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
+ * error in the directory index, and the caller should fall back to
+ * searching the directory normally. The callers of dx_probe **MUST**
+ * check for this error code, and make sure it never gets reflected
+ * back to userspace.
*/
--int iam_delete(handle_t *h, struct iam_container *c, struct iam_key *k)
--{
+-int iam_update(handle_t *h, struct iam_container *c,
+- struct iam_key *k, struct iam_rec *r)
++static int dx_probe(struct dentry *dentry, struct inode *dir,
++ struct dx_hash_info *hinfo, struct iam_path *path)
+ {
- struct dx_hash_info hinfo;
- struct iam_path_compat cpath;
- struct iam_path *path = &cpath.ipc_path;
- .hinfo = &hinfo
- };
- int err, i;
--
+-
- iam_path_init(path, c, &hc);
- for (i = 0; i < ARRAY_SIZE(path->ip_key_scratch); ++i)
- path->ip_key_scratch[i] =
- err = dx_lookup(path);
- if (err)
- goto errout;
--
-- err = iam_leaf_delete(h, path, k);
--errout:
-- iam_path_fini(path);
-- return err;
--}
--
--EXPORT_SYMBOL(iam_delete);
--
--static int iam_leaf_update(handle_t *handle, struct iam_path *path,
-- struct iam_key *k, struct iam_rec *r)
-+static int dx_probe(struct dentry *dentry, struct inode *dir,
-+ struct dx_hash_info *hinfo, struct iam_path *path)
- {
-- struct iam_leaf leaf;
- int err;
++ int err;
+ struct iam_path_compat *ipc;
-- err = iam_leaf_init(path, &leaf);
-- if (err)
-- goto errout;
--
-- err = iam_leaf_lookup(path, &leaf, k);
-- if (err)
-- goto errout;
--
-- memcpy(iam_leaf_entry_at(path, leaf.at), r, path_descr(path)->id_rec_size);
-- memcpy(iam_leaf_key_at(path, leaf.at), k, path_descr(path)->id_key_size);
+- err = iam_leaf_update(h, path, k, r);
+-errout:
+- iam_path_fini(path);
+ assert(path->ip_data != NULL);
+ ipc = container_of(path->ip_data, struct iam_path_compat, ipc_descr);
+ ipc->ipc_dentry = dentry;
+ ipc->ipc_hinfo = hinfo;
-
-- err = ext3_journal_dirty_metadata(handle, leaf.bh);
-- if (err)
-- ext3_std_error(path_obj(path)->i_sb, err);
--errout:
-- iam_leaf_fini(&leaf);
-- return err;
--}
--/*
-- * Replace existing record with key @k, or insert new one. New record data are
-- * in @r.
-- *
-- * Return values: 0: success, -ve: error.
-- *
-- * postcondition: ergo(result == 0, iam_lookup(c, k, r2) > 0 &&
-- * !memcmp(r, r2, c->ic_descr->id_rec_size));
-- */
--int iam_update(handle_t *h, struct iam_container *c,
-- struct iam_key *k, struct iam_rec *r)
--{
-- struct dx_hash_info hinfo;
-- struct iam_path_compat cpath;
-- struct iam_path *path = &cpath.ipc_path;
-- struct htree_cookie hc = {
-- .hinfo = &hinfo
-- };
-- int err, i;
--
-- iam_path_init(path, c, &hc);
-- for (i = 0; i < ARRAY_SIZE(path->ip_key_scratch); ++i)
-- path->ip_key_scratch[i] =
-- (struct iam_key *)&cpath.ipc_scrach[i];
++
+ assert(dx_index_is_compat(path));
- err = dx_lookup(path);
-- if (err)
-- goto errout;
--
-- err = iam_leaf_update(h, path, k, r);
--errout:
-- iam_path_fini(path);
++ err = dx_lookup(path);
+ assert(err != 0 || path->ip_frames[path->ip_indirect].bh != NULL);
return err;
}
/*
* This function increments the frame pointer to search the next leaf
* block, and reads in the necessary intervening nodes if the search
-@@ -1409,16 +374,15 @@
+@@ -1409,16 +359,15 @@ EXPORT_SYMBOL(iam_update);
* If start_hash is non-null, it will be filled in with the starting
* hash of the next page.
*/
p = path->ip_frame;
/*
* Find the next leaf page by incrementing the frame pointer.
-@@ -1438,28 +402,34 @@
+@@ -1438,28 +387,34 @@ static int ext3_htree_next_block(struct
--p;
}
if (err != 0)
return err; /* Failure */
++p;
-@@ -1471,6 +441,16 @@
+@@ -1471,6 +426,16 @@ static int ext3_htree_next_block(struct
return 1;
}
/*
* p is at least 6 bytes before the end of page
-@@ -1662,21 +642,30 @@
+@@ -1662,21 +627,30 @@ static void dx_sort_map (struct dx_map_e
} while(more);
}
#endif
-@@ -1897,14 +886,15 @@
+@@ -1897,14 +871,15 @@ static struct buffer_head * ext3_dx_find
if (*err != 0)
return NULL;
} else {
if (*err != 0)
goto errout;
de = (struct ext3_dir_entry_2 *) bh->b_data;
-@@ -2093,22 +1083,69 @@
+@@ -2093,22 +1068,69 @@ static struct ext3_dir_entry_2* dx_pack_
return prev;
}
int err;
bh2 = ext3_append (handle, dir, &newblock, error);
-@@ -2133,35 +1170,9 @@
+@@ -2133,35 +1155,9 @@ static struct ext3_dir_entry_2 *do_split
if (err)
goto journal_error;
err = ext3_journal_dirty_metadata (handle, bh2);
if (err)
goto journal_error;
-@@ -2175,6 +1186,67 @@
+@@ -2175,6 +1171,67 @@ errout:
}
#endif
/*
* Add a new entry into a directory (leaf) block. If de is non-NULL,
-@@ -2194,34 +1266,16 @@
+@@ -2194,34 +1251,16 @@ static int add_dirent_to_buf(handle_t *h
struct inode *dir = dentry->d_parent->d_inode;
const char *name = dentry->d_name.name;
int namelen = dentry->d_name.len;
}
BUFFER_TRACE(bh, "get_write_access");
err = ext3_journal_get_write_access(handle, bh);
-@@ -2232,22 +1286,9 @@
+@@ -2232,22 +1271,9 @@ static int add_dirent_to_buf(handle_t *h
}
/* By now the buffer is marked for journaling */
/*
* XXX shouldn't update any times until successful
* completion of syscall, but too many callers depend
-@@ -2424,18 +1465,25 @@
+@@ -2423,19 +1449,58 @@ static int ext3_add_entry (handle_t *han
+ return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
++static int shift_entries(struct iam_path *path,
++ struct iam_frame *frame, unsigned count,
++ struct iam_entry *entries, struct iam_entry *entries2,
++ u32 newblock)
++{
++ unsigned count1;
++ unsigned count2;
++ int delta;
++
++ struct iam_frame *parent = frame - 1;
++ struct iam_ikey *pivot = iam_path_ikey(path, 3);
++
++ delta = dx_index_is_compat(path) ? 0 : +1;
++
++ count1 = count/2 + delta;
++ count2 = count - count1;
++ iam_get_ikey(path, iam_entry_shift(path, entries, count1), pivot);
++
++ dxtrace(printk("Split index %i/%i\n", count1, count2));
++
++ memcpy((char *) iam_entry_shift(path, entries2, delta),
++ (char *) iam_entry_shift(path, entries, count1),
++ count2 * iam_entry_size(path));
++
++ dx_set_count(entries, count1);
++ dx_set_count(entries2, count2 + delta);
++ dx_set_limit(entries2, dx_node_limit(path));
++
++ iam_insert_key(path, parent, pivot, newblock);
++ return count1;
++}
++
#ifdef CONFIG_EXT3_INDEX
-static int split_index_node(handle_t *handle, struct iam_path *path)
-{
frame = path->ip_frame;
entries = frame->entries;
-@@ -2474,7 +1522,8 @@
+@@ -2474,7 +1539,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] ||
goto cleanup;
BUFFER_TRACE(frame->bh, "get_write_access");
err = ext3_journal_get_write_access(handle, frame->bh);
-@@ -2493,6 +1542,7 @@
+@@ -2493,6 +1559,7 @@ static int split_index_node(handle_t *ha
unsigned count;
int idx;
struct buffer_head *bh2;
entries = frame->entries;
count = dx_get_count(entries);
-@@ -2501,6 +1551,7 @@
+@@ -2501,6 +1568,7 @@ static int split_index_node(handle_t *ha
bh2 = bh_new[i];
entries2 = dx_get_entries(path, bh2->b_data, 0);
if (frame == path->ip_frames) {
/* splitting root node. Tricky point:
*
-@@ -2512,22 +1563,20 @@
+@@ -2512,22 +1580,20 @@ static int split_index_node(handle_t *ha
* capacity of the root node is smaller than that of
* non-root one.
*/
/* Shift frames in the path */
memmove(frames + 2, frames + 1,
-@@ -2537,20 +1586,21 @@
+@@ -2537,48 +1603,60 @@ static int split_index_node(handle_t *ha
frames[1].entries = entries = entries2;
frames[1].bh = bh2;
assert(dx_node_check(path, frame));
-- ++ frame;
-+ path->ip_frame = ++ frame;
++ ++ path->ip_frame;
+ ++ frame;
assert(dx_node_check(path, frame));
- bh_new[i] = NULL; /* buffer head is "consumed" */
+ bh_new[0] = NULL; /* buffer head is "consumed" */
goto journal_error;
} else {
/* splitting non-root index node. */
- unsigned count1 = count/2, count2 = count - count1;
+- unsigned count1 = count/2, count2 = count - count1;
- unsigned hash2;
-+ struct iam_ikey *pivot = iam_path_ikey(path, 3);
-+ struct iam_frame *parent = frame - 1;
-
+-
- dx_get_key(path,
- iam_entry_shift(path, entries, count1),
- (struct iam_key *)&hash2);
-+ iam_get_ikey(path,
-+ iam_entry_shift(path, entries, count1),
-+ pivot);
-
- dxtrace(printk("Split index %i/%i\n", count1, count2));
+-
+- dxtrace(printk("Split index %i/%i\n", count1, count2));
+-
+- memcpy ((char *) entries2,
+- (char *) iam_entry_shift(path, entries, count1),
+- count2 * iam_entry_size(path));
+- dx_set_count (entries, count1);
+- dx_set_count (entries2, count2);
+- dx_set_limit (entries2, dx_node_limit(path));
++ struct iam_frame *parent = frame - 1;
-@@ -2569,16 +1619,36 @@
++ count = shift_entries(path, frame, count,
++ entries, entries2, newblock[i]);
+ /* Which index block gets the new entry? */
+- if (idx >= count1) {
++ if (idx >= count) {
++ int d = dx_index_is_compat(path) ? 0 : +1;
++
+ frame->at = iam_entry_shift(path, entries2,
+- idx - count1);
++ idx - count + d);
+ frame->entries = entries = entries2;
swap(frame->bh, bh2);
bh_new[i] = bh2;
++ parent->at = iam_entry_shift(path,
++ parent->at, +1);
}
- dx_insert_block(path, frame - 1, hash2, newblock[i]);
-+ iam_insert_key(path, parent, pivot, newblock[i]);
assert(dx_node_check(path, frame));
- assert(dx_node_check(path, frame - 1));
+ assert(dx_node_check(path, parent));
}
goto cleanup;
journal_error:
-@@ -2610,7 +1680,7 @@
+@@ -2610,7 +1688,7 @@ static int ext3_dx_add_entry(handle_t *h
size_t isize;
iam_path_compat_init(&cpath, dir);
err = dx_probe(dentry, NULL, &hinfo, path);
if (err != 0)
-@@ -2620,8 +1690,9 @@
+@@ -2620,8 +1698,9 @@ static int ext3_dx_add_entry(handle_t *h
/* XXX nikita: global serialization! */
isize = dir->i_size;
if (err != 0)
goto cleanup;
-@@ -2641,7 +1712,7 @@
+@@ -2641,7 +1720,7 @@ static int ext3_dx_add_entry(handle_t *h
goto cleanup;
/*copy split inode too*/
if (!de)
goto cleanup;
-@@ -2758,12 +1829,12 @@
+@@ -2758,12 +1837,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
struct inode * inode;
int err, retries = 0;
-Index: linux-stage/include/linux/lustre_iam.h
+Index: iam/include/linux/lustre_iam.h
===================================================================
---- linux-stage.orig/include/linux/lustre_iam.h 2006-09-27 15:49:15.000000000 +0800
-+++ linux-stage/include/linux/lustre_iam.h 2006-09-27 15:49:15.000000000 +0800
+--- iam.orig/include/linux/lustre_iam.h 2006-09-28 22:11:15.000000000 +0400
++++ iam/include/linux/lustre_iam.h 2006-10-03 00:15:55.000000000 +0400
@@ -1,9 +1,68 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
};
/*
-@@ -30,6 +89,11 @@
+@@ -30,6 +89,11 @@ struct iam_key;
/* Incomplete type use to refer to the records stored in iam containers. */
struct iam_rec;
typedef __u64 iam_ptr_t;
/*
-@@ -41,45 +105,25 @@
+@@ -41,45 +105,25 @@ struct iam_frame {
struct iam_entry *at; /* target entry, found by binary search */
};
/*
* Returns pointer (in the same sense as pointer in index entry) to
* the root node.
-@@ -102,8 +146,8 @@
+@@ -102,8 +146,8 @@ struct iam_descr {
/*
* Key comparison function. Returns -1, 0, +1.
*/
/*
* Create new container.
*
-@@ -111,25 +155,113 @@
+@@ -111,25 +155,113 @@ struct iam_descr {
* contains single record with the smallest possible key.
*/
int (*id_create)(struct iam_container *c);
};
struct iam_container {
-@@ -142,10 +274,17 @@
+@@ -142,10 +274,17 @@ struct iam_container {
* container flavor.
*/
struct iam_descr *ic_descr;
};
/*
-@@ -172,36 +311,240 @@
+@@ -172,36 +311,240 @@ struct iam_path {
/*
* Leaf node: a child of ->ip_frame.
*/
*/
int iam_container_init(struct iam_container *c,
struct iam_descr *descr, struct inode *inode);
-@@ -210,3 +553,170 @@
+@@ -210,3 +553,170 @@ int iam_container_init(struct iam_contai
*/
void iam_container_fini(struct iam_container *c);