ext4: Reorder fs/Makefile so that ext2 root fs's are mounted using ext2
[safe/jmp/linux-2.6] / fs / btrfs / ctree.c
index c8f4c54..42491d7 100644 (file)
@@ -62,14 +62,38 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p)
 
 /*
  * reset all the locked nodes in the patch to spinning locks.
+ *
+ * held is used to keep lockdep happy, when lockdep is enabled
+ * we set held to a blocking lock before we go around and
+ * retake all the spinlocks in the path.  You can safely use NULL
+ * for held
  */
-noinline void btrfs_clear_path_blocking(struct btrfs_path *p)
+noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
+                                       struct extent_buffer *held)
 {
        int i;
-       for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       /* lockdep really cares that we take all of these spinlocks
+        * in the right order.  If any of the locks in the path are not
+        * currently blocking, it is going to complain.  So, make really
+        * really sure by forcing the path to blocking before we clear
+        * the path blocking.
+        */
+       if (held)
+               btrfs_set_lock_blocking(held);
+       btrfs_set_path_blocking(p);
+#endif
+
+       for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
                if (p->nodes[i] && p->locks[i])
                        btrfs_clear_lock_blocking(p->nodes[i]);
        }
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       if (held)
+               btrfs_clear_lock_blocking(held);
+#endif
 }
 
 /* this also releases the path */
@@ -279,7 +303,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                                                  trans->transid, level, &ins);
                BUG_ON(ret);
                cow = btrfs_init_new_buffer(trans, root, prealloc_dest,
-                                           buf->len);
+                                           buf->len, level);
        } else {
                cow = btrfs_alloc_free_block(trans, root, buf->len,
                                             parent_start,
@@ -1559,7 +1583,7 @@ cow_done:
                if (!p->skip_locking)
                        p->locks[level] = 1;
 
-               btrfs_clear_path_blocking(p);
+               btrfs_clear_path_blocking(p, NULL);
 
                /*
                 * we have a lock on b and as long as we aren't changing
@@ -1598,7 +1622,7 @@ cow_done:
 
                                btrfs_set_path_blocking(p);
                                sret = split_node(trans, root, p, level);
-                               btrfs_clear_path_blocking(p);
+                               btrfs_clear_path_blocking(p, NULL);
 
                                BUG_ON(sret > 0);
                                if (sret) {
@@ -1618,7 +1642,7 @@ cow_done:
 
                                btrfs_set_path_blocking(p);
                                sret = balance_level(trans, root, p, level);
-                               btrfs_clear_path_blocking(p);
+                               btrfs_clear_path_blocking(p, NULL);
 
                                if (sret) {
                                        ret = sret;
@@ -1681,13 +1705,13 @@ cow_done:
                        if (!p->skip_locking) {
                                int lret;
 
-                               btrfs_clear_path_blocking(p);
+                               btrfs_clear_path_blocking(p, NULL);
                                lret = btrfs_try_spin_lock(b);
 
                                if (!lret) {
                                        btrfs_set_path_blocking(p);
                                        btrfs_tree_lock(b);
-                                       btrfs_clear_path_blocking(p);
+                                       btrfs_clear_path_blocking(p, b);
                                }
                        }
                } else {
@@ -1699,7 +1723,7 @@ cow_done:
                                btrfs_set_path_blocking(p);
                                sret = split_leaf(trans, root, key,
                                                      p, ins_len, ret == 0);
-                               btrfs_clear_path_blocking(p);
+                               btrfs_clear_path_blocking(p, NULL);
 
                                BUG_ON(sret > 0);
                                if (sret) {
@@ -3919,7 +3943,6 @@ find_next_key:
                                btrfs_release_path(root, path);
                                goto again;
                        } else {
-                               btrfs_clear_path_blocking(path);
                                goto out;
                        }
                }
@@ -3939,7 +3962,7 @@ find_next_key:
                path->locks[level - 1] = 1;
                path->nodes[level - 1] = cur;
                unlock_up(path, level, 1);
-               btrfs_clear_path_blocking(path);
+               btrfs_clear_path_blocking(path, NULL);
        }
 out:
        if (ret == 0)