]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - fs/btrfs/ctree.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[linux-imx.git] / fs / btrfs / ctree.c
index 17dffe33e8d0d570dd64eb5717e3f2d69f1db7fc..ed504607d8ecc9e7e492b9c0f2d88ce02ae1d32b 100644 (file)
@@ -1089,7 +1089,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                btrfs_set_node_ptr_generation(parent, parent_slot,
                                              trans->transid);
                btrfs_mark_buffer_dirty(parent);
-               tree_mod_log_free_eb(root->fs_info, buf);
+               if (last_ref)
+                       tree_mod_log_free_eb(root->fs_info, buf);
                btrfs_free_tree_block(trans, root, buf, parent_start,
                                      last_ref);
        }
@@ -1161,8 +1162,8 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info,
  * time_seq).
  */
 static void
-__tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
-                     struct tree_mod_elem *first_tm)
+__tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
+                     u64 time_seq, struct tree_mod_elem *first_tm)
 {
        u32 n;
        struct rb_node *next;
@@ -1172,6 +1173,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
        unsigned long p_size = sizeof(struct btrfs_key_ptr);
 
        n = btrfs_header_nritems(eb);
+       tree_mod_log_read_lock(fs_info);
        while (tm && tm->seq >= time_seq) {
                /*
                 * all the operations are recorded with the operator used for
@@ -1226,6 +1228,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
                if (tm->index != first_tm->index)
                        break;
        }
+       tree_mod_log_read_unlock(fs_info);
        btrfs_set_header_nritems(eb, n);
 }
 
@@ -1268,13 +1271,12 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
                BUG_ON(!eb_rewin);
        }
 
-       extent_buffer_get(eb_rewin);
        btrfs_tree_read_unlock(eb);
        free_extent_buffer(eb);
 
        extent_buffer_get(eb_rewin);
        btrfs_tree_read_lock(eb_rewin);
-       __tree_mod_log_rewind(eb_rewin, time_seq, tm);
+       __tree_mod_log_rewind(fs_info, eb_rewin, time_seq, tm);
        WARN_ON(btrfs_header_nritems(eb_rewin) >
                BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root));
 
@@ -1350,7 +1352,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
                btrfs_set_header_generation(eb, old_generation);
        }
        if (tm)
-               __tree_mod_log_rewind(eb, time_seq, tm);
+               __tree_mod_log_rewind(root->fs_info, eb, time_seq, tm);
        else
                WARN_ON(btrfs_header_level(eb) != 0);
        WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));
@@ -2178,12 +2180,8 @@ static void reada_for_search(struct btrfs_root *root,
        }
 }
 
-/*
- * returns -EAGAIN if it had to drop the path, or zero if everything was in
- * cache
- */
-static noinline int reada_for_balance(struct btrfs_root *root,
-                                     struct btrfs_path *path, int level)
+static noinline void reada_for_balance(struct btrfs_root *root,
+                                      struct btrfs_path *path, int level)
 {
        int slot;
        int nritems;
@@ -2192,12 +2190,11 @@ static noinline int reada_for_balance(struct btrfs_root *root,
        u64 gen;
        u64 block1 = 0;
        u64 block2 = 0;
-       int ret = 0;
        int blocksize;
 
        parent = path->nodes[level + 1];
        if (!parent)
-               return 0;
+               return;
 
        nritems = btrfs_header_nritems(parent);
        slot = path->slots[level + 1];
@@ -2224,28 +2221,11 @@ static noinline int reada_for_balance(struct btrfs_root *root,
                        block2 = 0;
                free_extent_buffer(eb);
        }
-       if (block1 || block2) {
-               ret = -EAGAIN;
-
-               /* release the whole path */
-               btrfs_release_path(path);
 
-               /* read the blocks */
-               if (block1)
-                       readahead_tree_block(root, block1, blocksize, 0);
-               if (block2)
-                       readahead_tree_block(root, block2, blocksize, 0);
-
-               if (block1) {
-                       eb = read_tree_block(root, block1, blocksize, 0);
-                       free_extent_buffer(eb);
-               }
-               if (block2) {
-                       eb = read_tree_block(root, block2, blocksize, 0);
-                       free_extent_buffer(eb);
-               }
-       }
-       return ret;
+       if (block1)
+               readahead_tree_block(root, block1, blocksize, 0);
+       if (block2)
+               readahead_tree_block(root, block2, blocksize, 0);
 }
 
 
@@ -2359,35 +2339,28 @@ read_block_for_search(struct btrfs_trans_handle *trans,
        tmp = btrfs_find_tree_block(root, blocknr, blocksize);
        if (tmp) {
                /* first we do an atomic uptodate check */
-               if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) {
-                       if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
-                               /*
-                                * we found an up to date block without
-                                * sleeping, return
-                                * right away
-                                */
-                               *eb_ret = tmp;
-                               return 0;
-                       }
-                       /* the pages were up to date, but we failed
-                        * the generation number check.  Do a full
-                        * read for the generation number that is correct.
-                        * We must do this without dropping locks so
-                        * we can trust our generation number
-                        */
-                       free_extent_buffer(tmp);
-                       btrfs_set_path_blocking(p);
+               if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
+                       *eb_ret = tmp;
+                       return 0;
+               }
 
-                       /* now we're allowed to do a blocking uptodate check */
-                       tmp = read_tree_block(root, blocknr, blocksize, gen);
-                       if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) {
-                               *eb_ret = tmp;
-                               return 0;
-                       }
-                       free_extent_buffer(tmp);
-                       btrfs_release_path(p);
-                       return -EIO;
+               /* the pages were up to date, but we failed
+                * the generation number check.  Do a full
+                * read for the generation number that is correct.
+                * We must do this without dropping locks so
+                * we can trust our generation number
+                */
+               btrfs_set_path_blocking(p);
+
+               /* now we're allowed to do a blocking uptodate check */
+               ret = btrfs_read_buffer(tmp, gen);
+               if (!ret) {
+                       *eb_ret = tmp;
+                       return 0;
                }
+               free_extent_buffer(tmp);
+               btrfs_release_path(p);
+               return -EIO;
        }
 
        /*
@@ -2448,11 +2421,8 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans,
                        goto again;
                }
 
-               sret = reada_for_balance(root, p, level);
-               if (sret)
-                       goto again;
-
                btrfs_set_path_blocking(p);
+               reada_for_balance(root, p, level);
                sret = split_node(trans, root, p, level);
                btrfs_clear_path_blocking(p, NULL, 0);
 
@@ -2472,11 +2442,8 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans,
                        goto again;
                }
 
-               sret = reada_for_balance(root, p, level);
-               if (sret)
-                       goto again;
-
                btrfs_set_path_blocking(p);
+               reada_for_balance(root, p, level);
                sret = balance_level(trans, root, p, level);
                btrfs_clear_path_blocking(p, NULL, 0);
 
@@ -3143,7 +3110,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
  */
 static noinline int insert_new_root(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
-                          struct btrfs_path *path, int level, int log_removal)
+                          struct btrfs_path *path, int level)
 {
        u64 lower_gen;
        struct extent_buffer *lower;
@@ -3194,7 +3161,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
        btrfs_mark_buffer_dirty(c);
 
        old = root->node;
-       tree_mod_log_set_root_pointer(root, c, log_removal);
+       tree_mod_log_set_root_pointer(root, c, 0);
        rcu_assign_pointer(root->node, c);
 
        /* the super has an extra ref to root->node */
@@ -3278,14 +3245,14 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
                /*
                 * trying to split the root, lets make a new one
                 *
-                * tree mod log: We pass 0 as log_removal parameter to
+                * tree mod log: We don't log_removal old root in
                 * insert_new_root, because that root buffer will be kept as a
                 * normal node. We are going to log removal of half of the
                 * elements below with tree_mod_log_eb_copy. We're holding a
                 * tree lock on the buffer, which is why we cannot race with
                 * other tree_mod_log users.
                 */
-               ret = insert_new_root(trans, root, path, level + 1, 0);
+               ret = insert_new_root(trans, root, path, level + 1);
                if (ret)
                        return ret;
        } else {
@@ -3986,7 +3953,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
                return -EOVERFLOW;
 
        /* first try to make some room by pushing left and right */
-       if (data_size) {
+       if (data_size && path->nodes[1]) {
                wret = push_leaf_right(trans, root, path, data_size,
                                       data_size, 0, 0);
                if (wret < 0)
@@ -4005,7 +3972,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
        }
 
        if (!path->nodes[1]) {
-               ret = insert_new_root(trans, root, path, 1, 1);
+               ret = insert_new_root(trans, root, path, 1);
                if (ret)
                        return ret;
        }