Merge tag 'mfd-next-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
[linux-2.6-microblaze.git] / fs / btrfs / extent-tree.c
index 3d9fe58..de6f75f 100644 (file)
@@ -52,24 +52,21 @@ enum {
 };
 
 static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
-                              struct btrfs_fs_info *fs_info,
-                               struct btrfs_delayed_ref_node *node, u64 parent,
-                               u64 root_objectid, u64 owner_objectid,
-                               u64 owner_offset, int refs_to_drop,
-                               struct btrfs_delayed_extent_op *extra_op);
+                              struct btrfs_delayed_ref_node *node, u64 parent,
+                              u64 root_objectid, u64 owner_objectid,
+                              u64 owner_offset, int refs_to_drop,
+                              struct btrfs_delayed_extent_op *extra_op);
 static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op,
                                    struct extent_buffer *leaf,
                                    struct btrfs_extent_item *ei);
 static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
-                                     struct btrfs_fs_info *fs_info,
                                      u64 parent, u64 root_objectid,
                                      u64 flags, u64 owner, u64 offset,
                                      struct btrfs_key *ins, int ref_mod);
 static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
                                     struct btrfs_delayed_ref_node *node,
                                     struct btrfs_delayed_extent_op *extent_op);
-static int do_chunk_alloc(struct btrfs_trans_handle *trans,
-                         struct btrfs_fs_info *fs_info, u64 flags,
+static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
                          int force);
 static int find_next_key(struct btrfs_path *path, int level,
                         struct btrfs_key *key);
@@ -220,9 +217,9 @@ static int add_excluded_extent(struct btrfs_fs_info *fs_info,
        return 0;
 }
 
-static void free_excluded_extents(struct btrfs_fs_info *fs_info,
-                                 struct btrfs_block_group_cache *cache)
+static void free_excluded_extents(struct btrfs_block_group_cache *cache)
 {
+       struct btrfs_fs_info *fs_info = cache->fs_info;
        u64 start, end;
 
        start = cache->key.objectid;
@@ -234,9 +231,9 @@ static void free_excluded_extents(struct btrfs_fs_info *fs_info,
                          start, end, EXTENT_UPTODATE);
 }
 
-static int exclude_super_stripes(struct btrfs_fs_info *fs_info,
-                                struct btrfs_block_group_cache *cache)
+static int exclude_super_stripes(struct btrfs_block_group_cache *cache)
 {
+       struct btrfs_fs_info *fs_info = cache->fs_info;
        u64 bytenr;
        u64 *logical;
        int stripe_len;
@@ -558,7 +555,7 @@ static noinline void caching_thread(struct btrfs_work *work)
        caching_ctl->progress = (u64)-1;
 
        up_read(&fs_info->commit_root_sem);
-       free_excluded_extents(fs_info, block_group);
+       free_excluded_extents(block_group);
        mutex_unlock(&caching_ctl->mutex);
 
        wake_up(&caching_ctl->wait);
@@ -666,7 +663,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
                wake_up(&caching_ctl->wait);
                if (ret == 1) {
                        put_caching_control(caching_ctl);
-                       free_excluded_extents(fs_info, cache);
+                       free_excluded_extents(cache);
                        return 0;
                }
        } else {
@@ -758,7 +755,8 @@ static void add_pinned_bytes(struct btrfs_fs_info *fs_info, s64 num_bytes,
 
        space_info = __find_space_info(fs_info, flags);
        ASSERT(space_info);
-       percpu_counter_add(&space_info->total_bytes_pinned, num_bytes);
+       percpu_counter_add_batch(&space_info->total_bytes_pinned, num_bytes,
+                   BTRFS_TOTAL_BYTES_PINNED_BATCH);
 }
 
 /*
@@ -870,18 +868,16 @@ search_again:
                        num_refs = btrfs_extent_refs(leaf, ei);
                        extent_flags = btrfs_extent_flags(leaf, ei);
                } else {
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-                       struct btrfs_extent_item_v0 *ei0;
-                       BUG_ON(item_size != sizeof(*ei0));
-                       ei0 = btrfs_item_ptr(leaf, path->slots[0],
-                                            struct btrfs_extent_item_v0);
-                       num_refs = btrfs_extent_refs_v0(leaf, ei0);
-                       /* FIXME: this isn't correct for data */
-                       extent_flags = BTRFS_BLOCK_FLAG_FULL_BACKREF;
-#else
-                       BUG();
-#endif
+                       ret = -EINVAL;
+                       btrfs_print_v0_err(fs_info);
+                       if (trans)
+                               btrfs_abort_transaction(trans, ret);
+                       else
+                               btrfs_handle_fs_error(fs_info, ret, NULL);
+
+                       goto out_free;
                }
