Whamcloud - gitweb
iam: add debugging for bug 11027.
authornikita <nikita>
Sat, 11 Nov 2006 01:02:31 +0000 (01:02 +0000)
committernikita <nikita>
Sat, 11 Nov 2006 01:02:31 +0000 (01:02 +0000)
lustre/kernel_patches/patches/ext3-iam-separate.patch
lustre/kernel_patches/patches/ext3-pdirops-2.6.9.patch

index 3939256..190db71 100644 (file)
@@ -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;
index efe56a5..19e11ee 100644 (file)
@@ -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: