===================================================================
--- iam.orig/fs/ext3/iam.c
+++ iam/fs/ext3/iam.c
-@@ -0,0 +1,1340 @@
+@@ -0,0 +1,1316 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+}
+
+/*
-+ * Leaf helpers.
-+ */
-+
-+struct iam_path *iam_leaf_path(const struct iam_leaf *leaf)
-+{
-+ return leaf->il_path;
-+}
-+
-+struct iam_container *iam_leaf_container(const struct iam_leaf *leaf)
-+{
-+ return iam_leaf_path(leaf)->ip_container;
-+}
-+
-+struct iam_descr *iam_leaf_descr(const struct iam_leaf *leaf)
-+{
-+ return iam_leaf_container(leaf)->ic_descr;
-+}
-+
-+struct iam_leaf_operations *iam_leaf_ops(const struct iam_leaf *leaf)
-+{
-+ return iam_leaf_descr(leaf)->id_leaf_ops;
-+}
-+
-+/*
+ * Return pointer to current leaf record. Pointer is valid while corresponding
+ * leaf node is locked and pinned.
+ */
===================================================================
--- iam.orig/fs/ext3/iam_lvar.c
+++ iam/fs/ext3/iam_lvar.c
-@@ -0,0 +1,970 @@
+@@ -0,0 +1,976 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ return ((void *)ent) + e_size(leaf, ent);
+}
+
++#define LVAR_HASH_TEA (0)
++#define LVAR_HASH_R5 (1)
++#define LVAR_HASH_PREFIX (0)
++
+static inline lvar_hash_t get_hash(const struct iam_container *bag,
+ const char *name, int namelen)
+{
-+#if 1
-+ struct dx_hash_info hinfo;
-+ struct super_block *sb = bag->ic_object->i_sb;
-+ int result;
++ lvar_hash_t result;
+
+ if (namelen == 0)
+ return 0;
+ if (strncmp(name, "..", 2) == 0 && namelen == 2)
+ return 4;
+
-+ hinfo.hash_version = EXT3_SB(sb)->s_def_hash_version ;
-+ hinfo.seed = 0;
-+ result = ext3fs_dirhash(name, namelen, &hinfo);
-+ assert(result == 0);
-+ return (hinfo.hash << 1) & 0x7fffffff;
-+#else
-+ lvar_hash_t result;
++ if (LVAR_HASH_PREFIX) {
++ result = 0;
++ strncpy((void *)&result,
++ name, min(namelen, (int)sizeof result));
++ } else {
++ struct dx_hash_info hinfo;
++
++ if (LVAR_HASH_TEA)
++ hinfo.hash_version = DX_HASH_TEA;
++ else if (LVAR_HASH_R5)
++ hinfo.hash_version = DX_HASH_R5;
++ hinfo.seed = 0;
++ ext3fs_dirhash(name, namelen, &hinfo);
++ result = hinfo.hash;
++ }
+
-+ result = 0;
-+ strncpy((void *)&result, name, min(namelen, (int)sizeof result));
+ return (result << 1) & 0x7fffffff;
-+#endif
+}
+
+static inline int e_eq(const struct lvar_leaf_entry *ent,
int (*can_add)(const struct iam_leaf *l,
const struct iam_key *k, const struct iam_rec *r);
-@@ -221,12 +352,13 @@ struct iam_leaf_operations {
+@@ -221,17 +352,15 @@ struct iam_leaf_operations {
/*
* remove rec for a leaf
*/
+ iam_ptr_t newblknr);
};
- struct iam_path *iam_leaf_path(const struct iam_leaf *leaf);
-@@ -241,6 +373,10 @@ struct iam_descr {
+-struct iam_path *iam_leaf_path(const struct iam_leaf *leaf);
+-struct iam_container *iam_leaf_container(const struct iam_leaf *leaf);
+-
+ /*
+ * Parameters, describing a flavor of iam container.
+ */
+@@ -241,6 +370,10 @@ struct iam_descr {
*/
size_t id_key_size;
/*
* Size of a pointer to the next level (stored in index nodes), in
* bytes.
*/
-@@ -264,6 +400,9 @@ struct iam_descr {
+@@ -264,6 +397,9 @@ struct iam_descr {
struct iam_leaf_operations *id_leaf_ops;
};
struct iam_container {
/*
* Underlying flat file. IO against this object is issued to
-@@ -274,6 +413,10 @@ struct iam_container {
+@@ -274,6 +410,10 @@ struct iam_container {
* container flavor.
*/
struct iam_descr *ic_descr;
};
/*
-@@ -284,7 +427,7 @@ struct iam_path_descr {
+@@ -284,7 +424,7 @@ struct iam_path_descr {
/*
* Scratch-pad area for temporary keys.
*/
};
/*
-@@ -316,6 +459,7 @@ struct iam_path {
+@@ -316,6 +456,7 @@ struct iam_path {
* Key searched for.
*/
const struct iam_key *ip_key_target;
/*
* Description-specific data.
*/
-@@ -334,6 +478,7 @@ struct iam_path_compat {
+@@ -334,6 +475,7 @@ struct iam_path_compat {
struct dx_hash_info *ipc_hinfo;
struct dentry *ipc_dentry;
struct iam_path_descr ipc_descr;
};
/*
-@@ -347,7 +492,9 @@ enum iam_it_state {
+@@ -347,7 +489,9 @@ enum iam_it_state {
/* initial state */
IAM_IT_DETACHED,
/* iterator is above particular record in the container */
};
/*
-@@ -355,7 +502,7 @@ enum iam_it_state {
+@@ -355,7 +499,7 @@ enum iam_it_state {
*/
enum iam_it_flags {
/*
*/
IAM_IT_MOVE = (1 << 0),
/*
-@@ -372,15 +519,26 @@ enum iam_it_flags {
+@@ -372,15 +516,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
*
*/
struct iam_iterator {
-@@ -390,7 +548,8 @@ struct iam_iterator {
+@@ -390,7 +545,8 @@ struct iam_iterator {
__u32 ii_flags;
enum iam_it_state ii_state;
/*
*/
struct iam_path ii_path;
};
-@@ -405,133 +564,26 @@ void iam_path_compat_fini(struct iam_pat
+@@ -405,133 +561,26 @@ void iam_path_compat_fini(struct iam_pat
struct iam_path_descr *iam_ipd_alloc(int keysize);
void iam_ipd_free(struct iam_path_descr *ipd);
int iam_it_load(struct iam_iterator *it, iam_pos_t pos);
int iam_lookup(struct iam_container *c, const struct iam_key *k,
-@@ -539,10 +591,10 @@ int iam_lookup(struct iam_container *c,
+@@ -539,10 +588,10 @@ int iam_lookup(struct iam_container *c,
int iam_delete(handle_t *h, struct iam_container *c, const struct iam_key *k,
struct iam_path_descr *pd);
int iam_update(handle_t *h, struct iam_container *c, const struct iam_key *k,
/*
* Initialize container @c.
*/
-@@ -558,10 +610,6 @@ void iam_container_fini(struct iam_conta
+@@ -558,10 +607,6 @@ void iam_container_fini(struct iam_conta
*/
int iam_container_setup(struct iam_container *c);
static inline struct iam_descr *iam_container_descr(struct iam_container *c)
{
return c->ic_descr;
-@@ -577,16 +625,65 @@ static inline struct inode *iam_path_obj
+@@ -577,16 +622,65 @@ static inline struct inode *iam_path_obj
return p->ip_container->ic_object;
}
}
static inline void iam_reccpy(const struct iam_path *p, struct iam_rec *rec_dst,
-@@ -604,7 +701,7 @@ static inline void *iam_entry_off(struct
+@@ -600,11 +694,38 @@ static inline void *iam_entry_off(struct
+ return (void *)((char *)entry + off);
+ }
+
++/*
++ * Leaf helpers.
++ */
++
++static inline struct iam_path *iam_leaf_path(const struct iam_leaf *leaf)
++{
++ return leaf->il_path;
++}
++
++static inline struct iam_container *
++iam_leaf_container(const struct iam_leaf *leaf)
++{
++ return iam_leaf_path(leaf)->ip_container;
++}
++
++static inline struct iam_descr *iam_leaf_descr(const struct iam_leaf *leaf)
++{
++ return iam_leaf_container(leaf)->ic_descr;
++}
++
++static inline struct iam_leaf_operations *
++iam_leaf_ops(const struct iam_leaf *leaf)
++{
++ return iam_leaf_descr(leaf)->id_leaf_ops;
++}
++
++
+ /*XXX These stuff put here, just because they are used by iam.c and namei.c*/
static inline unsigned dx_get_block(struct iam_path *p, struct iam_entry *entry)
{
return le32_to_cpu(*(u32*)iam_entry_off(entry,
& 0x00ffffff;
}
-@@ -612,21 +709,64 @@ static inline void dx_set_block(struct i
+@@ -612,21 +733,64 @@ static inline void dx_set_block(struct i
struct iam_entry *entry, unsigned value)
{
*(u32*)iam_entry_off(entry,
static inline unsigned dx_get_count(struct iam_entry *entries)
{
return le16_to_cpu(((struct dx_countlimit *) entries)->count);
-@@ -647,9 +787,21 @@ static inline unsigned dx_node_limit(str
+@@ -647,9 +811,21 @@ static inline unsigned dx_node_limit(str
struct iam_descr *param = iam_path_descr(p);
unsigned entry_space = iam_path_obj(p)->i_sb->s_blocksize -
param->id_node_gap;
- return entry_space / (param->id_key_size + param->id_ptr_size);
+ return entry_space / (param->id_ikey_size + param->id_ptr_size);
- }
-
++}
++
+static inline unsigned dx_root_limit(struct iam_path *p)
+{
+ struct iam_descr *param = iam_path_descr(p);
+ if (limit == dx_node_limit(p))
+ limit--;
+ return limit;
-+}
-+
+ }
+
+
static inline struct iam_entry *dx_get_entries(struct iam_path *path,
void *data, int root)
{
-@@ -665,7 +817,8 @@ static inline struct iam_entry *dx_node_
+@@ -665,7 +841,8 @@ static inline struct iam_entry *dx_node_
frame->bh->b_data, frame == path->ip_frames);
}
{
assert(0 <= nr && nr < ARRAY_SIZE(path->ip_data->ipd_key_scratch));
return path->ip_data->ipd_key_scratch[nr];
-@@ -674,6 +827,7 @@ static inline struct iam_key *iam_path_k
+@@ -674,6 +851,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 ext3_htree_next_block(struct inode *dir, __u32 hash,
struct iam_path *path, __u32 *start_hash);
-@@ -681,6 +835,20 @@ int ext3_htree_next_block(struct inode *
+@@ -681,6 +859,20 @@ int ext3_htree_next_block(struct inode *
struct buffer_head *ext3_append(handle_t *handle, struct inode *inode,
u32 *block, int *err);
int split_index_node(handle_t *handle, struct iam_path *path);
/*
* external
-@@ -698,10 +866,12 @@ int iam_node_read(struct iam_container *
+@@ -698,10 +890,12 @@ int iam_node_read(struct iam_container *
handle_t *handle, struct buffer_head **bh);
void iam_insert_key(struct iam_path *path, struct iam_frame *frame,
struct iam_path *iam_leaf_path(const struct iam_leaf *leaf);
struct iam_container *iam_leaf_container(const struct iam_leaf *leaf);
-@@ -709,14 +879,95 @@ struct iam_descr *iam_leaf_descr(const s
+@@ -709,14 +903,95 @@ struct iam_descr *iam_leaf_descr(const s
struct iam_leaf_operations *iam_leaf_ops(const struct iam_leaf *leaf);
#ifdef __KERNEL__
/* This hash calculate method must be same as the lvar hash method */
-static int mea_hash_segment(int count, char *name, int namelen)
+
+#define LVAR_HASH_TEA (0)
+#define LVAR_HASH_R5 (1)
+#define LVAR_HASH_PREFIX (0)
+
+static __u32 hash_build(char *name, int namelen)
{
- struct ldiskfs_dx_hash_info hinfo;
- int result;
- __u64 hash;
- __u64 hash_segment = MAX_HASH_SIZE;
+ __u32 result;
if (namelen == 0)
return 0;
if (strncmp(name, "..", 2) == 0 && namelen == 2)
return 4;
- hinfo.hash_version = LDISKFS_DX_HASH_TEA;
- hinfo.seed = 0;
- result = ldiskfsfs_dirhash(name, namelen, &hinfo);
- LASSERT(result == 0);
- hash = (hinfo.hash << 1) & 0x7fffffff;
+ if (LVAR_HASH_PREFIX) {
+ result = 0;
+ strncpy((void *)&result,
+ name, min(namelen, (int)sizeof result));
+ } else {
+ struct ldiskfs_dx_hash_info hinfo;
+
+ if (LVAR_HASH_TEA)
+ hinfo.hash_version = LDISKFS_DX_HASH_TEA;
+ else
+ hinfo.hash_version = LDISKFS_DX_HASH_R5;
+ hinfo.seed = 0;
+ ldiskfsfs_dirhash(name, namelen, &hinfo);
+ result = hinfo.hash;
+ }
+
+ return (result << 1) & 0x7fffffff;
+}
+
+static int mea_hash_segment(int count, char *name, int namelen)
+{
+ __u64 hash;
+ __u64 hash_segment = MAX_HASH_SIZE;
+
+ hash = hash_build(name, namelen);
do_div(hash_segment, count);
do_div(hash, hash_segment);
LASSERTF(hash <= count, "hash "LPU64" count %d \n", hash, count);