+
                BUG_ON(num_refs == 0);
        } else {
                num_refs = 0;
@@ -1039,89 +1035,6 @@ out_free:
  * tree block info structure.
  */
 
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-static int convert_extent_item_v0(struct btrfs_trans_handle *trans,
-                                 struct btrfs_fs_info *fs_info,
-                                 struct btrfs_path *path,
-                                 u64 owner, u32 extra_size)
-{
-       struct btrfs_root *root = fs_info->extent_root;
-       struct btrfs_extent_item *item;
-       struct btrfs_extent_item_v0 *ei0;
-       struct btrfs_extent_ref_v0 *ref0;
-       struct btrfs_tree_block_info *bi;
-       struct extent_buffer *leaf;
-       struct btrfs_key key;
-       struct btrfs_key found_key;
-       u32 new_size = sizeof(*item);
-       u64 refs;
-       int ret;
-
-       leaf = path->nodes[0];
-       BUG_ON(btrfs_item_size_nr(leaf, path->slots[0]) != sizeof(*ei0));
-
-       btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
-       ei0 = btrfs_item_ptr(leaf, path->slots[0],
-                            struct btrfs_extent_item_v0);
-       refs = btrfs_extent_refs_v0(leaf, ei0);
-
-       if (owner == (u64)-1) {
-               while (1) {
-                       if (path->slots[0] >= btrfs_header_nritems(leaf)) {
-                               ret = btrfs_next_leaf(root, path);
-                               if (ret < 0)
-                                       return ret;
-                               BUG_ON(ret > 0); /* Corruption */
-                               leaf = path->nodes[0];
-                       }
-                       btrfs_item_key_to_cpu(leaf, &found_key,
-                                             path->slots[0]);
-                       BUG_ON(key.objectid != found_key.objectid);
-                       if (found_key.type != BTRFS_EXTENT_REF_V0_KEY) {
-                               path->slots[0]++;
-                               continue;
-                       }
-                       ref0 = btrfs_item_ptr(leaf, path->slots[0],
-                                             struct btrfs_extent_ref_v0);
-                       owner = btrfs_ref_objectid_v0(leaf, ref0);
-                       break;
-               }
-       }
-       btrfs_release_path(path);
-
-       if (owner < BTRFS_FIRST_FREE_OBJECTID)
-               new_size += sizeof(*bi);
-
-       new_size -= sizeof(*ei0);
-       ret = btrfs_search_slot(trans, root, &key, path,
-                               new_size + extra_size, 1);
-       if (ret < 0)
-               return ret;
-       BUG_ON(ret); /* Corruption */
-
-       btrfs_extend_item(fs_info, path, new_size);
-
-       leaf = path->nodes[0];
-       item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
-       btrfs_set_extent_refs(leaf, item, refs);
-       /* FIXME: get real generation */
-       btrfs_set_extent_generation(leaf, item, 0);
-       if (owner < BTRFS_FIRST_FREE_OBJECTID) {
-               btrfs_set_extent_flags(leaf, item,
-                                      BTRFS_EXTENT_FLAG_TREE_BLOCK |
-                                      BTRFS_BLOCK_FLAG_FULL_BACKREF);
-               bi = (struct btrfs_tree_block_info *)(item + 1);
-               /* FIXME: get first key of the block */
-               memzero_extent_buffer(leaf, (unsigned long)bi, sizeof(*bi));
-               btrfs_set_tree_block_level(leaf, bi, (int)owner);
-       } else {
-               btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_DATA);
-       }
-       btrfs_mark_buffer_dirty(leaf);
-       return 0;
-}
-#endif
-
 /*
  * is_data == BTRFS_REF_TYPE_BLOCK, tree block type is required,
  * is_data == BTRFS_REF_TYPE_DATA, data type is requried,
@@ -1216,13 +1129,12 @@ static int match_extent_data_ref(struct extent_buffer *leaf,
 }
 
 static noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans,
-                                          struct btrfs_fs_info *fs_info,
                                           struct btrfs_path *path,
                                           u64 bytenr, u64 parent,
                                           u64 root_objectid,
                                           u64 owner, u64 offset)
 {
-       struct btrfs_root *root = fs_info->extent_root;
+       struct btrfs_root *root = trans->fs_info->extent_root;
        struct btrfs_key key;
        struct btrfs_extent_data_ref *ref;
        struct extent_buffer *leaf;
@@ -1251,17 +1163,6 @@ again:
        if (parent) {
                if (!ret)
                        return 0;
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-               key.type = BTRFS_EXTENT_REF_V0_KEY;
-               btrfs_release_path(path);
-               ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-               if (ret < 0) {
-                       err = ret;
-                       goto fail;
-               }
-               if (!ret)
-                       return 0;
-#endif
                goto fail;
        }
 
@@ -1304,13 +1205,12 @@ fail:
 }
 
 static noinline int insert_extent_data_ref(struct btrfs_trans_handle *trans,
-                                          struct btrfs_fs_info *fs_info,
                                           struct btrfs_path *path,
                                           u64 bytenr, u64 parent,
                                           u64 root_objectid, u64 owner,
                                           u64 offset, int refs_to_add)
 {
-       struct btrfs_root *root = fs_info->extent_root;
+       struct btrfs_root *root = trans->fs_info->extent_root;
        struct btrfs_key key;
        struct extent_buffer *leaf;
        u32 size;
@@ -1384,7 +1284,6 @@ fail:
 }
 
 static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
-                                          struct btrfs_fs_info *fs_info,
                                           struct btrfs_path *path,
                                           int refs_to_drop, int *last_ref)
 {
@@ -1406,13 +1305,10 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
                ref2 = btrfs_item_ptr(leaf, path->slots[0],
                                      struct btrfs_shared_data_ref);
                num_refs = btrfs_shared_data_ref_count(leaf, ref2);
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-       } else if (key.type == BTRFS_EXTENT_REF_V0_KEY) {
-               struct btrfs_extent_ref_v0 *ref0;
-               ref0 = btrfs_item_ptr(leaf, path->slots[0],
-                                     struct btrfs_extent_ref_v0);
-               num_refs = btrfs_ref_count_v0(leaf, ref0);
-#endif
+       } else if (unlikely(key.type == BTRFS_EXTENT_REF_V0_KEY)) {
+               btrfs_print_v0_err(trans->fs_info);
+               btrfs_abort_transaction(trans, -EINVAL);
+               return -EINVAL;
        } else {
                BUG();
        }
@@ -1421,21 +1317,13 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
        num_refs -= refs_to_drop;
 
        if (num_refs == 0) {
-               ret = btrfs_del_item(trans, fs_info->extent_root, path);
+               ret = btrfs_del_item(trans, trans->fs_info->extent_root, path);
                *last_ref = 1;
        } else {
                if (key.type == BTRFS_EXTENT_DATA_REF_KEY)
                        btrfs_set_extent_data_ref_count(leaf, ref1, num_refs);
                else if (key.type == BTRFS_SHARED_DATA_REF_KEY)
                        btrfs_set_shared_data_ref_count(leaf, ref2, num_refs);
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-               else {
-                       struct btrfs_extent_ref_v0 *ref0;
-                       ref0 = btrfs_item_ptr(leaf, path->slots[0],
-                                       struct btrfs_extent_ref_v0);
-                       btrfs_set_ref_count_v0(leaf, ref0, num_refs);
-               }
-#endif
                btrfs_mark_buffer_dirty(leaf);
        }
        return ret;
@@ -1453,6 +1341,8 @@ static noinline u32 extent_data_ref_count(struct btrfs_path *path,
 
        leaf = path->nodes[0];
        btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+
+       BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY);
        if (iref) {
                /*
                 * If type is invalid, we should have bailed out earlier than
@@ -1475,13 +1365,6 @@ static noinline u32 extent_data_ref_count(struct btrfs_path *path,
                ref2 = btrfs_item_ptr(leaf, path->slots[0],
                                      struct btrfs_shared_data_ref);
                num_refs = btrfs_shared_data_ref_count(leaf, ref2);
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-       } else if (key.type == BTRFS_EXTENT_REF_V0_KEY) {
-               struct btrfs_extent_ref_v0 *ref0;
-               ref0 = btrfs_item_ptr(leaf, path->slots[0],
-                                     struct btrfs_extent_ref_v0);
-               num_refs = btrfs_ref_count_v0(leaf, ref0);
-#endif
        } else {
                WARN_ON(1);
        }
@@ -1489,12 +1372,11 @@ static noinline u32 extent_data_ref_count(struct btrfs_path *path,
 }
 
 static noinline int lookup_tree_block_ref(struct btrfs_trans_handle *trans,
-                                         struct btrfs_fs_info *fs_info,
                                          struct btrfs_path *path,
                                          u64 bytenr, u64 parent,
                                          u64 root_objectid)
 {
-       struct btrfs_root *root = fs_info->extent_root;
+       struct btrfs_root *root = trans->fs_info->extent_root;
        struct btrfs_key key;
        int ret;
 
@@ -1510,20 +1392,10 @@ static noinline int lookup_tree_block_ref(struct btrfs_trans_handle *trans,
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret > 0)
                ret = -ENOENT;
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-       if (ret == -ENOENT && parent) {
-               btrfs_release_path(path);
-               key.type = BTRFS_EXTENT_REF_V0_KEY;
-               ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-               if (ret > 0)
-                       ret = -ENOENT;
-       }
-#endif
        return ret;
 }
 
 static noinline int insert_tree_block_ref(struct btrfs_trans_handle *trans,
-                                         struct btrfs_fs_info *fs_info,
                                          struct btrfs_path *path,
                                          u64 bytenr, u64 parent,
                                          u64 root_objectid)
@@ -1540,7 +1412,7 @@ static noinline int insert_tree_block_ref(struct btrfs_trans_handle *trans,
                key.offset = root_objectid;
        }
 
-       ret = btrfs_insert_empty_item(trans, fs_info->extent_root,
+       ret = btrfs_insert_empty_item(trans, trans->fs_info->extent_root,
                                      path, &key, 0);
        btrfs_release_path(path);
        return ret;
@@ -1599,13 +1471,13 @@ static int find_next_key(struct btrfs_path *path, int level,
  */
 static noinline_for_stack
 int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
-                                struct btrfs_fs_info *fs_info,
                                 struct btrfs_path *path,
                                 struct btrfs_extent_inline_ref **ref_ret,
                                 u64 bytenr, u64 num_bytes,
                                 u64 parent, u64 root_objectid,
                                 u64 owner, u64 offset, int insert)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_root *root = fs_info->extent_root;
        struct btrfs_key key;
        struct extent_buffer *leaf;
