]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/btrfs/extent-tree.c
Btrfs: Lower contention on the csum mutex
[mirror_ubuntu-artful-kernel.git] / fs / btrfs / extent-tree.c
index 98a1c0faedae1c7c5e28cca62a7fcaab30a73878..fff219ed61d9a7be5d76cbb8cff7771341fa5c3b 100644 (file)
@@ -893,10 +893,10 @@ out:
        return ret;
 }
 
-int btrfs_cross_ref_exists(struct btrfs_root *root,
+int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans,
+                          struct btrfs_root *root,
                           struct btrfs_key *key, u64 bytenr)
 {
-       struct btrfs_trans_handle *trans;
        struct btrfs_root *old_root;
        struct btrfs_path *path = NULL;
        struct extent_buffer *eb;
@@ -908,6 +908,7 @@ int btrfs_cross_ref_exists(struct btrfs_root *root,
        int level;
        int ret;
 
+       BUG_ON(trans == NULL);
        BUG_ON(key->type != BTRFS_EXTENT_DATA_KEY);
        ret = get_reference_status(root, bytenr, 0, key->objectid,
                                   &min_generation, &ref_count);
@@ -917,7 +918,6 @@ int btrfs_cross_ref_exists(struct btrfs_root *root,
        if (ref_count != 1)
                return 1;
 
-       trans = btrfs_start_transaction(root, 0);
        old_root = root->dirty_root->root;
        ref_generation = old_root->root_key.offset;
 
@@ -973,7 +973,6 @@ int btrfs_cross_ref_exists(struct btrfs_root *root,
 out:
        if (path)
                btrfs_free_path(path);
-       btrfs_end_transaction(trans, root);
        return ret;
 }
 
@@ -1230,7 +1229,6 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
                found->total_bytes += total_bytes;
                found->bytes_used += bytes_used;
                found->full = 0;
-               WARN_ON(found->total_bytes < found->bytes_used);
                *space_info = found;
                return 0;
        }
@@ -2369,6 +2367,11 @@ static int noinline drop_leaf_ref_no_cache(struct btrfs_trans_handle *trans,
                                leaf_owner, leaf_generation,
                                key.objectid, key.offset, 0);
                mutex_unlock(&root->fs_info->alloc_mutex);
+
+               atomic_inc(&root->fs_info->throttle_gen);
+               wake_up(&root->fs_info->transaction_throttle);
+               cond_resched();
+
                BUG_ON(ret);
        }
        return 0;
@@ -2389,6 +2392,11 @@ static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans,
                                        ref->owner, ref->generation,
                                        info->objectid, info->offset, 0);
                mutex_unlock(&root->fs_info->alloc_mutex);
+
+               atomic_inc(&root->fs_info->throttle_gen);
+               wake_up(&root->fs_info->transaction_throttle);
+               cond_resched();
+
                BUG_ON(ret);
                info++;
        }
@@ -2396,51 +2404,6 @@ static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-static void noinline reada_walk_down(struct btrfs_root *root,
-                                    struct extent_buffer *node,
-                                    int slot)
-{
-       u64 bytenr;
-       u64 last = 0;
-       u32 nritems;
-       u32 refs;
-       u32 blocksize;
-       int ret;
-       int i;
-       int level;
-       int skipped = 0;
-
-       nritems = btrfs_header_nritems(node);
-       level = btrfs_header_level(node);
-       if (level)
-               return;
-
-       for (i = slot; i < nritems && skipped < 32; i++) {
-               bytenr = btrfs_node_blockptr(node, i);
-               if (last && ((bytenr > last && bytenr - last > 32 * 1024) ||
-                            (last > bytenr && last - bytenr > 32 * 1024))) {
-                       skipped++;
-                       continue;
-               }
-               blocksize = btrfs_level_size(root, level - 1);
-               if (i != slot) {
-                       ret = lookup_extent_ref(NULL, root, bytenr,
-                                               blocksize, &refs);
-                       BUG_ON(ret);
-                       if (refs != 1) {
-                               skipped++;
-                               continue;
-                       }
-               }
-               ret = readahead_tree_block(root, bytenr, blocksize,
-                                          btrfs_node_ptr_generation(node, i));
-               last = bytenr + blocksize;
-               cond_resched();
-               if (ret)
-                       break;
-       }
-}
-
 int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start, u64 len,
                              u32 *refs)
 {
@@ -2549,6 +2512,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
 
                        atomic_inc(&root->fs_info->throttle_gen);
                        wake_up(&root->fs_info->transaction_throttle);
+                       cond_resched();
 
                        continue;
                }
@@ -2578,8 +2542,6 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
                if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
                        free_extent_buffer(next);
 
-                       if (path->slots[*level] == 0)
-                               reada_walk_down(root, cur, path->slots[*level]);
                        next = read_tree_block(root, bytenr, blocksize,
                                               ptr_gen);
                        cond_resched();
@@ -2601,6 +2563,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
                path->nodes[*level-1] = next;
                *level = btrfs_header_level(next);
                path->slots[*level] = 0;
+               cond_resched();
        }
 out:
        WARN_ON(*level < 0);
@@ -2876,8 +2839,7 @@ again:
                 */
                clear_page_dirty_for_io(page);
 
-               set_extent_delalloc(io_tree, page_start,
-                                   page_end, GFP_NOFS);
+               btrfs_set_extent_delalloc(inode, page_start, page_end);
                set_page_dirty(page);
 
                unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
@@ -3354,6 +3316,13 @@ again:
        key.type = 0;
        cur_byte = key.objectid;
 
+       mutex_unlock(&root->fs_info->alloc_mutex);
+
+       btrfs_start_delalloc_inodes(root);
+       btrfs_wait_ordered_extents(tree_root, 0);
+
+       mutex_lock(&root->fs_info->alloc_mutex);
+
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
        if (ret < 0)
                goto out;
@@ -3436,7 +3405,8 @@ next:
 
                btrfs_clean_old_snapshots(tree_root);
 
-               btrfs_wait_ordered_extents(tree_root);
+               btrfs_start_delalloc_inodes(root);
+               btrfs_wait_ordered_extents(tree_root, 0);
 
                trans = btrfs_start_transaction(tree_root, 1);
                btrfs_commit_transaction(trans, tree_root);
@@ -3472,8 +3442,10 @@ next:
                           key.objectid, key.objectid + key.offset - 1,
                           (unsigned int)-1, GFP_NOFS);
 
+       /*
        memset(shrink_block_group, 0, sizeof(*shrink_block_group));
        kfree(shrink_block_group);
+       */
 
        btrfs_del_item(trans, root, path);
        btrfs_release_path(root, path);