up_write(&space_info->groups_sem);
 }
 
+static struct btrfs_block_group_cache *
+btrfs_create_block_group_cache(struct btrfs_root *root, u64 start, u64 size)
+{
+       struct btrfs_block_group_cache *cache;
+
+       cache = kzalloc(sizeof(*cache), GFP_NOFS);
+       if (!cache)
+               return NULL;
+
+       cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl),
+                                       GFP_NOFS);
+       if (!cache->free_space_ctl) {
+               kfree(cache);
+               return NULL;
+       }
+
+       cache->key.objectid = start;
+       cache->key.offset = size;
+       cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
+
+       cache->sectorsize = root->sectorsize;
+       cache->fs_info = root->fs_info;
+       cache->full_stripe_len = btrfs_full_stripe_len(root,
+                                              &root->fs_info->mapping_tree,
+                                              start);
+       atomic_set(&cache->count, 1);
+       spin_lock_init(&cache->lock);
+       INIT_LIST_HEAD(&cache->list);
+       INIT_LIST_HEAD(&cache->cluster_list);
+       INIT_LIST_HEAD(&cache->new_bg_list);
+       btrfs_init_free_space_ctl(cache);
+
+       return cache;
+}
+
 int btrfs_read_block_groups(struct btrfs_root *root)
 {
        struct btrfs_path *path;
                        break;
                if (ret != 0)
                        goto error;
+
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
-               cache = kzalloc(sizeof(*cache), GFP_NOFS);
+
+               cache = btrfs_create_block_group_cache(root, found_key.objectid,
+                                                      found_key.offset);
                if (!cache) {
                        ret = -ENOMEM;
                        goto error;
                }
-               cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl),
-                                               GFP_NOFS);
-               if (!cache->free_space_ctl) {
-                       kfree(cache);
-                       ret = -ENOMEM;
-                       goto error;
-               }
-
-               atomic_set(&cache->count, 1);
-               spin_lock_init(&cache->lock);
-               cache->fs_info = info;
-               INIT_LIST_HEAD(&cache->list);
-               INIT_LIST_HEAD(&cache->cluster_list);
 
                if (need_clear) {
                        /*
                read_extent_buffer(leaf, &cache->item,
                                   btrfs_item_ptr_offset(leaf, path->slots[0]),
                                   sizeof(cache->item));
-               memcpy(&cache->key, &found_key, sizeof(found_key));
+               cache->flags = btrfs_block_group_flags(&cache->item);
 
                key.objectid = found_key.objectid + found_key.offset;
                btrfs_release_path(path);
-               cache->flags = btrfs_block_group_flags(&cache->item);
-               cache->sectorsize = root->sectorsize;
-               cache->full_stripe_len = btrfs_full_stripe_len(root,
-                                              &root->fs_info->mapping_tree,
-                                              found_key.objectid);
-               btrfs_init_free_space_ctl(cache);
 
                /*
                 * We need to exclude the super stripes now so that the space
                         * case.
                         */
                        free_excluded_extents(root, cache);
-                       kfree(cache->free_space_ctl);
-                       kfree(cache);
+                       btrfs_put_block_group(cache);
                        goto error;
                }
 
 
        root->fs_info->last_trans_log_full_commit = trans->transid;
 
-       cache = kzalloc(sizeof(*cache), GFP_NOFS);
+       cache = btrfs_create_block_group_cache(root, chunk_offset, size);
        if (!cache)
                return -ENOMEM;
-       cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl),
-                                       GFP_NOFS);
-       if (!cache->free_space_ctl) {
-               kfree(cache);
-               return -ENOMEM;
-       }
-
-       cache->key.objectid = chunk_offset;
-       cache->key.offset = size;
-       cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
-       cache->sectorsize = root->sectorsize;
-       cache->fs_info = root->fs_info;
-       cache->full_stripe_len = btrfs_full_stripe_len(root,
-                                              &root->fs_info->mapping_tree,
-                                              chunk_offset);
-
-       atomic_set(&cache->count, 1);
-       spin_lock_init(&cache->lock);
-       INIT_LIST_HEAD(&cache->list);
-       INIT_LIST_HEAD(&cache->cluster_list);
-       INIT_LIST_HEAD(&cache->new_bg_list);
-
-       btrfs_init_free_space_ctl(cache);
 
        btrfs_set_block_group_used(&cache->item, bytes_used);
        btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid);
-       cache->flags = type;
        btrfs_set_block_group_flags(&cache->item, type);
 
+       cache->flags = type;
        cache->last_byte_to_unpin = (u64)-1;
        cache->cached = BTRFS_CACHE_FINISHED;
        ret = exclude_super_stripes(root, cache);
                 * case.
                 */
                free_excluded_extents(root, cache);
-               kfree(cache->free_space_ctl);
-               kfree(cache);
+               btrfs_put_block_group(cache);
                return ret;
        }