@@ -1635,8 +1507,8 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
                extra_size = -1;
 
        /*
-        * Owner is our parent level, so we can just add one to get the level
-        * for the block we are interested in.
+        * Owner is our level, so we can just add one to get the level for the
+        * block we are interested in.
         */
        if (skinny_metadata && owner < BTRFS_FIRST_FREE_OBJECTID) {
                key.type = BTRFS_METADATA_ITEM_KEY;
@@ -1684,23 +1556,12 @@ again:
 
        leaf = path->nodes[0];
        item_size = btrfs_item_size_nr(leaf, path->slots[0]);
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-       if (item_size < sizeof(*ei)) {
-               if (!insert) {
-                       err = -ENOENT;
-                       goto out;
-               }
-               ret = convert_extent_item_v0(trans, fs_info, path, owner,
-                                            extra_size);
-               if (ret < 0) {
-                       err = ret;
-                       goto out;
-               }
-               leaf = path->nodes[0];
-               item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+       if (unlikely(item_size < sizeof(*ei))) {
+               err = -EINVAL;
+               btrfs_print_v0_err(fs_info);
+               btrfs_abort_transaction(trans, err);
+               goto out;
        }
-#endif
-       BUG_ON(item_size < sizeof(*ei));
 
        ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
        flags = btrfs_extent_flags(leaf, ei);
@@ -1727,7 +1588,7 @@ again:
                iref = (struct btrfs_extent_inline_ref *)ptr;
                type = btrfs_get_extent_inline_ref_type(leaf, iref, needed);
                if (type == BTRFS_REF_TYPE_INVALID) {
-                       err = -EINVAL;
+                       err = -EUCLEAN;
                        goto out;
                }
 
@@ -1863,7 +1724,6 @@ void setup_inline_extent_backref(struct btrfs_fs_info *fs_info,
 }
 
 static int lookup_extent_backref(struct btrfs_trans_handle *trans,
-                                struct btrfs_fs_info *fs_info,
                                 struct btrfs_path *path,
                                 struct btrfs_extent_inline_ref **ref_ret,
                                 u64 bytenr, u64 num_bytes, u64 parent,
@@ -1871,9 +1731,9 @@ static int lookup_extent_backref(struct btrfs_trans_handle *trans,
 {
        int ret;
 
-       ret = lookup_inline_extent_backref(trans, fs_info, path, ref_ret,
-                                          bytenr, num_bytes, parent,
-                                          root_objectid, owner, offset, 0);
+       ret = lookup_inline_extent_backref(trans, path, ref_ret, bytenr,
+                                          num_bytes, parent, root_objectid,
+                                          owner, offset, 0);
        if (ret != -ENOENT)
                return ret;
 
@@ -1881,12 +1741,11 @@ static int lookup_extent_backref(struct btrfs_trans_handle *trans,
        *ref_ret = NULL;
 
        if (owner < BTRFS_FIRST_FREE_OBJECTID) {
-               ret = lookup_tree_block_ref(trans, fs_info, path, bytenr,
-                                           parent, root_objectid);
+               ret = lookup_tree_block_ref(trans, path, bytenr, parent,
+                                           root_objectid);
        } else {
-               ret = lookup_extent_data_ref(trans, fs_info, path, bytenr,
-                                            parent, root_objectid, owner,
-                                            offset);
+               ret = lookup_extent_data_ref(trans, path, bytenr, parent,
+                                            root_objectid, owner, offset);
        }
        return ret;
 }
@@ -1895,14 +1754,14 @@ static int lookup_extent_backref(struct btrfs_trans_handle *trans,
  * helper to update/remove inline back ref
  */
 static noinline_for_stack
-void update_inline_extent_backref(struct btrfs_fs_info *fs_info,
-                                 struct btrfs_path *path,
+void update_inline_extent_backref(struct btrfs_path *path,
                                  struct btrfs_extent_inline_ref *iref,
                                  int refs_to_mod,
                                  struct btrfs_delayed_extent_op *extent_op,
                                  int *last_ref)
 {
-       struct extent_buffer *leaf;
+       struct extent_buffer *leaf = path->nodes[0];
+       struct btrfs_fs_info *fs_info = leaf->fs_info;
        struct btrfs_extent_item *ei;
        struct btrfs_extent_data_ref *dref = NULL;
        struct btrfs_shared_data_ref *sref = NULL;
@@ -1913,7 +1772,6 @@ void update_inline_extent_backref(struct btrfs_fs_info *fs_info,
        int type;
        u64 refs;
 
-       leaf = path->nodes[0];
        ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
        refs = btrfs_extent_refs(leaf, ei);
        WARN_ON(refs_to_mod < 0 && refs + refs_to_mod <= 0);
@@ -1965,7 +1823,6 @@ void update_inline_extent_backref(struct btrfs_fs_info *fs_info,
 
 static noinline_for_stack
 int insert_inline_extent_backref(struct btrfs_trans_handle *trans,
-                                struct btrfs_fs_info *fs_info,
                                 struct btrfs_path *path,
                                 u64 bytenr, u64 num_bytes, u64 parent,
                                 u64 root_objectid, u64 owner,
@@ -1975,15 +1832,15 @@ int insert_inline_extent_backref(struct btrfs_trans_handle *trans,
        struct btrfs_extent_inline_ref *iref;
        int ret;
 
-       ret = lookup_inline_extent_backref(trans, fs_info, path, &iref,
-                                          bytenr, num_bytes, parent,
-                                          root_objectid, owner, offset, 1);
+       ret = lookup_inline_extent_backref(trans, path, &iref, bytenr,
+                                          num_bytes, parent, root_objectid,
+                                          owner, offset, 1);
        if (ret == 0) {
                BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID);
-               update_inline_extent_backref(fs_info, path, iref,
-                                            refs_to_add, extent_op, NULL);
+               update_inline_extent_backref(path, iref, refs_to_add,
+                                            extent_op, NULL);
        } else if (ret == -ENOENT) {
-               setup_inline_extent_backref(fs_info, path, iref, parent,
+               setup_inline_extent_backref(trans->fs_info, path, iref, parent,
                                            root_objectid, owner, offset,
                                            refs_to_add, extent_op);
                ret = 0;
@@ -1992,7 +1849,6 @@ int insert_inline_extent_backref(struct btrfs_trans_handle *trans,
 }
 
 static int insert_extent_backref(struct btrfs_trans_handle *trans,
-                                struct btrfs_fs_info *fs_info,
                                 struct btrfs_path *path,
                                 u64 bytenr, u64 parent, u64 root_objectid,
                                 u64 owner, u64 offset, int refs_to_add)
@@ -2000,18 +1856,17 @@ static int insert_extent_backref(struct btrfs_trans_handle *trans,
        int ret;
        if (owner < BTRFS_FIRST_FREE_OBJECTID) {
                BUG_ON(refs_to_add != 1);
-               ret = insert_tree_block_ref(trans, fs_info, path, bytenr,
-                                           parent, root_objectid);
+               ret = insert_tree_block_ref(trans, path, bytenr, parent,
+                                           root_objectid);
        } else {
-               ret = insert_extent_data_ref(trans, fs_info, path, bytenr,
-                                            parent, root_objectid,
-                                            owner, offset, refs_to_add);
+               ret = insert_extent_data_ref(trans, path, bytenr, parent,
+                                            root_objectid, owner, offset,
+                                            refs_to_add);
        }
        return ret;
 }
 
 static int remove_extent_backref(struct btrfs_trans_handle *trans,
-                                struct btrfs_fs_info *fs_info,
                                 struct btrfs_path *path,
                                 struct btrfs_extent_inline_ref *iref,
                                 int refs_to_drop, int is_data, int *last_ref)
@@ -2020,14 +1875,14 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
 
        BUG_ON(!is_data && refs_to_drop != 1);
        if (iref) {
-               update_inline_extent_backref(fs_info, path, iref,
-                                            -refs_to_drop, NULL, last_ref);
+               update_inline_extent_backref(path, iref, -refs_to_drop, NULL,
+                                            last_ref);
        } else if (is_data) {
-               ret = remove_extent_data_ref(trans, fs_info, path, refs_to_drop,
+               ret = remove_extent_data_ref(trans, path, refs_to_drop,
                                             last_ref);
        } else {
                *last_ref = 1;
-               ret = btrfs_del_item(trans, fs_info->extent_root, path);
+               ret = btrfs_del_item(trans, trans->fs_info->extent_root, path);
        }
        return ret;
 }
@@ -2185,13 +2040,13 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
                           owner, offset, BTRFS_ADD_DELAYED_REF);
 
        if (owner < BTRFS_FIRST_FREE_OBJECTID) {
-               ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
+               ret = btrfs_add_delayed_tree_ref(trans, bytenr,
                                                 num_bytes, parent,
                                                 root_objectid, (int)owner,
                                                 BTRFS_ADD_DELAYED_REF, NULL,
                                                 &old_ref_mod, &new_ref_mod);
        } else {
-               ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
+               ret = btrfs_add_delayed_data_ref(trans, bytenr,
                                                 num_bytes, parent,
                                                 root_objectid, owner, offset,
                                                 0, BTRFS_ADD_DELAYED_REF,
@@ -2207,8 +2062,41 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
        return ret;
 }
 
+/*
+ * __btrfs_inc_extent_ref - insert backreference for a given extent
+ *
+ * @trans:         Handle of transaction
+ *
+ * @node:          The delayed ref node used to get the bytenr/length for
+ *                 extent whose references are incremented.
+ *
+ * @parent:        If this is a shared extent (BTRFS_SHARED_DATA_REF_KEY/
+ *                 BTRFS_SHARED_BLOCK_REF_KEY) then it holds the logical
+ *                 bytenr of the parent block. Since new extents are always
+ *                 created with indirect references, this will only be the case
+ *                 when relocating a shared extent. In that case, root_objectid
+ *                 will be BTRFS_TREE_RELOC_OBJECTID. Otheriwse, parent must
+ *                 be 0
+ *
+ * @root_objectid:  The id of the root where this modification has originated,
+ *                 this can be either one of the well-known metadata trees or
+ *                 the subvolume id which references this extent.
+ *
+ * @owner:         For data extents it is the inode number of the owning file.
+ *                 For metadata extents this parameter holds the level in the
+ *                 tree of the extent.
+ *
+ * @offset:        For metadata extents the offset is ignored and is currently
+ *                 always passed as 0. For data extents it is the fileoffset
+ *                 this extent belongs to.
+ *
+ * @refs_to_add     Number of references to add
+ *
+ * @extent_op       Pointer to a structure, holding information necessary when
+ *                  updating a tree block's flags
+ *
+ */
 static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
-                                 struct btrfs_fs_info *fs_info,
                                  struct btrfs_delayed_ref_node *node,
                                  u64 parent, u64 root_objectid,
                                  u64 owner, u64 offset, int refs_to_add,
@@ -2230,10 +2118,9 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
        path->reada = READA_FORWARD;
        path->leave_spinning = 1;
        /* this will setup the path even if it fails to insert the back ref */
-       ret = insert_inline_extent_backref(trans, fs_info, path, bytenr,
-                                          num_bytes, parent, root_objectid,
-                                          owner, offset,
-                                          refs_to_add, extent_op);
+       ret = insert_inline_extent_backref(trans, path, bytenr, num_bytes,
+                                          parent, root_objectid, owner,
+                                          offset, refs_to_add, extent_op);
        if ((ret < 0 && ret != -EAGAIN) || !ret)
                goto out;
 
@@ -2256,8 +2143,8 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
        path->reada = READA_FORWARD;
        path->leave_spinning = 1;
        /* now insert the actual backref */
-       ret = insert_extent_backref(trans, fs_info, path, bytenr, parent,
-                                   root_objectid, owner, offset, refs_to_add);
+       ret = insert_extent_backref(trans, path, bytenr, parent, root_objectid,
+                                   owner, offset, refs_to_add);
        if (ret)
                btrfs_abort_transaction(trans, ret);
 out:
@@ -2266,7 +2153,6 @@ out:
 }
 
 static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
-                               struct btrfs_fs_info *fs_info,
                                struct btrfs_delayed_ref_node *node,
                                struct btrfs_delayed_extent_op *extent_op,
                                int insert_reserved)
@@ -2283,7 +2169,7 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
        ins.type = BTRFS_EXTENT_ITEM_KEY;
 
        ref = btrfs_delayed_node_to_data_ref(node);
-       trace_run_delayed_data_ref(fs_info, node, ref, node->action);
+       trace_run_delayed_data_ref(trans->fs_info, node, ref, node->action);
 
        if (node->type == BTRFS_SHARED_DATA_REF_KEY)
                parent = ref->parent;
@@ -2292,17 +2178,16 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
        if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
                if (extent_op)
                        flags |= extent_op->flags_to_set;
-               ret = alloc_reserved_file_extent(trans, fs_info,
-                                                parent, ref_root, flags,
-                                                ref->objectid, ref->offset,
-                                                &ins, node->ref_mod);
+               ret = alloc_reserved_file_extent(trans, parent, ref_root,
+                                                flags, ref->objectid,
+                                                ref->offset, &ins,
+                                                node->ref_mod);
        } else if (node->action == BTRFS_ADD_DELAYED_REF) {
-               ret = __btrfs_inc_extent_ref(trans, fs_info, node, parent,
-                                            ref_root, ref->objectid,
-                                            ref->offset, node->ref_mod,
-                                            extent_op);
+               ret = __btrfs_inc_extent_ref(trans, node, parent, ref_root,
+                                            ref->objectid, ref->offset,
+                                            node->ref_mod, extent_op);
        } else if (node->action == BTRFS_DROP_DELAYED_REF) {
-               ret = __btrfs_free_extent(trans, fs_info, node, parent,
+               ret = __btrfs_free_extent(trans, node, parent,
                                          ref_root, ref->objectid,
                                          ref->offset, node->ref_mod,
                                          extent_op);
@@ -2331,10 +2216,10 @@ static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op,
 }
 
 static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
-                                struct btrfs_fs_info *fs_info,
                                 struct btrfs_delayed_ref_head *head,
                                 struct btrfs_delayed_extent_op *extent_op)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_key key;
        struct btrfs_path *path;
        struct btrfs_extent_item *ei;
@@ -2400,18 +2285,14 @@ again:
 
        leaf = path->nodes[0];
        item_size = btrfs_item_size_nr(leaf, path->slots[0]);
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-       if (item_size < sizeof(*ei)) {
-               ret = convert_extent_item_v0(trans, fs_info, path, (u64)-1, 0);
-               if (ret < 0) {
-                       err = ret;
-                       goto out;
-               }
-               leaf = path->nodes[0];
-               item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+
+       if (unlikely(item_size < sizeof(*ei))) {
+               err = -EINVAL;
+               btrfs_print_v0_err(fs_info);
+               btrfs_abort_transaction(trans, err);
+               goto out;
        }
-#endif
-       BUG_ON(item_size < sizeof(*ei));
+
        ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
        __run_delayed_extent_op(extent_op, leaf, ei);
 
@@ -2422,7 +2303,6 @@ out:
 }
 
 static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
-                               struct btrfs_fs_info *fs_info,
                                struct btrfs_delayed_ref_node *node,
                                struct btrfs_delayed_extent_op *extent_op,
                                int insert_reserved)
@@ -2433,14 +2313,14 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
        u64 ref_root = 0;
 
        ref = btrfs_delayed_node_to_tree_ref(node);
-       trace_run_delayed_tree_ref(fs_info, node, ref, node->action);
+       trace_run_delayed_tree_ref(trans->fs_info, node, ref, node->action);
 
        if (node->type == BTRFS_SHARED_BLOCK_REF_KEY)
                parent = ref->parent;
        ref_root = ref->root;
 
        if (node->ref_mod != 1) {
-               btrfs_err(fs_info,
+               btrfs_err(trans->fs_info,
        "btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu",
                          node->bytenr, node->ref_mod, node->action, ref_root,
                          parent);
@@ -2450,13 +2330,10 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
                BUG_ON(!extent_op || !extent_op->update_flags);
                ret = alloc_reserved_tree_block(trans, node, extent_op);
        } else if (node->action == BTRFS_ADD_DELAYED_REF) {
-               ret = __btrfs_inc_extent_ref(trans, fs_info, node,
-                                            parent, ref_root,
-                                            ref->level, 0, 1,
-                                            extent_op);
+               ret = __btrfs_inc_extent_ref(trans, node, parent, ref_root,
+                                            ref->level, 0, 1, extent_op);
        } else if (node->action == BTRFS_DROP_DELAYED_REF) {
-               ret = __btrfs_free_extent(trans, fs_info, node,
-                                         parent, ref_root,
+               ret = __btrfs_free_extent(trans, node, parent, ref_root,
                                          ref->level, 0, 1, extent_op);
        } else {
                BUG();
@@ -2466,7 +2343,6 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
 
 /* helper function to actually process a single delayed ref entry */
 static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
-                              struct btrfs_fs_info *fs_info,
                               struct btrfs_delayed_ref_node *node,
                               struct btrfs_delayed_extent_op *extent_op,
                               int insert_reserved)
@@ -2475,18 +2351,18 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
 
        if (trans->aborted) {
                if (insert_reserved)
-                       btrfs_pin_extent(fs_info, node->bytenr,
+                       btrfs_pin_extent(trans->fs_info, node->bytenr,
                                         node->num_bytes, 1);
                return 0;
        }
 
        if (node->type == BTRFS_TREE_BLOCK_REF_KEY ||
            node->type == BTRFS_SHARED_BLOCK_REF_KEY)
-               ret = run_delayed_tree_ref(trans, fs_info, node, extent_op,
+               ret = run_delayed_tree_ref(trans, node, extent_op,
                                           insert_reserved);
        else if (node->type == BTRFS_EXTENT_DATA_REF_KEY ||
                 node->type == BTRFS_SHARED_DATA_REF_KEY)
-               ret = run_delayed_data_ref(trans, fs_info, node, extent_op,
+               ret = run_delayed_data_ref(trans, node, extent_op,
                                           insert_reserved);
        else
                BUG();
@@ -2528,7 +2404,6 @@ static void unselect_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_ref
 }
 
 static int cleanup_extent_op(struct btrfs_trans_handle *trans,
-                            struct btrfs_fs_info *fs_info,
                             struct btrfs_delayed_ref_head *head)
 {
        struct btrfs_delayed_extent_op *extent_op = head->extent_op;
@@ -2542,21 +2417,22 @@ static int cleanup_extent_op(struct btrfs_trans_handle *trans,
                return 0;
        }
        spin_unlock(&head->lock);
-       ret = run_delayed_extent_op(trans, fs_info, head, extent_op);
+       ret = run_delayed_extent_op(trans, head, extent_op);
        btrfs_free_delayed_extent_op(extent_op);
        return ret ? ret : 1;
 }
 
 static int cleanup_ref_head(struct btrfs_trans_handle *trans,
-                           struct btrfs_fs_info *fs_info,
                            struct btrfs_delayed_ref_head *head)
 {
+
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_delayed_ref_root *delayed_refs;
        int ret;
 
        delayed_refs = &trans->transaction->delayed_refs;
 
-       ret = cleanup_extent_op(trans, fs_info, head);
+       ret = cleanup_extent_op(trans, head);
        if (ret < 0) {
                unselect_delayed_ref_head(delayed_refs, head);
                btrfs_debug(fs_info, "run_delayed_extent_op returned %d", ret);
@@ -2598,8 +2474,9 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
                        flags = BTRFS_BLOCK_GROUP_METADATA;
                space_info = __find_space_info(fs_info, flags);
                ASSERT(space_info);
-               percpu_counter_add(&space_info->total_bytes_pinned,
-                                  -head->num_bytes);
+               percpu_counter_add_batch(&space_info->total_bytes_pinned,
+                                  -head->num_bytes,
+                                  BTRFS_TOTAL_BYTES_PINNED_BATCH);
 
                if (head->is_data) {
                        spin_lock(&delayed_refs->lock);
@@ -2705,7 +2582,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                 * up and move on to the next ref_head.
                 */
                if (!ref) {
-                       ret = cleanup_ref_head(trans, fs_info, locked_ref);
+                       ret = cleanup_ref_head(trans, locked_ref);
                        if (ret > 0 ) {
                                /* We dropped our lock, we need to loop. */
                                ret = 0;
@@ -2752,7 +2629,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                locked_ref->extent_op = NULL;
                spin_unlock(&locked_ref->lock);
 
-               ret = run_one_delayed_ref(trans, fs_info, ref, extent_op,
+               ret = run_one_delayed_ref(trans, ref, extent_op,
                                          must_insert_reserved);
 
                btrfs_free_delayed_extent_op(extent_op);
@@ -3227,12 +3104,6 @@ static noinline int check_committed_ref(struct btrfs_root *root,
 
        ret = 1;
        item_size = btrfs_item_size_nr(leaf, path->slots[0]);
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-       if (item_size < sizeof(*ei)) {
-               WARN_ON(item_size != sizeof(struct btrfs_extent_item_v0));
-               goto out;
-       }
-#endif
        ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
 
        if (item_size != sizeof(*ei) +
@@ -4060,11 +3931,7 @@ static void update_space_info(struct btrfs_fs_info *info, u64 flags,
        struct btrfs_space_info *found;
        int factor;
 
-       if (flags & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 |
-                    BTRFS_BLOCK_GROUP_RAID10))
-               factor = 2;
-       else
-               factor = 1;
+       factor = btrfs_bg_type_to_factor(flags);
 
        found = __find_space_info(info, flags);
        ASSERT(found);
@@ -4289,7 +4156,7 @@ again:
                        if (IS_ERR(trans))
                                return PTR_ERR(trans);
 
-                       ret = do_chunk_alloc(trans, fs_info, alloc_target,
+                       ret = do_chunk_alloc(trans, alloc_target,
                                             CHUNK_ALLOC_NO_FORCE);
                        btrfs_end_transaction(trans);
                        if (ret < 0) {
@@ -4309,9 +4176,10 @@ again:
                 * allocation, and no removed chunk in current transaction,
                 * don't bother committing the transaction.
                 */
-               have_pinned_space = percpu_counter_compare(
+               have_pinned_space = __percpu_counter_compare(
                        &data_sinfo->total_bytes_pinned,
-                       used + bytes - data_sinfo->total_bytes);
+                       used + bytes - data_sinfo->total_bytes,
+                       BTRFS_TOTAL_BYTES_PINNED_BATCH);
                spin_unlock(&data_sinfo->lock);
 
                /* commit the current transaction and try again */
@@ -4358,7 +4226,7 @@ commit_trans:
                                      data_sinfo->flags, bytes, 1);
        spin_unlock(&data_sinfo->lock);
 
-       return ret;
+       return 0;
 }
 
 int btrfs_check_data_free_space(struct inode *inode,
@@ -4511,9 +4379,9 @@ static u64 get_profile_num_devs(struct btrfs_fs_info *fs_info, u64 type)
  * for allocating a chunk, otherwise if it's false, reserve space necessary for
  * removing a chunk.
  */
-void check_system_chunk(struct btrfs_trans_handle *trans,
-                       struct btrfs_fs_info *fs_info, u64 type)
+void check_system_chunk(struct btrfs_trans_handle *trans, u64 type)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_space_info *info;
        u64 left;
        u64 thresh;
@@ -4552,7 +4420,7 @@ void check_system_chunk(struct btrfs_trans_handle *trans,
                 * the paths we visit in the chunk tree (they were already COWed
                 * or created in the current transaction for example).
                 */
-               ret = btrfs_alloc_chunk(trans, fs_info, flags);
+               ret = btrfs_alloc_chunk(trans, flags);
        }
 
        if (!ret) {
@@ -4573,11 +4441,13 @@ void check_system_chunk(struct btrfs_trans_handle *trans,
  *    - return 1 if it successfully allocates a chunk,
  *    - return errors including -ENOSPC otherwise.
  */
-static int do_chunk_alloc(struct btrfs_trans_handle *trans,
-                         struct btrfs_fs_info *fs_info, u64 flags, int force)
+static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
+                         int force)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_space_info *space_info;
-       int wait_for_alloc = 0;
+       bool wait_for_alloc = false;
+       bool should_alloc = false;
        int ret = 0;
 
        /* Don't re-enter if we're already allocating a chunk */
@@ -4587,45 +4457,44 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
        space_info = __find_space_info(fs_info, flags);
        ASSERT(space_info);
 
-again:
-       spin_lock(&space_info->lock);
-       if (force < space_info->force_alloc)
-               force = space_info->force_alloc;
-       if (space_info->full) {
-               if (should_alloc_chunk(fs_info, space_info, force))
-                       ret = -ENOSPC;
-               else
-                       ret = 0;
-               spin_unlock(&space_info->lock);
-               return ret;
-       }
-
-       if (!should_alloc_chunk(fs_info, space_info, force)) {
-               spin_unlock(&space_info->lock);
-               return 0;
-       } else if (space_info->chunk_alloc) {
-               wait_for_alloc = 1;
-       } else {
-               space_info->chunk_alloc = 1;
-       }
-
-       spin_unlock(&space_info->lock);
-
-       mutex_lock(&fs_info->chunk_mutex);
+       do {
+               spin_lock(&space_info->lock);
+               if (force < space_info->force_alloc)
+                       force = space_info->force_alloc;
+               should_alloc = should_alloc_chunk(fs_info, space_info, force);
+               if (space_info->full) {
+                       /* No more free physical space */
+                       if (should_alloc)
+                               ret = -ENOSPC;
+                       else
+                               ret = 0;
+                       spin_unlock(&space_info->lock);
+                       return ret;
+               } else if (!should_alloc) {
+                       spin_unlock(&space_info->lock);
+                       return 0;
+               } else if (space_info->chunk_alloc) {
+                       /*
+                        * Someone is already allocating, so we need to block
+                        * until this someone is finished and then loop to
+                        * recheck if we should continue with our allocation
+                        * attempt.
+                        */
+                       wait_for_alloc = true;
+                       spin_unlock(&space_info->lock);
+                       mutex_lock(&fs_info->chunk_mutex);
+                       mutex_unlock(&fs_info->chunk_mutex);
+               } else {
+                       /* Proceed with allocation */
+                       space_info->chunk_alloc = 1;
+                       wait_for_alloc = false;
+                       spin_unlock(&space_info->lock);
+               }
 
-       /*
-        * The chunk_mutex is held throughout the entirety of a chunk
-        * allocation, so once we've acquired the chunk_mutex we know that the
-        * other guy is done and we need to recheck and see if we should
-        * allocate.
-        */
-       if (wait_for_alloc) {
-               mutex_unlock(&fs_info->chunk_mutex);
-               wait_for_alloc = 0;
                cond_resched();
-               goto again;
-       }
+       } while (wait_for_alloc);
 
+       mutex_lock(&fs_info->chunk_mutex);
        trans->allocating_chunk = true;
 
        /*
@@ -4651,9 +4520,9 @@ again:
         * Check if we have enough space in SYSTEM chunk because we may need
         * to update devices.
         */
-       check_system_chunk(trans, fs_info, flags);
+       check_system_chunk(trans, flags);
 
-       ret = btrfs_alloc_chunk(trans, fs_info, flags);
+       ret = btrfs_alloc_chunk(trans, flags);
        trans->allocating_chunk = false;
 
        spin_lock(&space_info->lock);
@@ -4703,6 +4572,7 @@ static int can_overcommit(struct btrfs_fs_info *fs_info,
        u64 space_size;
        u64 avail;
        u64 used;
+       int factor;
 
        /* Don't overcommit when in mixed mode. */
        if (space_info->flags & BTRFS_BLOCK_GROUP_DATA)
@@ -4737,10 +4607,8 @@ static int can_overcommit(struct btrfs_fs_info *fs_info,
         * doesn't include the parity drive, so we don't have to
         * change the math
         */
-       if (profile & (BTRFS_BLOCK_GROUP_DUP |
-                      BTRFS_BLOCK_GROUP_RAID1 |
-                      BTRFS_BLOCK_GROUP_RAID10))
-               avail >>= 1;
+       factor = btrfs_bg_type_to_factor(profile);
+       avail = div_u64(avail, factor);
 
        /*
         * If we aren't flushing all things, let us overcommit up to
@@ -4912,8 +4780,9 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
                return 0;
 
        /* See if there is enough pinned space to make this reservation */
-       if (percpu_counter_compare(&space_info->total_bytes_pinned,
-                                  bytes) >= 0)
+       if (__percpu_counter_compare(&space_info->total_bytes_pinned,
+                                  bytes,
+                                  BTRFS_TOTAL_BYTES_PINNED_BATCH) >= 0)
                goto commit;
 
        /*
@@ -4930,8 +4799,9 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
                bytes -= delayed_rsv->size;
        spin_unlock(&delayed_rsv->lock);
 
-       if (percpu_counter_compare(&space_info->total_bytes_pinned,
-                                  bytes) < 0) {
+       if (__percpu_counter_compare(&space_info->total_bytes_pinned,
+                                  bytes,
+                                  BTRFS_TOTAL_BYTES_PINNED_BATCH) < 0) {
                return -ENOSPC;
        }
 
@@ -4984,7 +4854,7 @@ static void flush_space(struct btrfs_fs_info *fs_info,
                        ret = PTR_ERR(trans);
                        break;
                }
-               ret = do_chunk_alloc(trans, fs_info,
+               ret = do_chunk_alloc(trans,
                                     btrfs_metadata_alloc_profile(fs_info),
                                     CHUNK_ALLOC_NO_FORCE);
                btrfs_end_transaction(trans);
@@ -5659,11 +5529,6 @@ void btrfs_free_block_rsv(struct btrfs_fs_info *fs_info,
        kfree(rsv);
 }
 
-void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv)
-{
-       kfree(rsv);
-}
-
 int btrfs_block_rsv_add(struct btrfs_root *root,
                        struct btrfs_block_rsv *block_rsv, u64 num_bytes,
                        enum btrfs_reserve_flush_enum flush)
@@ -6019,7 +5884,7 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
 
 int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
+       struct btrfs_fs_info *fs_info = inode->root->fs_info;
        unsigned nr_extents;
        enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL;
        int ret = 0;
@@ -6092,7 +5957,7 @@ out_fail:
 void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
                                     bool qgroup_free)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
+       struct btrfs_fs_info *fs_info = inode->root->fs_info;
 
        num_bytes = ALIGN(num_bytes, fs_info->sectorsize);
        spin_lock(&inode->lock);
@@ -6121,7 +5986,7 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
 void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
                                    bool qgroup_free)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
+       struct btrfs_fs_info *fs_info = inode->root->fs_info;
        unsigned num_extents;
 
        spin_lock(&inode->lock);
@@ -6219,12 +6084,8 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                cache = btrfs_lookup_block_group(info, bytenr);
                if (!cache)
                        return -ENOENT;
-               if (cache->flags & (BTRFS_BLOCK_GROUP_DUP |
-                                   BTRFS_BLOCK_GROUP_RAID1 |
-                                   BTRFS_BLOCK_GROUP_RAID10))
-                       factor = 2;
-               else
-                       factor = 1;
+               factor = btrfs_bg_type_to_factor(cache->flags);
+
                /*
                 * If this block group has free space cache written out, we
                 * need to make sure to load it if we are removing space.  This
@@ -6268,8 +6129,9 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                        trace_btrfs_space_reservation(info, "pinned",
                                                      cache->space_info->flags,
                                                      num_bytes, 1);
-                       percpu_counter_add(&cache->space_info->total_bytes_pinned,
-                                          num_bytes);
+                       percpu_counter_add_batch(&cache->space_info->total_bytes_pinned,
+                                          num_bytes,
+                                          BTRFS_TOTAL_BYTES_PINNED_BATCH);
                        set_extent_dirty(info->pinned_extents,
                                         bytenr, bytenr + num_bytes - 1,
                                         GFP_NOFS | __GFP_NOFAIL);
@@ -6279,7 +6141,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                if (list_empty(&cache->dirty_list)) {
                        list_add_tail(&cache->dirty_list,
                                      &trans->transaction->dirty_bgs);
-                               trans->transaction->num_dirty_bgs++;
+                       trans->transaction->num_dirty_bgs++;
                        btrfs_get_block_group(cache);
                }
                spin_unlock(&trans->transaction->dirty_bgs_lock);
@@ -6290,16 +6152,8 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                 * dirty list to avoid races between cleaner kthread and space
                 * cache writeout.
                 */
-               if (!alloc && old_val == 0) {
-                       spin_lock(&info->unused_bgs_lock);
-                       if (list_empty(&cache->bg_list)) {
-                               btrfs_get_block_group(cache);
-                               trace_btrfs_add_unused_block_group(cache);
-                               list_add_tail(&cache->bg_list,
-                                             &info->unused_bgs);
-                       }
-                       spin_unlock(&info->unused_bgs_lock);
-               }
+               if (!alloc && old_val == 0)
+                       btrfs_mark_bg_unused(cache);
 
                btrfs_put_block_group(cache);
                total -= num_bytes;
@@ -6347,7 +6201,8 @@ static int pin_down_extent(struct btrfs_fs_info *fs_info,
 
        trace_btrfs_space_reservation(fs_info, "pinned",
                                      cache->space_info->flags, num_bytes, 1);
-       percpu_counter_add(&cache->space_info->total_bytes_pinned, num_bytes);
+       percpu_counter_add_batch(&cache->space_info->total_bytes_pinned,
+                   num_bytes, BTRFS_TOTAL_BYTES_PINNED_BATCH);
        set_extent_dirty(fs_info->pinned_extents, bytenr,
                         bytenr + num_bytes - 1, GFP_NOFS | __GFP_NOFAIL);
        return 0;
@@ -6711,7 +6566,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
                trace_btrfs_space_reservation(fs_info, "pinned",
                                              space_info->flags, len, 0);
                space_info->max_extent_size = 0;
-               percpu_counter_add(&space_info->total_bytes_pinned, -len);
+               percpu_counter_add_batch(&space_info->total_bytes_pinned,
+                           -len, BTRFS_TOTAL_BYTES_PINNED_BATCH);
                if (cache->ro) {
                        space_info->bytes_readonly += len;
                        readonly = true;
@@ -6815,12 +6671,12 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
 }
 
 static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
-                               struct btrfs_fs_info *info,
-                               struct btrfs_delayed_ref_node *node, u64 parent,
-                               u64 root_objectid, u64 owner_objectid,
-                               u64 owner_offset, int refs_to_drop,
-                               struct btrfs_delayed_extent_op *extent_op)
+                              struct btrfs_delayed_ref_node *node, u64 parent,
+                              u64 root_objectid, u64 owner_objectid,
+                              u64 owner_offset, int refs_to_drop,
+                              struct btrfs_delayed_extent_op *extent_op)
 {
+       struct btrfs_fs_info *info = trans->fs_info;
        struct btrfs_key key;
        struct btrfs_path *path;
        struct btrfs_root *extent_root = info->extent_root;
@@ -6852,9 +6708,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
        if (is_data)
                skinny_metadata = false;
 
-       ret = lookup_extent_backref(trans, info, path, &iref,
-                                   bytenr, num_bytes, parent,
-                                   root_objectid, owner_objectid,
+       ret = lookup_extent_backref(trans, path, &iref, bytenr, num_bytes,
+                                   parent, root_objectid, owner_objectid,
                                    owner_offset);
        if (ret == 0) {
                extent_slot = path->slots[0];
@@ -6877,14 +6732,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                                break;
                        extent_slot--;
                }
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-               item_size = btrfs_item_size_nr(path->nodes[0], extent_slot);
-               if (found_extent && item_size < sizeof(*ei))
-                       found_extent = 0;
-#endif
+
                if (!found_extent) {
                        BUG_ON(iref);
-                       ret = remove_extent_backref(trans, info, path, NULL,
+                       ret = remove_extent_backref(trans, path, NULL,
                                                    refs_to_drop,
                                                    is_data, &last_ref);
                        if (ret) {
@@ -6957,42 +6808,12 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 
        leaf = path->nodes[0];
        item_size = btrfs_item_size_nr(leaf, extent_slot);
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-       if (item_size < sizeof(*ei)) {
-               BUG_ON(found_extent || extent_slot != path->slots[0]);
-               ret = convert_extent_item_v0(trans, info, path, owner_objectid,
-                                            0);
-               if (ret < 0) {
-                       btrfs_abort_transaction(trans, ret);
-                       goto out;
-               }
-
-               btrfs_release_path(path);
-               path->leave_spinning = 1;
-
-               key.objectid = bytenr;
-               key.type = BTRFS_EXTENT_ITEM_KEY;
-               key.offset = num_bytes;
-
-               ret = btrfs_search_slot(trans, extent_root, &key, path,
-                                       -1, 1);
-               if (ret) {
-                       btrfs_err(info,
-                                 "umm, got %d back from search, was looking for %llu",
-                               ret, bytenr);
-                       btrfs_print_leaf(path->nodes[0]);
-               }
-               if (ret < 0) {
-                       btrfs_abort_transaction(trans, ret);
-                       goto out;
-               }
-
-               extent_slot = path->slots[0];
-               leaf = path->nodes[0];
-               item_size = btrfs_item_size_nr(leaf, extent_slot);
+       if (unlikely(item_size < sizeof(*ei))) {
+               ret = -EINVAL;
+               btrfs_print_v0_err(info);
+               btrfs_abort_transaction(trans, ret);
+               goto out;
        }
-#endif
-       BUG_ON(item_size < sizeof(*ei));
        ei = btrfs_item_ptr(leaf, extent_slot,
                            struct btrfs_extent_item);
        if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID &&
@@ -7028,9 +6849,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                        btrfs_mark_buffer_dirty(leaf);
                }
                if (found_extent) {
-                       ret = remove_extent_backref(trans, info, path,
-                                                   iref, refs_to_drop,
-                                                   is_data, &last_ref);
+                       ret = remove_extent_backref(trans, path, iref,
+                                                   refs_to_drop, is_data,
+                                                   &last_ref);
                        if (ret) {
                                btrfs_abort_transaction(trans, ret);
                                goto out;
@@ -7172,7 +6993,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
                                   root->root_key.objectid,
                                   btrfs_header_level(buf), 0,
                                   BTRFS_DROP_DELAYED_REF);
-               ret = btrfs_add_delayed_tree_ref(fs_info, trans, buf->start,
+               ret = btrfs_add_delayed_tree_ref(trans, buf->start,
                                                 buf->len, parent,
                                                 root->root_key.objectid,
                                                 btrfs_header_level(buf),
@@ -7251,13 +7072,13 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
                old_ref_mod = new_ref_mod = 0;
                ret = 0;
        } else if (owner < BTRFS_FIRST_FREE_OBJECTID) {
-               ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
+               ret = btrfs_add_delayed_tree_ref(trans, bytenr,
                                                 num_bytes, parent,
                                                 root_objectid, (int)owner,
                                                 BTRFS_DROP_DELAYED_REF, NULL,
                                                 &old_ref_mod, &new_ref_mod);
        } else {
-               ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
+               ret = btrfs_add_delayed_data_ref(trans, bytenr,
                                                 num_bytes, parent,
                                                 root_objectid, owner, offset,
                                                 0, BTRFS_DROP_DELAYED_REF,
@@ -7534,7 +7355,7 @@ search:
                 * for the proper type.
                 */
                if (!block_group_bits(block_group, flags)) {
-                   u64 extra = BTRFS_BLOCK_GROUP_DUP |
+                       u64 extra = BTRFS_BLOCK_GROUP_DUP |
                                BTRFS_BLOCK_GROUP_RAID1 |
                                BTRFS_BLOCK_GROUP_RAID5 |
                                BTRFS_BLOCK_GROUP_RAID6 |
@@ -7738,7 +7559,7 @@ unclustered_alloc:
                        goto loop;
                }
 checks:
-               search_start = ALIGN(offset, fs_info->stripesize);
+               search_start = round_up(offset, fs_info->stripesize);
 
                /* move on to the next group */
                if (search_start + num_bytes >
@@ -7750,7 +7571,6 @@ checks:
                if (offset < search_start)
                        btrfs_add_free_space(block_group, offset,
                                             search_start - offset);
-               BUG_ON(offset > search_start);
 
                ret = btrfs_add_reserved_bytes(block_group, ram_bytes,
                                num_bytes, delalloc);
@@ -7826,8 +7646,7 @@ loop:
                                goto out;
                        }
 
-                       ret = do_chunk_alloc(trans, fs_info, flags,
-                                            CHUNK_ALLOC_FORCE);
+                       ret = do_chunk_alloc(trans, flags, CHUNK_ALLOC_FORCE);
 
                        /*
                         * If we can't allocate a new chunk we've already looped
@@ -8053,11 +7872,11 @@ int btrfs_free_and_pin_reserved_extent(struct btrfs_fs_info *fs_info,
 }
 
 static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
-                                     struct btrfs_fs_info *fs_info,
                                      u64 parent, u64 root_objectid,
                                      u64 flags, u64 owner, u64 offset,
                                      struct btrfs_key *ins, int ref_mod)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        int ret;
        struct btrfs_extent_item *extent_item;
        struct btrfs_extent_inline_ref *iref;
@@ -8231,7 +8050,6 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
                                     u64 offset, u64 ram_bytes,
                                     struct btrfs_key *ins)
 {
-       struct btrfs_fs_info *fs_info = root->fs_info;
        int ret;
 
        BUG_ON(root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
@@ -8240,7 +8058,7 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
                           root->root_key.objectid, owner, offset,
                           BTRFS_ADD_DELAYED_EXTENT);
 
-       ret = btrfs_add_delayed_data_ref(fs_info, trans, ins->objectid,
+       ret = btrfs_add_delayed_data_ref(trans, ins->objectid,
                                         ins->offset, 0,
                                         root->root_key.objectid, owner,
                                         offset, ram_bytes,
@@ -8254,10 +8072,10 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
  * space cache bits as well
  */
 int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
-                                  struct btrfs_fs_info *fs_info,
                                   u64 root_objectid, u64 owner, u64 offset,
                                   struct btrfs_key *ins)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        int ret;
        struct btrfs_block_group_cache *block_group;
        struct btrfs_space_info *space_info;
@@ -8285,15 +8103,15 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
        spin_unlock(&block_group->lock);
        spin_unlock(&space_info->lock);
 
-       ret = alloc_reserved_file_extent(trans, fs_info, 0, root_objectid,
-                                        0, owner, offset, ins, 1);
+       ret = alloc_reserved_file_extent(trans, 0, root_objectid, 0, owner,
+                                        offset, ins, 1);
        btrfs_put_block_group(block_group);
        return ret;
 }
 
 static struct extent_buffer *
 btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-                     u64 bytenr, int level)
+                     u64 bytenr, int level, u64 owner)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct extent_buffer *buf;
@@ -8302,7 +8120,6 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        if (IS_ERR(buf))
                return buf;
 
-       btrfs_set_header_generation(buf, trans->transid);
        btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
        btrfs_tree_lock(buf);
        clean_tree_block(fs_info, buf);
@@ -8311,6 +8128,14 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        btrfs_set_lock_blocking(buf);
        set_extent_buffer_uptodate(buf);
 
+       memzero_extent_buffer(buf, 0, sizeof(struct btrfs_header));
+       btrfs_set_header_level(buf, level);
+       btrfs_set_header_bytenr(buf, buf->start);
+       btrfs_set_header_generation(buf, trans->transid);
+       btrfs_set_header_backref_rev(buf, BTRFS_MIXED_BACKREF_REV);
+       btrfs_set_header_owner(buf, owner);
+       write_extent_buffer_fsid(buf, fs_info->fsid);
+       write_extent_buffer_chunk_tree_uuid(buf, fs_info->chunk_tree_uuid);
        if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
                buf->log_index = root->log_transid % 2;
                /*
@@ -8419,7 +8244,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
        if (btrfs_is_testing(fs_info)) {
                buf = btrfs_init_new_buffer(trans, root, root->alloc_bytenr,
-                                           level);
+                                           level, root_objectid);
                if (!IS_ERR(buf))
                        root->alloc_bytenr += blocksize;
                return buf;
@@ -8435,7 +8260,8 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
        if (ret)
                goto out_unuse;
 
-       buf = btrfs_init_new_buffer(trans, root, ins.objectid, level);
+       buf = btrfs_init_new_buffer(trans, root, ins.objectid, level,
+                                   root_objectid);
        if (IS_ERR(buf)) {
                ret = PTR_ERR(buf);
                goto out_free_reserved;
@@ -8467,7 +8293,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
                btrfs_ref_tree_mod(root, ins.objectid, ins.offset, parent,
                                   root_objectid, level, 0,
                                   BTRFS_ADD_DELAYED_EXTENT);
-               ret = btrfs_add_delayed_tree_ref(fs_info, trans, ins.objectid,
+               ret = btrfs_add_delayed_tree_ref(trans, ins.objectid,
                                                 ins.offset, parent,
                                                 root_objectid, level,
                                                 BTRFS_ADD_DELAYED_EXTENT,
@@ -8499,7 +8325,6 @@ struct walk_control {
        int keep_locks;
        int reada_slot;
        int reada_count;
-       int for_reloc;
 };
 
 #define DROP_REFERENCE 1
@@ -8819,7 +8644,7 @@ skip:
                }
 
                if (need_account) {
-                       ret = btrfs_qgroup_trace_subtree(trans, root, next,
+                       ret = btrfs_qgroup_trace_subtree(trans, next,
                                                         generation, level - 1);
                        if (ret) {
                                btrfs_err_rl(fs_info,
@@ -8919,7 +8744,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
                        else
                                ret = btrfs_dec_ref(trans, root, eb, 0);
                        BUG_ON(ret); /* -ENOMEM */
-                       ret = btrfs_qgroup_trace_leaf_items(trans, fs_info, eb);
+                       ret = btrfs_qgroup_trace_leaf_items(trans, eb);
                        if (ret) {
                                btrfs_err_rl(fs_info,
                                             "error %d accounting leaf items. Quota is out of sync, rescan required.",
@@ -9136,7 +8961,6 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        wc->stage = DROP_REFERENCE;
        wc->update_ref = update_ref;
        wc->keep_locks = 0;
-       wc->for_reloc = for_reloc;
        wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(fs_info);
 
        while (1) {
@@ -9199,7 +9023,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        if (err)
                goto out_end_trans;
 
-       ret = btrfs_del_root(trans, fs_info, &root->root_key);
+       ret = btrfs_del_root(trans, &root->root_key);
        if (ret) {
                btrfs_abort_transaction(trans, ret);
                err = ret;
@@ -9302,7 +9126,6 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
        wc->stage = DROP_REFERENCE;
        wc->update_ref = 0;
        wc->keep_locks = 1;
-       wc->for_reloc = 1;
        wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(fs_info);
 
        while (1) {
@@ -9417,10 +9240,10 @@ out:
        return ret;
 }
 
-int btrfs_inc_block_group_ro(struct btrfs_fs_info *fs_info,
-                            struct btrfs_block_group_cache *cache)
+int btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache)
 
 {
+       struct btrfs_fs_info *fs_info = cache->fs_info;
        struct btrfs_trans_handle *trans;
        u64 alloc_flags;
        int ret;
@@ -9454,7 +9277,7 @@ again:
         */
        alloc_flags = update_block_group_flags(fs_info, cache->flags);
        if (alloc_flags != cache->flags) {
-               ret = do_chunk_alloc(trans, fs_info, alloc_flags,
+               ret = do_chunk_alloc(trans, alloc_flags,
                                     CHUNK_ALLOC_FORCE);
                /*
                 * ENOSPC is allowed here, we may have enough space
@@ -9471,8 +9294,7 @@ again:
        if (!ret)
                goto out;
        alloc_flags = get_alloc_profile(fs_info, cache->space_info->flags);
-       ret = do_chunk_alloc(trans, fs_info, alloc_flags,
-                            CHUNK_ALLOC_FORCE);
+       ret = do_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
        if (ret < 0)
                goto out;
        ret = inc_block_group_ro(cache, 0);
@@ -9480,7 +9302,7 @@ out:
        if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) {
                alloc_flags = update_block_group_flags(fs_info, cache->flags);
                mutex_lock(&fs_info->chunk_mutex);
-               check_system_chunk(trans, fs_info, alloc_flags);
+               check_system_chunk(trans, alloc_flags);
                mutex_unlock(&fs_info->chunk_mutex);
        }
        mutex_unlock(&fs_info->ro_block_group_mutex);
@@ -9489,12 +9311,11 @@ out:
        return ret;
 }
 
-int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
-                           struct btrfs_fs_info *fs_info, u64 type)
+int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, u64 type)
 {
-       u64 alloc_flags = get_alloc_profile(fs_info, type);
+       u64 alloc_flags = get_alloc_profile(trans->fs_info, type);
 
-       return do_chunk_alloc(trans, fs_info, alloc_flags, CHUNK_ALLOC_FORCE);
+       return do_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
 }
 
 /*
@@ -9520,13 +9341,7 @@ u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo)
                        continue;
                }
 
-               if (block_group->flags & (BTRFS_BLOCK_GROUP_RAID1 |
-                                         BTRFS_BLOCK_GROUP_RAID10 |
-                                         BTRFS_BLOCK_GROUP_DUP))
-                       factor = 2;
-               else
-                       factor = 1;
-
+               factor = btrfs_bg_type_to_factor(block_group->flags);
                free_bytes += (block_group->key.offset -
                               btrfs_block_group_used(&block_group->item)) *
                               factor;
@@ -9717,6 +9532,8 @@ static int find_first_block_group(struct btrfs_fs_info *fs_info,
        int ret = 0;
        struct btrfs_key found_key;
        struct extent_buffer *leaf;
+       struct btrfs_block_group_item bg;
+       u64 flags;
        int slot;
 
        ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
@@ -9751,8 +9568,32 @@ static int find_first_block_group(struct btrfs_fs_info *fs_info,
                        "logical %llu len %llu found bg but no related chunk",
                                          found_key.objectid, found_key.offset);
                                ret = -ENOENT;
+                       } else if (em->start != found_key.objectid ||
+                                  em->len != found_key.offset) {
+                               btrfs_err(fs_info,
+               "block group %llu len %llu mismatch with chunk %llu len %llu",
+                                         found_key.objectid, found_key.offset,
+                                         em->start, em->len);
+                               ret = -EUCLEAN;
                        } else {
-                               ret = 0;
+                               read_extent_buffer(leaf, &bg,
+                                       btrfs_item_ptr_offset(leaf, slot),
+                                       sizeof(bg));
+                               flags = btrfs_block_group_flags(&bg) &
+                                       BTRFS_BLOCK_GROUP_TYPE_MASK;
+
+                               if (flags != (em->map_lookup->type &
+                                             BTRFS_BLOCK_GROUP_TYPE_MASK)) {
+                                       btrfs_err(fs_info,
+"block group %llu len %llu type flags 0x%llx mismatch with chunk type flags 0x%llx",
+                                               found_key.objectid,
+                                               found_key.offset, flags,
+                                               (BTRFS_BLOCK_GROUP_TYPE_MASK &
+                                                em->map_lookup->type));
+                                       ret = -EUCLEAN;
+                               } else {
+                                       ret = 0;
+                               }
                        }
                        free_extent_map(em);
                        goto out;
@@ -9847,7 +9688,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
                 */
                if (block_group->cached == BTRFS_CACHE_NO ||
                    block_group->cached == BTRFS_CACHE_ERROR)
-                       free_excluded_extents(info, block_group);
+                       free_excluded_extents(block_group);
 
                btrfs_remove_free_space_cache(block_group);
                ASSERT(block_group->cached != BTRFS_CACHE_STARTED);
@@ -10003,6 +9844,62 @@ btrfs_create_block_group_cache(struct btrfs_fs_info *fs_info,
        return cache;
 }
 
+
+/*
+ * Iterate all chunks and verify that each of them has the corresponding block
+ * group
+ */
+static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
+       struct extent_map *em;
+       struct btrfs_block_group_cache *bg;
+       u64 start = 0;
+       int ret = 0;
+
+       while (1) {
+               read_lock(&map_tree->map_tree.lock);
+               /*
+                * lookup_extent_mapping will return the first extent map
+                * intersecting the range, so setting @len to 1 is enough to
+                * get the first chunk.
+                */
+               em = lookup_extent_mapping(&map_tree->map_tree, start, 1);
+               read_unlock(&map_tree->map_tree.lock);
+               if (!em)
+                       break;
+
+               bg = btrfs_lookup_block_group(fs_info, em->start);
+               if (!bg) {
+                       btrfs_err(fs_info,
+       "chunk start=%llu len=%llu doesn't have corresponding block group",
+                                    em->start, em->len);
+                       ret = -EUCLEAN;
+                       free_extent_map(em);
+                       break;
+               }
+               if (bg->key.objectid != em->start ||
+                   bg->key.offset != em->len ||
+                   (bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK) !=
+                   (em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) {
+                       btrfs_err(fs_info,
+"chunk start=%llu len=%llu flags=0x%llx doesn't match block group start=%llu len=%llu flags=0x%llx",
+                               em->start, em->len,
+                               em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK,
+                               bg->key.objectid, bg->key.offset,
+                               bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK);
+                       ret = -EUCLEAN;
+                       free_extent_map(em);
+                       btrfs_put_block_group(bg);
+                       break;
+               }
+               start = em->start + em->len;
+               free_extent_map(em);
+               btrfs_put_block_group(bg);
+       }
+       return ret;
+}
+
 int btrfs_read_block_groups(struct btrfs_fs_info *info)
 {
        struct btrfs_path *path;
@@ -10089,13 +9986,13 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                 * info has super bytes accounted for, otherwise we'll think
                 * we have more space than we actually do.
                 */
-               ret = exclude_super_stripes(info, cache);
+               ret = exclude_super_stripes(cache);
                if (ret) {
                        /*
                         * We may have excluded something, so call this just in
                         * case.
                         */
-                       free_excluded_extents(info, cache);
+                       free_excluded_extents(cache);
                        btrfs_put_block_group(cache);
                        goto error;
                }
@@ -10110,14 +10007,14 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                if (found_key.offset == btrfs_block_group_used(&cache->item)) {
                        cache->last_byte_to_unpin = (u64)-1;
                        cache->cached = BTRFS_CACHE_FINISHED;
-                       free_excluded_extents(info, cache);
+                       free_excluded_extents(cache);
                } else if (btrfs_block_group_used(&cache->item) == 0) {
                        cache->last_byte_to_unpin = (u64)-1;
                        cache->cached = BTRFS_CACHE_FINISHED;
                        add_new_free_space(cache, found_key.objectid,
                                           found_key.objectid +
                                           found_key.offset);
-                       free_excluded_extents(info, cache);
+                       free_excluded_extents(cache);
                }
 
                ret = btrfs_add_block_group_cache(info, cache);
@@ -10140,15 +10037,8 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                if (btrfs_chunk_readonly(info, cache->key.objectid)) {
                        inc_block_group_ro(cache, 1);
                } else if (btrfs_block_group_used(&cache->item) == 0) {
-                       spin_lock(&info->unused_bgs_lock);
-                       /* Should always be true but just in case. */
-                       if (list_empty(&cache->bg_list)) {
-                               btrfs_get_block_group(cache);
-                               trace_btrfs_add_unused_block_group(cache);
-                               list_add_tail(&cache->bg_list,
-                                             &info->unused_bgs);
-                       }
-                       spin_unlock(&info->unused_bgs_lock);
+                       ASSERT(list_empty(&cache->bg_list));
+                       btrfs_mark_bg_unused(cache);
                }
        }
 
@@ -10176,7 +10066,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
 
        btrfs_add_raid_kobjects(info);
        init_global_block_rsv(info);
-       ret = 0;
+       ret = check_chunk_block_group_mappings(info);
 error:
        btrfs_free_path(path);
        return ret;
@@ -10206,8 +10096,7 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans)
                                        sizeof(item));
                if (ret)
                        btrfs_abort_transaction(trans, ret);
-               ret = btrfs_finish_chunk_alloc(trans, fs_info, key.objectid,
-                                              key.offset);
+               ret = btrfs_finish_chunk_alloc(trans, key.objectid, key.offset);
                if (ret)
                        btrfs_abort_transaction(trans, ret);
                add_block_group_free_space(trans, block_group);
@@ -10218,10 +10107,10 @@ next:
        trans->can_flush_pending_bgs = can_flush_pending_bgs;
 }
 
-int btrfs_make_block_group(struct btrfs_trans_handle *trans,
-                          struct btrfs_fs_info *fs_info, u64 bytes_used,
+int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used,
                           u64 type, u64 chunk_offset, u64 size)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_block_group_cache *cache;
        int ret;
 
@@ -10240,20 +10129,20 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
        cache->last_byte_to_unpin = (u64)-1;
        cache->cached = BTRFS_CACHE_FINISHED;
        cache->needs_free_space = 1;
-       ret = exclude_super_stripes(fs_info, cache);
+       ret = exclude_super_stripes(cache);
        if (ret) {
                /*
                 * We may have excluded something, so call this just in
                 * case.
                 */
-               free_excluded_extents(fs_info, cache);
+               free_excluded_extents(cache);
                btrfs_put_block_group(cache);
                return ret;
        }
 
        add_new_free_space(cache, chunk_offset, chunk_offset + size);
 
-       free_excluded_extents(fs_info, cache);
+       free_excluded_extents(cache);
 
 #ifdef CONFIG_BTRFS_DEBUG
        if (btrfs_should_fragment_free_space(cache)) {
@@ -10311,9 +10200,9 @@ static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
 }
 
 int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
-                            struct btrfs_fs_info *fs_info, u64 group_start,
-                            struct extent_map *em)
+                            u64 group_start, struct extent_map *em)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_root *root = fs_info->extent_root;
        struct btrfs_path *path;
        struct btrfs_block_group_cache *block_group;
@@ -10337,18 +10226,13 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
         * Free the reserved super bytes from this block group before
         * remove it.
         */
-       free_excluded_extents(fs_info, block_group);
+       free_excluded_extents(block_group);
        btrfs_free_ref_tree_range(fs_info, block_group->key.objectid,
                                  block_group->key.offset);
 
        memcpy(&key, &block_group->key, sizeof(key));
        index = btrfs_bg_flags_to_raid_index(block_group->flags);
-       if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP |
-                                 BTRFS_BLOCK_GROUP_RAID1 |
-                                 BTRFS_BLOCK_GROUP_RAID10))
-               factor = 2;
-       else
-               factor = 1;
+       factor = btrfs_bg_type_to_factor(block_group->flags);
 
        /* make sure this block group isn't part of an allocation cluster */
        cluster = &fs_info->data_alloc_cluster;
@@ -10687,7 +10571,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
                /* Don't want to race with allocators so take the groups_sem */
                down_write(&space_info->groups_sem);
                spin_lock(&block_group->lock);
-               if (block_group->reserved ||
+               if (block_group->reserved || block_group->pinned ||
                    btrfs_block_group_used(&block_group->item) ||
                    block_group->ro ||
                    list_is_singular(&block_group->list)) {
@@ -10764,8 +10648,9 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
 
                space_info->bytes_pinned -= block_group->pinned;
                space_info->bytes_readonly += block_group->pinned;
-               percpu_counter_add(&space_info->total_bytes_pinned,
-                                  -block_group->pinned);
+               percpu_counter_add_batch(&space_info->total_bytes_pinned,
+                                  -block_group->pinned,
+                                  BTRFS_TOTAL_BYTES_PINNED_BATCH);
                block_group->pinned = 0;
 
                spin_unlock(&block_group->lock);
@@ -10782,8 +10667,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
                 * Btrfs_remove_chunk will abort the transaction if things go
                 * horribly wrong.
                 */
-               ret = btrfs_remove_chunk(trans, fs_info,
-                                        block_group->key.objectid);
+               ret = btrfs_remove_chunk(trans, block_group->key.objectid);
 
                if (ret) {
                        if (trimming)
@@ -11066,3 +10950,16 @@ void btrfs_wait_for_snapshot_creation(struct btrfs_root *root)
                               !atomic_read(&root->will_be_snapshotted));
        }
 }
+
+void btrfs_mark_bg_unused(struct btrfs_block_group_cache *bg)
+{
+       struct btrfs_fs_info *fs_info = bg->fs_info;
+
+       spin_lock(&fs_info->unused_bgs_lock);
+       if (list_empty(&bg->bg_list)) {
+               btrfs_get_block_group(bg);
+               trace_btrfs_add_unused_block_group(bg);
+               list_add_tail(&bg->bg_list, &fs_info->unused_bgs);
+       }
+       spin_unlock(&fs_info->unused_bgs_lock);
+}