From 2e4284835779b604e8308c754252d276c7f7cc8c Mon Sep 17 00:00:00 2001 From: nikita Date: Sat, 11 Nov 2006 01:02:31 +0000 Subject: [PATCH] iam: add debugging for bug 11027. --- .../kernel_patches/patches/ext3-iam-separate.patch | 10 +- .../patches/ext3-pdirops-2.6.9.patch | 146 ++++++++++++++++----- 2 files changed, 122 insertions(+), 34 deletions(-) diff --git a/lustre/kernel_patches/patches/ext3-iam-separate.patch b/lustre/kernel_patches/patches/ext3-iam-separate.patch index 3939256..190db71 100644 --- a/lustre/kernel_patches/patches/ext3-iam-separate.patch +++ b/lustre/kernel_patches/patches/ext3-iam-separate.patch @@ -15,7 +15,7 @@ Index: iam/fs/ext3/iam.c =================================================================== --- iam.orig/fs/ext3/iam.c +++ iam/fs/ext3/iam.c -@@ -0,0 +1,1402 @@ +@@ -0,0 +1,1410 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * @@ -382,6 +382,14 @@ Index: iam/fs/ext3/iam.c + leaf = &path->ip_leaf; + descr = iam_path_descr(path); + block = dx_get_block(path, path->ip_frame->at); ++ if (block == 0) { ++ /* XXX bug 11027 */ ++ printk(KERN_EMERG "wrong leaf: %p %d [%p %p %p]\n", ++ path->ip_frame->at, ++ dx_get_count(dx_node_get_entries(path, path->ip_frame)), ++ path->ip_frames[0].bh, path->ip_frames[1].bh, ++ path->ip_frames[2].bh); ++ } + err = descr->id_ops->id_node_read(c, block, NULL, &bh); + if (err == 0) { + leaf->il_bh = bh; diff --git a/lustre/kernel_patches/patches/ext3-pdirops-2.6.9.patch b/lustre/kernel_patches/patches/ext3-pdirops-2.6.9.patch index efe56a5..19e11ee 100644 --- a/lustre/kernel_patches/patches/ext3-pdirops-2.6.9.patch +++ b/lustre/kernel_patches/patches/ext3-pdirops-2.6.9.patch @@ -45,7 +45,47 @@ Index: iam/fs/ext3/namei.c static inline void dx_set_limit(struct iam_entry *entries, unsigned value) { ((struct dx_countlimit *) entries)->limit = cpu_to_le16(value); -@@ -241,12 +246,183 @@ struct stats dx_show_entries(struct dx_h +@@ -116,6 +121,39 @@ int dx_index_is_compat(struct iam_path * + } + + ++int dx_bug11027_check(struct iam_path *p, struct iam_frame *f) ++{ ++ struct iam_entry *e; ++ struct iam_container *c; ++ unsigned count; ++ unsigned i; ++ iam_ptr_t blk; ++ iam_ptr_t root; ++ struct inode *inode; ++ ++ c = p->ip_container; ++ e = dx_node_get_entries(p, f); ++ count = dx_get_count(e); ++ e = iam_entry_shift(p, e, 1); ++ root = iam_path_descr(p)->id_ops->id_root_ptr(c); ++ ++ inode = iam_path_obj(p); ++ for (i = 0; i < count - 1; ++i, e = iam_entry_shift(p, e, 1)) { ++ iam_ikeycpy(c, iam_path_ikey(p, 0), iam_path_ikey(p, 1)); ++ iam_get_ikey(p, e, iam_path_ikey(p, 1)); ++ blk = dx_get_block(p, e); ++ /* ++ * By definition of a tree, no node points to the root. ++ */ ++ if (blk == root) { ++ dump_stack(); ++ BREAKPOINT(); ++ return 0; ++ } ++ } ++ return 1; ++} ++ + int dx_node_check(struct iam_path *p, struct iam_frame *f) + { + struct iam_entry *e; +@@ -241,12 +279,183 @@ struct stats dx_show_entries(struct dx_h } #endif /* DX_DEBUG */ @@ -231,7 +271,7 @@ Index: iam/fs/ext3/namei.c struct iam_descr *param; struct iam_frame *frame; -@@ -255,20 +431,19 @@ int dx_lookup(struct iam_path *path) +@@ -255,20 +464,19 @@ int dx_lookup(struct iam_path *path) param = iam_path_descr(path); c = path->ip_container; @@ -262,7 +302,7 @@ Index: iam/fs/ext3/namei.c if (err != 0) break; -@@ -283,53 +458,82 @@ int dx_lookup(struct iam_path *path) +@@ -283,53 +491,83 @@ int dx_lookup(struct iam_path *path) break; assert_inv(dx_node_check(path, frame)); @@ -301,6 +341,7 @@ Index: iam/fs/ext3/namei.c - path->ip_ikey_target)); - } - at = iam_entry_shift(path, at, -1); ++ assert(dx_bug11027_check(path, frame)); + /* + * splitting may change root index block and move hash we're + * looking for into another index block so, we have to check @@ -384,7 +425,7 @@ Index: iam/fs/ext3/namei.c /* * Probe for a directory leaf block to search. * -@@ -339,7 +543,7 @@ int dx_lookup(struct iam_path *path) +@@ -339,7 +577,7 @@ int dx_lookup(struct iam_path *path) * check for this error code, and make sure it never gets reflected * back to userspace. */ @@ -393,7 +434,7 @@ Index: iam/fs/ext3/namei.c struct dx_hash_info *hinfo, struct iam_path *path) { int err; -@@ -347,7 +551,7 @@ static int dx_probe(struct dentry *dentr +@@ -347,7 +585,7 @@ static int dx_probe(struct dentry *dentr assert_corr(path->ip_data != NULL); ipc = container_of(path->ip_data, struct iam_path_compat, ipc_descr); @@ -402,7 +443,7 @@ Index: iam/fs/ext3/namei.c ipc->ipc_hinfo = hinfo; assert_corr(dx_index_is_compat(path)); -@@ -356,6 +560,7 @@ static int dx_probe(struct dentry *dentr +@@ -356,6 +594,7 @@ static int dx_probe(struct dentry *dentr return err; } @@ -410,7 +451,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 -@@ -391,10 +596,13 @@ static int ext3_htree_advance(struct ino +@@ -391,10 +630,13 @@ static int ext3_htree_advance(struct ino * nodes need to be read. */ while (1) { @@ -425,7 +466,7 @@ Index: iam/fs/ext3/namei.c if (p == path->ip_frames) return 0; num_frames++; -@@ -409,7 +617,7 @@ static int ext3_htree_advance(struct ino +@@ -409,7 +651,7 @@ static int ext3_htree_advance(struct ino * If the hash is 1, then continue only if the next page has a * continuation hash of any value. This is used for readdir * handling. Otherwise, check to see if the hash matches the @@ -434,7 +475,7 @@ Index: iam/fs/ext3/namei.c * there's no point to read in the successive index pages. */ iam_get_ikey(path, p->at, (struct iam_ikey *)&bhash); -@@ -425,25 +633,95 @@ static int ext3_htree_advance(struct ino +@@ -425,25 +667,96 @@ static int ext3_htree_advance(struct ino * block so no check is necessary */ while (num_frames--) { @@ -462,6 +503,7 @@ Index: iam/fs/ext3/namei.c + p->curidx = idx; + p->leaf = dx_get_block(path, p->at); assert_inv(dx_node_check(path, p)); ++ assert(dx_bug11027_check(path, p)); } return 1; } @@ -535,22 +577,23 @@ Index: iam/fs/ext3/namei.c } int ext3_htree_next_block(struct inode *dir, __u32 hash, -@@ -659,6 +937,14 @@ void iam_insert_key(struct iam_path *pat +@@ -657,6 +970,15 @@ void iam_insert_key(struct iam_path *pat + dx_set_ikey(path, new, key); + dx_set_block(path, new, ptr); dx_set_count(entries, count + 1); - } - ++ assert(dx_bug11027_check(path, frame)); ++} ++ +void iam_insert_key_lock(struct iam_path *path, struct iam_frame *frame, + const struct iam_ikey *key, iam_ptr_t ptr) +{ + dx_lock_bh(frame->bh); + iam_insert_key(path, frame, key, ptr); + dx_unlock_bh(frame->bh); -+} -+ + } + void dx_insert_block(struct iam_path *path, struct iam_frame *frame, - u32 hash, u32 block) - { -@@ -882,7 +1168,7 @@ static struct buffer_head * ext3_dx_find +@@ -882,7 +1204,7 @@ static struct buffer_head * ext3_dx_find sb = dir->i_sb; /* NFS may look up ".." - look at dx_root directory block */ if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){ @@ -559,7 +602,7 @@ Index: iam/fs/ext3/namei.c if (*err != 0) return NULL; } else { -@@ -1114,7 +1400,7 @@ struct ext3_dir_entry_2 *move_entries(st +@@ -1114,7 +1436,7 @@ struct ext3_dir_entry_2 *move_entries(st hash2 = map[split].hash; continued = hash2 == map[split - 1].hash; dxtrace(printk("Split block %i at %x, %i/%i\n", @@ -568,7 +611,7 @@ Index: iam/fs/ext3/namei.c /* Fancy dance to stay within two buffers */ de2 = dx_move_dirents(data1, data2, map + split, count - split); -@@ -1484,16 +1770,38 @@ static int shift_entries(struct iam_path +@@ -1484,16 +1806,38 @@ static int shift_entries(struct iam_path (char *) iam_entry_shift(path, entries, count1), count2 * iam_entry_size(path)); @@ -610,7 +653,7 @@ Index: iam/fs/ext3/namei.c { struct iam_entry *entries; /* old block contents */ -@@ -1501,6 +1809,8 @@ int split_index_node(handle_t *handle, s +@@ -1501,6 +1845,8 @@ int split_index_node(handle_t *handle, s struct iam_frame *frame, *safe; struct buffer_head *bh_new[DX_MAX_TREE_HEIGHT] = {0}; u32 newblock[DX_MAX_TREE_HEIGHT] = {0}; @@ -619,7 +662,7 @@ Index: iam/fs/ext3/namei.c struct inode *dir = iam_path_obj(path); struct iam_descr *descr; int nr_splet; -@@ -1523,12 +1833,14 @@ int split_index_node(handle_t *handle, s +@@ -1523,12 +1869,14 @@ int split_index_node(handle_t *handle, s * - first allocate all necessary blocks * * - insert pointers into them atomically. @@ -638,7 +681,7 @@ Index: iam/fs/ext3/namei.c dxtrace(printk("using %u of %u node entries\n", dx_get_count(entries), dx_get_limit(entries))); -@@ -1536,6 +1848,7 @@ int split_index_node(handle_t *handle, s +@@ -1536,6 +1884,7 @@ int split_index_node(handle_t *handle, s for (nr_splet = 0; frame >= path->ip_frames && dx_get_count(frame->entries) == dx_get_limit(frame->entries); --frame, ++nr_splet) { @@ -646,7 +689,7 @@ Index: iam/fs/ext3/namei.c if (nr_splet == DX_MAX_TREE_HEIGHT) { ext3_warning(dir->i_sb, __FUNCTION__, "Directory index full!\n"); -@@ -1545,14 +1858,40 @@ int split_index_node(handle_t *handle, s +@@ -1545,14 +1894,53 @@ int split_index_node(handle_t *handle, s } safe = frame; @@ -663,12 +706,25 @@ Index: iam/fs/ext3/namei.c + goto cleanup; + } + } ++ + /* + * Check for concurrent index modification. + */ + err = dx_check_full_path(path); + if (err) + goto cleanup; ++ /* ++ * And check that the same number of nodes is to be split. ++ */ ++ for (i = 0, frame = path->ip_frame; frame >= path->ip_frames && ++ dx_get_count(frame->entries) == dx_get_limit(frame->entries); ++ --frame, ++i) { ++ ; ++ } ++ if (i != nr_splet) { ++ err = -EAGAIN; ++ goto cleanup; ++ } + + /* Go back down, allocating blocks, locking them, and adding into * transaction... */ @@ -688,7 +744,7 @@ Index: iam/fs/ext3/namei.c BUFFER_TRACE(frame->bh, "get_write_access"); err = ext3_journal_get_write_access(handle, frame->bh); if (err) -@@ -1560,6 +1899,7 @@ int split_index_node(handle_t *handle, s +@@ -1560,6 +1948,7 @@ int split_index_node(handle_t *handle, s } /* Add "safe" node to transaction too */ if (safe + 1 != path->ip_frames) { @@ -696,7 +752,7 @@ Index: iam/fs/ext3/namei.c err = ext3_journal_get_write_access(handle, safe->bh); if (err) goto journal_error; -@@ -1596,16 +1936,21 @@ int split_index_node(handle_t *handle, s +@@ -1596,16 +1985,21 @@ int split_index_node(handle_t *handle, s assert_corr(i == 0); @@ -718,7 +774,17 @@ Index: iam/fs/ext3/namei.c /* Shift frames in the path */ memmove(frames + 2, frames + 1, (sizeof path->ip_frames) - 2 * sizeof frames[0]); -@@ -1621,10 +1966,12 @@ int split_index_node(handle_t *handle, s +@@ -1613,18 +2007,22 @@ int split_index_node(handle_t *handle, s + frames[1].at = iam_entry_shift(path, entries2, idx); + frames[1].entries = entries = entries2; + frames[1].bh = bh2; ++ assert(dx_bug11027_check(path, frame)); + assert_inv(dx_node_check(path, frame)); + ++ path->ip_frame; + ++ frame; + assert_inv(dx_node_check(path, frame)); ++ assert(dx_bug11027_check(path, frame)); + bh_new[0] = NULL; /* buffer head is "consumed" */ err = ext3_journal_get_write_access(handle, bh2); if (err) goto journal_error; @@ -731,7 +797,7 @@ Index: iam/fs/ext3/namei.c count = shift_entries(path, frame, count, entries, entries2, newblock[i]); /* Which index block gets the new entry? */ -@@ -1635,6 +1982,9 @@ int split_index_node(handle_t *handle, s +@@ -1635,22 +2033,29 @@ int split_index_node(handle_t *handle, s idx - count + d); frame->entries = entries = entries2; swap(frame->bh, bh2); @@ -741,7 +807,14 @@ Index: iam/fs/ext3/namei.c bh_new[i] = bh2; parent->at = iam_entry_shift(path, parent->at, +1); -@@ -1647,10 +1997,12 @@ int split_index_node(handle_t *handle, s + } + assert_inv(dx_node_check(path, frame)); + assert_inv(dx_node_check(path, parent)); ++ assert(dx_bug11027_check(path, frame)); ++ assert(dx_bug11027_check(path, parent)); + dxtrace(dx_show_index ("node", frame->entries)); + dxtrace(dx_show_index ("node", + ((struct dx_node *) bh2->b_data)->entries)); err = ext3_journal_dirty_metadata(handle, bh2); if (err) goto journal_error; @@ -754,7 +827,7 @@ Index: iam/fs/ext3/namei.c err = ext3_journal_dirty_metadata(handle, bh); if (err) goto journal_error; -@@ -1661,6 +2013,9 @@ int split_index_node(handle_t *handle, s +@@ -1661,6 +2066,9 @@ int split_index_node(handle_t *handle, s assert_corr(dx_get_count(path->ip_frame->entries) < dx_get_limit(path->ip_frame->entries)); } @@ -764,7 +837,7 @@ Index: iam/fs/ext3/namei.c if (nr_splet > 0) { /* * Log ->i_size modification. -@@ -1674,6 +2029,10 @@ journal_error: +@@ -1674,6 +2082,10 @@ journal_error: ext3_std_error(dir->i_sb, err); cleanup: @@ -775,7 +848,7 @@ Index: iam/fs/ext3/namei.c for (i = 0; i < ARRAY_SIZE(bh_new); ++i) { if (bh_new[i] != NULL) brelse(bh_new[i]); -@@ -1695,18 +2054,18 @@ static int ext3_dx_add_entry(handle_t *h +@@ -1695,18 +2107,18 @@ static int ext3_dx_add_entry(handle_t *h struct buffer_head * bh = NULL; struct inode *dir = dentry->d_parent->d_inode; struct ext3_dir_entry_2 *de; @@ -796,7 +869,7 @@ Index: iam/fs/ext3/namei.c isize = dir->i_size; err = param->id_ops->id_node_read(path->ip_container, -@@ -1726,7 +2085,7 @@ static int ext3_dx_add_entry(handle_t *h +@@ -1726,7 +2138,7 @@ static int ext3_dx_add_entry(handle_t *h goto cleanup; } @@ -805,7 +878,14 @@ Index: iam/fs/ext3/namei.c if (err) goto cleanup; -@@ -1742,6 +2101,7 @@ static int ext3_dx_add_entry(handle_t *h +@@ -1736,12 +2148,14 @@ static int ext3_dx_add_entry(handle_t *h + goto cleanup; + + assert_inv(dx_node_check(path, frame)); ++ assert(dx_bug11027_check(path, frame)); + err = add_dirent_to_buf(handle, dentry, inode, de, bh); + goto cleanup2; + journal_error: ext3_std_error(dir->i_sb, err); cleanup: -- 1.8.3.1