===================================================================
--- iam.orig/fs/ext3/iam_lvar.c
+++ iam/fs/ext3/iam_lvar.c
-@@ -0,0 +1,905 @@
+@@ -0,0 +1,960 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ if (namelen == 0)
+ return 0;
+ if (strncmp(name, ".", 1) == 0 && namelen == 1)
-+ return 1;
-+ if (strncmp(name, "..", 2) == 0 && namelen == 2)
+ return 2;
++ if (strncmp(name, "..", 2) == 0 && namelen == 2)
++ return 4;
+
+ hinfo.hash_version = EXT3_SB(sb)->s_def_hash_version ;
+ hinfo.seed = 0;
+ n_start(folio) <= lentry_lvar(folio->il_at) &&
+ lentry_lvar(folio->il_at) < n_end(folio);
+}
++
++static int n_invariant(const struct iam_leaf *leaf)
++{
++ struct lvar_leaf_entry *scan;
++ struct lvar_leaf_entry *end;
++ lvar_hash_t hash;
++ lvar_hash_t nexthash;
++
++ end = n_end(leaf);
++ hash = 0;
++
++ if (h_used(n_head(leaf)) > blocksize(leaf))
++ return 0;
++
++ for (scan = n_start(leaf); scan < end; scan = e_next(leaf, scan)) {
++ nexthash = e_hash(scan);
++ if (nexthash != get_hash(iam_leaf_container(leaf),
++ e_char(scan), e_keysize(scan))) {
++ return 0;
++ BREAKPOINT();
++ }
++ if (nexthash < hash) {
++ BREAKPOINT();
++ return 0;
++ }
++ hash = nexthash;
++ }
++ if (scan != end) {
++ BREAKPOINT();
++ return 0;
++ }
++ return 1;
++}
++
+#endif
+
+static struct iam_ikey *lvar_ikey(const struct iam_leaf *l,
+ int found_equal;
+ lvar_hash_t hash;
+
++ assert_inv(n_invariant(leaf));
+ end = n_end(leaf);
+
+ name = kchar(k);
+ result = IAM_LOOKUP_OK;
+ assert_corr(n_at_rec(leaf));
+ }
++ assert_inv(n_invariant(leaf));
+ return result;
+}
+
+ struct lvar_leaf_entry *end;
+ lvar_hash_t hash;
+
++ assert_inv(n_invariant(leaf));
+ end = n_end(leaf);
+ hash = *(const lvar_hash_t *)ik;
+
+ IAM_LOOKUP_EXACT : IAM_LOOKUP_OK;
+ }
+ }
++ assert_inv(n_invariant(leaf));
+ return -E2BIG;
+}
+
+ assert_corr(n_at_rec(l));
+ assert_corr(strlen(kchar(k)) == e_keysize(n_cur(l)));
+ memcpy(e_key(n_cur(l)), k, e_keysize(n_cur(l)));
++ assert_inv(n_invariant(l));
+}
+
+static int lvar_key_cmp(const struct iam_leaf *l, const struct iam_key *k)
+{
+ assert_corr(n_at_rec(l));
+ iam_reccpy(iam_leaf_path(l), e_rec(n_cur(l)), r);
++ assert_inv(n_invariant(l));
+}
+
+static int lvar_can_add(const struct iam_leaf *l,
+ ptrdiff_t diff;
+
+ assert_corr(lvar_can_add(leaf, k, r));
++ assert_inv(n_invariant(leaf));
+
+ key = kchar(k);
+ ksize = strlen(key);
+ shift = getsize(leaf, ksize);
+
+ if (!lvar_at_end(leaf)) {
++ assert_corr(n_cur(leaf) < n_end(leaf));
+ end = n_end(leaf);
+ if (lvar_key_cmp(leaf, k) <= 0)
+ lvar_next(leaf);
+ lvar_key_set(leaf, k);
+ lvar_rec_set(leaf, r);
+ assert_corr(n_at_rec(leaf));
++ assert_inv(n_invariant(leaf));
+}
+
+static void lvar_rec_del(struct iam_leaf *leaf, int shift)
+ int nob;
+
+ assert_corr(n_at_rec(leaf));
++ assert_inv(n_invariant(leaf));
+
+ end = n_end(leaf);
+ next = e_next(leaf, n_cur(leaf));
+ nob = e_size(leaf, n_cur(leaf));
+ memmove(leaf->il_at, next, end - next);
+ h_used_adj(leaf, n_head(leaf), -nob);
++ assert_inv(n_invariant(leaf));
+}
+
+static void lvar_init_new(struct iam_container *c, struct buffer_head *bh)
+ ptrdiff_t tomove;
+ lvar_hash_t hash;
+
++ assert_inv(n_invariant(leaf));
++
+ new_leaf = *bh;
+ path = iam_leaf_path(leaf);
+
+ assert_corr(result == 0);
+ leaf->il_at = ((void *)leaf->il_at) + shift;
+ }
++ assert_corr(n_cur(leaf) < n_end(leaf));
++ assert_inv(n_invariant(leaf));
+}
+
+static struct iam_leaf_operations lvar_leaf_ops = {
+ int blocksize, int keysize, int ptrsize, int recsize)
+{
+ struct lvar_leaf_header *head;
++ struct lvar_leaf_entry *entry;
+
+ /* form leaf */
+ head = buf;
+ .vlh_magic = cpu_to_le16(IAM_LVAR_LEAF_MAGIC),
+ .vlh_used = cpu_to_le16(sizeof *head + lvar_esize(0, recsize))
+ };
++ entry = (void *)(head + 1);
++ *entry = (typeof(*entry)) {
++ .vle_hash = 0,
++ .vle_keysize = 0
++ };
+}
+
+#include <linux/jbd.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
-#else
+#else
#include <liblustre.h>
#include <obd_class.h>
#include <obd.h>
static int mea_last_char_hash(int count, char *name, int namelen)
{
unsigned int c;
-
+
c = name[namelen - 1];
if (c == 0)
CWARN("looks like wrong len is passed\n");
int result;
__u64 hash;
__u32 hash_segment = MAX_HASH_SIZE;
-
+
if (namelen == 0)
return 0;
- if (strncmp(name, ".", 1) == 0 && namelen == 1)
- return 1;
- if (strncmp(name, "..", 2) == 0 && namelen == 2)
+ if (strncmp(name, ".", 1) == 0 && namelen == 1)
return 2;
+ if (strncmp(name, "..", 2) == 0 && namelen == 2)
+ return 4;
hinfo.hash_version = LDISKFS_DX_HASH_TEA;
hinfo.seed = 0;
do_div(hash_segment, count);
do_div(hash, hash_segment);
LASSERT(hash <= count);
-
- return hash;
+
+ return hash;
}
#else
static int mea_hash_segment(int count, char *name, int namelen)
int mea_name2idx(struct lmv_stripe_md *mea, char *name, int namelen)
{
unsigned int c;
-
+
LASSERT(mea && mea->mea_count);
c = raw_name2idx(mea->mea_magic, mea->mea_count, name, namelen);