Btrfs: Fix compile warnings on 32 bit machines
[linux-2.6-block.git] / fs / btrfs / extent-tree.c
index fada9c22a021180a2c6a5dd8fb84f79d419a0f19..b7530c3ac2063593c904ed52030ea9effd1e7d3f 100644 (file)
@@ -768,7 +768,11 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
        l = path->nodes[0];
 
        btrfs_item_key_to_cpu(l, &key, path->slots[0]);
-       BUG_ON(key.objectid != bytenr);
+       if (key.objectid != bytenr) {
+               btrfs_print_leaf(root->fs_info->extent_root, path->nodes[0]);
+               printk("wanted %Lu found %Lu\n", bytenr, key.objectid);
+               BUG();
+       }
        BUG_ON(key.type != BTRFS_EXTENT_ITEM_KEY);
 
        item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
@@ -848,9 +852,8 @@ out:
        return 0;
 }
 
-static int get_reference_status(struct btrfs_root *root, u64 bytenr,
-                               u64 parent_gen, u64 ref_objectid,
-                               u64 *min_generation, u32 *ref_count)
+int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root, u64 bytenr)
 {
        struct btrfs_root *extent_root = root->fs_info->extent_root;
        struct btrfs_path *path;
@@ -858,8 +861,8 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr,
        struct btrfs_extent_ref *ref_item;
        struct btrfs_key key;
        struct btrfs_key found_key;
-       u64 root_objectid = root->root_key.objectid;
-       u64 ref_generation;
+       u64 ref_root;
+       u64 last_snapshot;
        u32 nritems;
        int ret;
 
@@ -872,7 +875,9 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr,
        if (ret < 0)
                goto out;
        BUG_ON(ret == 0);
-       if (ret < 0 || path->slots[0] == 0)
+
+       ret = -ENOENT;
+       if (path->slots[0] == 0)
                goto out;
 
        path->slots[0]--;
@@ -880,14 +885,10 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr,
        btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 
        if (found_key.objectid != bytenr ||
-           found_key.type != BTRFS_EXTENT_ITEM_KEY) {
-               ret = 1;
+           found_key.type != BTRFS_EXTENT_ITEM_KEY)
                goto out;
-       }
-
-       *ref_count = 0;
-       *min_generation = (u64)-1;
 
+       last_snapshot = btrfs_root_last_snapshot(&root->root_item);
        while (1) {
                leaf = path->nodes[0];
                nritems = btrfs_header_nritems(leaf);
@@ -910,114 +911,22 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr,
 
                ref_item = btrfs_item_ptr(leaf, path->slots[0],
                                          struct btrfs_extent_ref);
-               ref_generation = btrfs_ref_generation(leaf, ref_item);
-               /*
-                * For (parent_gen > 0 && parent_gen > ref_generation):
-                *
-                * we reach here through the oldest root, therefore
-                * all other reference from same snapshot should have
-                * a larger generation.
-                */
-               if ((root_objectid != btrfs_ref_root(leaf, ref_item)) ||
-                   (parent_gen > 0 && parent_gen > ref_generation) ||
-                   (ref_objectid >= BTRFS_FIRST_FREE_OBJECTID &&
-                    ref_objectid != btrfs_ref_objectid(leaf, ref_item))) {
-                       *ref_count = 2;
-                       break;
-               }
-
-               *ref_count = 1;
-               if (*min_generation > ref_generation)
-                       *min_generation = ref_generation;
-
-               path->slots[0]++;
-       }
-       ret = 0;
-out:
-       btrfs_free_path(path);
-       return ret;
-}
-
-int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans,
-                          struct btrfs_root *root,
-                          struct btrfs_key *key, u64 bytenr)
-{
-       struct btrfs_root *old_root;
-       struct btrfs_path *path = NULL;
-       struct extent_buffer *eb;
-       struct btrfs_file_extent_item *item;
-       u64 ref_generation;
-       u64 min_generation;
-       u64 extent_start;
-       u32 ref_count;
-       int level;
-       int ret;
-
-       BUG_ON(trans == NULL);
-       BUG_ON(key->type != BTRFS_EXTENT_DATA_KEY);
-       ret = get_reference_status(root, bytenr, 0, key->objectid,
-                                  &min_generation, &ref_count);
-       if (ret)
-               return ret;
-
-       if (ref_count != 1)
-               return 1;
-
-       old_root = root->dirty_root->root;
-       ref_generation = old_root->root_key.offset;
-
-       /* all references are created in running transaction */
-       if (min_generation > ref_generation) {
-               ret = 0;
-               goto out;
-       }
-
-       path = btrfs_alloc_path();
-       if (!path) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       path->skip_locking = 1;
-       /* if no item found, the extent is referenced by other snapshot */
-       ret = btrfs_search_slot(NULL, old_root, key, path, 0, 0);
-       if (ret)
-               goto out;
-
-       eb = path->nodes[0];
-       item = btrfs_item_ptr(eb, path->slots[0],
-                             struct btrfs_file_extent_item);
-       if (btrfs_file_extent_type(eb, item) != BTRFS_FILE_EXTENT_REG ||
-           btrfs_file_extent_disk_bytenr(eb, item) != bytenr) {
-               ret = 1;
-               goto out;
-       }
-
-       for (level = BTRFS_MAX_LEVEL - 1; level >= -1; level--) {
-               if (level >= 0) {
-                       eb = path->nodes[level];
-                       if (!eb)
-                               continue;
-                       extent_start = eb->start;
-               } else
-                       extent_start = bytenr;
-
-               ret = get_reference_status(root, extent_start, ref_generation,
-                                          0, &min_generation, &ref_count);
-               if (ret)
+               ref_root = btrfs_ref_root(leaf, ref_item);
+               if (ref_root != root->root_key.objectid &&
+                   ref_root != BTRFS_TREE_LOG_OBJECTID) {
+                       ret = 1;
                        goto out;
-
-               if (ref_count != 1) {
+               }
+               if (btrfs_ref_generation(leaf, ref_item) <= last_snapshot) {
                        ret = 1;
                        goto out;
                }
-               if (level >= 0)
-                       ref_generation = btrfs_header_generation(eb);
+
+               path->slots[0]++;
        }
        ret = 0;
 out:
-       if (path)
-               btrfs_free_path(path);
+       btrfs_free_path(path);
        return ret;
 }
 
@@ -2207,12 +2116,14 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
        struct btrfs_root * root = orig_root->fs_info->extent_root;
        u64 total_needed = num_bytes;
        u64 *last_ptr = NULL;
+       u64 last_wanted = 0;
        struct btrfs_block_group_cache *block_group = NULL;
        int chunk_alloc_done = 0;
        int empty_cluster = 2 * 1024 * 1024;
        int allowed_chunk_alloc = 0;
        struct list_head *head = NULL, *cur = NULL;
        int loop = 0;
+       int extra_loop = 0;
        struct btrfs_space_info *space_info;
 
        WARN_ON(num_bytes < root->sectorsize);
@@ -2225,23 +2136,34 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
 
        if (data & BTRFS_BLOCK_GROUP_METADATA) {
                last_ptr = &root->fs_info->last_alloc;
-               empty_cluster = 256 * 1024;
+               empty_cluster = 64 * 1024;
        }
 
        if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD))
                last_ptr = &root->fs_info->last_data_alloc;
 
        if (last_ptr) {
-               if (*last_ptr)
+               if (*last_ptr) {
                        hint_byte = *last_ptr;
-               else
+                       last_wanted = *last_ptr;
+               } else
                        empty_size += empty_cluster;
+       } else {
+               empty_cluster = 0;
        }
        search_start = max(search_start, first_logical_byte(root, 0));
        search_start = max(search_start, hint_byte);
-       total_needed += empty_size;
 
+       if (last_wanted && search_start != last_wanted) {
+               last_wanted = 0;
+               empty_size += empty_cluster;
+       }
+
+       total_needed += empty_size;
        block_group = btrfs_lookup_block_group(root->fs_info, search_start);
+       if (!block_group)
+               block_group = btrfs_lookup_first_block_group(root->fs_info,
+                                                            search_start);
        space_info = __find_space_info(root->fs_info, data);
 
        down_read(&space_info->groups_sem);
@@ -2252,7 +2174,12 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
                 * group thats not of the proper type, while looping this
                 * should never happen
                 */
-               WARN_ON(!block_group);
+               if (empty_size)
+                       extra_loop = 1;
+
+               if (!block_group)
+                       goto new_group_no_lock;
+
                mutex_lock(&block_group->alloc_mutex);
                if (unlikely(!block_group_bits(block_group, data)))
                        goto new_group;
@@ -2283,6 +2210,24 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
                        if (search_start + num_bytes > end)
                                goto new_group;
 
+                       if (last_wanted && search_start != last_wanted) {
+                               total_needed += empty_cluster;
+                               empty_size += empty_cluster;
+                               last_wanted = 0;
+                               /*
+                                * if search_start is still in this block group
+                                * then we just re-search this block group
+                                */
+                               if (search_start >= start &&
+                                   search_start < end) {
+                                       mutex_unlock(&block_group->alloc_mutex);
+                                       continue;
+                               }
+
+                               /* else we go to the next block group */
+                               goto new_group;
+                       }
+
                        if (exclude_nr > 0 &&
                            (search_start + num_bytes > exclude_start &&
                             search_start < exclude_start + exclude_nr)) {
@@ -2294,6 +2239,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
                                if (search_start >= start &&
                                    search_start < end) {
                                        mutex_unlock(&block_group->alloc_mutex);
+                                       last_wanted = 0;
                                        continue;
                                }
 
@@ -2312,6 +2258,12 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
                }
 new_group:
                mutex_unlock(&block_group->alloc_mutex);
+new_group_no_lock:
+               /* don't try to compare new allocations against the
+                * last allocation any more
+                */
+               last_wanted = 0;
+
                /*
                 * Here's how this works.
                 * loop == 0: we were searching a block group via a hint
@@ -2327,13 +2279,24 @@ new_group:
                if (loop == 0) {
                        head = &space_info->block_groups;
                        cur = head->next;
-
-                       if (last_ptr && *last_ptr) {
-                               total_needed += empty_cluster;
-                               *last_ptr = 0;
-                       }
                        loop++;
                } else if (loop == 1 && cur == head) {
+                       int keep_going;
+
+                       /* at this point we give up on the empty_size
+                        * allocations and just try to allocate the min
+                        * space.
+                        *
+                        * The extra_loop field was set if an empty_size
+                        * allocation was attempted above, and if this
+                        * is try we need to try the loop again without
+                        * the additional empty_size.
+                        */
+                       total_needed -= empty_size;
+                       empty_size = 0;
+                       keep_going = extra_loop;
+                       loop++;
+
                        if (allowed_chunk_alloc && !chunk_alloc_done) {
                                up_read(&space_info->groups_sem);
                                ret = do_chunk_alloc(trans, root, num_bytes +
@@ -2341,13 +2304,19 @@ new_group:
                                if (ret < 0)
                                        break;
                                down_read(&space_info->groups_sem);
-                               loop++;
                                head = &space_info->block_groups;
-                               cur = head->next;
+                               /*
+                                * we've allocated a new chunk, keep
+                                * trying
+                                */
+                               keep_going = 1;
                                chunk_alloc_done = 1;
                        } else if (!allowed_chunk_alloc) {
                                space_info->force_alloc = 1;
-                               break;
+                       }
+                       if (keep_going) {
+                               cur = head->next;
+                               extra_loop = 0;
                        } else {
                                break;
                        }
@@ -3379,11 +3348,13 @@ static int noinline relocate_data_extent(struct inode *reloc_inode,
        struct btrfs_root *root = BTRFS_I(reloc_inode)->root;
        struct extent_map_tree *em_tree = &BTRFS_I(reloc_inode)->extent_tree;
        struct extent_map *em;
+       u64 start = extent_key->objectid - offset;
+       u64 end = start + extent_key->offset - 1;
 
        em = alloc_extent_map(GFP_NOFS);
        BUG_ON(!em || IS_ERR(em));
 
-       em->start = extent_key->objectid - offset;
+       em->start = start;
        em->len = extent_key->offset;
        em->block_len = extent_key->offset;
        em->block_start = extent_key->objectid;
@@ -3391,7 +3362,7 @@ static int noinline relocate_data_extent(struct inode *reloc_inode,
        set_bit(EXTENT_FLAG_PINNED, &em->flags);
 
        /* setup extent map to cheat btrfs_readpage */
-       mutex_lock(&BTRFS_I(reloc_inode)->extent_mutex);
+       lock_extent(&BTRFS_I(reloc_inode)->io_tree, start, end, GFP_NOFS);
        while (1) {
                int ret;
                spin_lock(&em_tree->lock);
@@ -3401,13 +3372,11 @@ static int noinline relocate_data_extent(struct inode *reloc_inode,
                        free_extent_map(em);
                        break;
                }
-               btrfs_drop_extent_cache(reloc_inode, em->start,
-                                       em->start + em->len - 1, 0);
+               btrfs_drop_extent_cache(reloc_inode, start, end, 0);
        }
-       mutex_unlock(&BTRFS_I(reloc_inode)->extent_mutex);
+       unlock_extent(&BTRFS_I(reloc_inode)->io_tree, start, end, GFP_NOFS);
 
-       return relocate_inode_pages(reloc_inode, extent_key->objectid - offset,
-                                   extent_key->offset);
+       return relocate_inode_pages(reloc_inode, start, extent_key->offset);
 }
 
 struct btrfs_ref_path {
@@ -3521,9 +3490,7 @@ walk_down:
 next:
                level--;
                btrfs_release_path(extent_root, path);
-               if (need_resched()) {
-                       cond_resched();
-               }
+               cond_resched();
        }
        /* reached lowest level */
        ret = 1;
@@ -3634,9 +3601,7 @@ found:
                }
 
                btrfs_release_path(extent_root, path);
-               if (need_resched()) {
-                       cond_resched();
-               }
+               cond_resched();
        }
        /* reached max tree level, but no tree root found. */
        BUG();
@@ -3749,8 +3714,9 @@ static int noinline get_new_locations(struct inode *reloc_inode,
                exts[nr].encryption = btrfs_file_extent_encryption(leaf, fi);
                exts[nr].other_encoding = btrfs_file_extent_other_encoding(leaf,
                                                                           fi);
-               WARN_ON(exts[nr].offset > 0);
-               WARN_ON(exts[nr].num_bytes != exts[nr].disk_num_bytes);
+               BUG_ON(exts[nr].offset > 0);
+               BUG_ON(exts[nr].compression || exts[nr].encryption);
+               BUG_ON(exts[nr].num_bytes != exts[nr].disk_num_bytes);
 
                cur_pos += exts[nr].num_bytes;
                nr++;
@@ -3804,6 +3770,7 @@ static int noinline replace_one_extent(struct btrfs_trans_handle *trans,
        u32 nritems;
        int nr_scaned = 0;
        int extent_locked = 0;
+       int extent_type;
        int ret;
 
        memcpy(&key, leaf_key, sizeof(key));
@@ -3831,7 +3798,6 @@ next:
                         * the file extent item was modified by someone
                         * before the extent got locked.
                         */
-                       mutex_unlock(&BTRFS_I(inode)->extent_mutex);
                        unlock_extent(&BTRFS_I(inode)->io_tree, lock_start,
                                      lock_end, GFP_NOFS);
                        extent_locked = 0;
@@ -3877,8 +3843,9 @@ next:
                }
                fi = btrfs_item_ptr(leaf, path->slots[0],
                                    struct btrfs_file_extent_item);
-               if ((btrfs_file_extent_type(leaf, fi) !=
-                    BTRFS_FILE_EXTENT_REG) ||
+               extent_type = btrfs_file_extent_type(leaf, fi);
+               if ((extent_type != BTRFS_FILE_EXTENT_REG &&
+                    extent_type != BTRFS_FILE_EXTENT_PREALLOC) ||
                    (btrfs_file_extent_disk_bytenr(leaf, fi) !=
                     extent_key->objectid)) {
                        path->slots[0]++;
@@ -3896,8 +3863,12 @@ next:
                        lock_start = key.offset;
                        lock_end = lock_start + num_bytes - 1;
                } else {
-                       BUG_ON(lock_start != key.offset);
-                       BUG_ON(lock_end - lock_start + 1 < num_bytes);
+                       if (lock_start > key.offset ||
+                           lock_end + 1 < key.offset + num_bytes) {
+                               unlock_extent(&BTRFS_I(inode)->io_tree,
+                                             lock_start, lock_end, GFP_NOFS);
+                               extent_locked = 0;
+                       }
                }
 
                if (!inode) {
@@ -3951,23 +3922,16 @@ next:
                        if (ordered)
                                btrfs_put_ordered_extent(ordered);
 
-                       mutex_lock(&BTRFS_I(inode)->extent_mutex);
                        extent_locked = 1;
                        continue;
                }
 
                if (nr_extents == 1) {
                        /* update extent pointer in place */
-                       btrfs_set_file_extent_generation(leaf, fi,
-                                               trans->transid);
                        btrfs_set_file_extent_disk_bytenr(leaf, fi,
                                                new_extents[0].disk_bytenr);
                        btrfs_set_file_extent_disk_num_bytes(leaf, fi,
                                                new_extents[0].disk_num_bytes);
-                       btrfs_set_file_extent_ram_bytes(leaf, fi,
-                                               new_extents[0].ram_bytes);
-                       ext_offset += new_extents[0].offset;
-                       btrfs_set_file_extent_offset(leaf, fi, ext_offset);
                        btrfs_mark_buffer_dirty(leaf);
 
                        btrfs_drop_extent_cache(inode, key.offset,
@@ -3994,6 +3958,8 @@ next:
                        btrfs_release_path(root, path);
                        key.offset += num_bytes;
                } else {
+                       BUG_ON(1);
+#if 0
                        u64 alloc_hint;
                        u64 extent_len;
                        int i;
@@ -4070,10 +4036,10 @@ next:
                                        break;
                        }
                        BUG_ON(i >= nr_extents);
+#endif
                }
 
                if (extent_locked) {
-                       mutex_unlock(&BTRFS_I(inode)->extent_mutex);
                        unlock_extent(&BTRFS_I(inode)->io_tree, lock_start,
                                      lock_end, GFP_NOFS);
                        extent_locked = 0;
@@ -4091,7 +4057,6 @@ out:
        if (inode) {
                mutex_unlock(&inode->i_mutex);
                if (extent_locked) {
-                       mutex_unlock(&BTRFS_I(inode)->extent_mutex);
                        unlock_extent(&BTRFS_I(inode)->io_tree, lock_start,
                                      lock_end, GFP_NOFS);
                }
@@ -4180,10 +4145,8 @@ static int noinline invalidate_extent_cache(struct btrfs_root *root,
 
                lock_extent(&BTRFS_I(inode)->io_tree, key.offset,
                            key.offset + num_bytes - 1, GFP_NOFS);
-               mutex_lock(&BTRFS_I(inode)->extent_mutex);
                btrfs_drop_extent_cache(inode, key.offset,
                                        key.offset + num_bytes - 1, 1);
-               mutex_unlock(&BTRFS_I(inode)->extent_mutex);
                unlock_extent(&BTRFS_I(inode)->io_tree, key.offset,
                              key.offset + num_bytes - 1, GFP_NOFS);
                cond_resched();
@@ -4253,15 +4216,10 @@ static int noinline replace_extents_in_leaf(struct btrfs_trans_handle *trans,
                ref->extents[ext_index].bytenr = new_extent->disk_bytenr;
                ref->extents[ext_index].num_bytes = new_extent->disk_num_bytes;
 
-               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
-               btrfs_set_file_extent_ram_bytes(leaf, fi,
-                                               new_extent->ram_bytes);
                btrfs_set_file_extent_disk_bytenr(leaf, fi,
                                                new_extent->disk_bytenr);
                btrfs_set_file_extent_disk_num_bytes(leaf, fi,
                                                new_extent->disk_num_bytes);
-               new_extent->offset += btrfs_file_extent_offset(leaf, fi);
-               btrfs_set_file_extent_offset(leaf, fi, new_extent->offset);
                btrfs_mark_buffer_dirty(leaf);
 
                ret = btrfs_inc_extent_ref(trans, root,
@@ -4722,12 +4680,15 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root,
                         */
                        if (!new_extents) {
                                u64 group_start = group->key.objectid;
+                               new_extents = kmalloc(sizeof(*new_extents),
+                                                     GFP_NOFS);
+                               nr_extents = 1;
                                ret = get_new_locations(reloc_inode,
                                                        extent_key,
-                                                       group_start, 0,
+                                                       group_start, 1,
                                                        &new_extents,
                                                        &nr_extents);
-                               if (ret < 0)
+                               if (ret)
                                        goto out;
                        }
                        btrfs_record_root_in_trans(found_root);
@@ -4859,7 +4820,8 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans,
        btrfs_set_inode_generation(leaf, item, 1);
        btrfs_set_inode_size(leaf, item, size);
        btrfs_set_inode_mode(leaf, item, S_IFREG | 0600);
-       btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NODATASUM);
+       btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NODATASUM |
+                                         BTRFS_INODE_NOCOMPRESS);
        btrfs_mark_buffer_dirty(leaf);
        btrfs_release_path(root, path);
 out:
@@ -4932,6 +4894,7 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start)
        struct inode *reloc_inode;
        struct btrfs_block_group_cache *block_group;
        struct btrfs_key key;
+       u64 skipped;
        u64 cur_byte;
        u64 total_found;
        u32 nritems;
@@ -4961,6 +4924,7 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start)
        btrfs_start_delalloc_inodes(info->tree_root);
        btrfs_wait_ordered_extents(info->tree_root, 0);
 again:
+       skipped = 0;
        total_found = 0;
        progress = 0;
        key.objectid = block_group->key.objectid;
@@ -5023,6 +4987,8 @@ next:
                ret = relocate_one_extent(root, path, &key, block_group,
                                          reloc_inode, pass);
                BUG_ON(ret < 0);
+               if (ret > 0)
+                       skipped++;
 
                key.objectid = cur_byte;
                key.type = 0;
@@ -5041,6 +5007,11 @@ next:
                printk("btrfs found %llu extents in pass %d\n",
                       (unsigned long long)total_found, pass);
                pass++;
+               if (total_found == skipped && pass > 2) {
+                       iput(reloc_inode);
+                       reloc_inode = create_reloc_inode(info, block_group);
+                       pass = 0;
+               }
                goto again;
        }
 
@@ -5108,17 +5079,17 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
        while ((n = rb_last(&info->block_group_cache_tree)) != NULL) {
                block_group = rb_entry(n, struct btrfs_block_group_cache,
                                       cache_node);
-
-               spin_unlock(&info->block_group_cache_lock);
-               btrfs_remove_free_space_cache(block_group);
-               spin_lock(&info->block_group_cache_lock);
-
                rb_erase(&block_group->cache_node,
                         &info->block_group_cache_tree);
+               spin_unlock(&info->block_group_cache_lock);
+
+               btrfs_remove_free_space_cache(block_group);
                down_write(&block_group->space_info->groups_sem);
                list_del(&block_group->list);
                up_write(&block_group->space_info->groups_sem);
                kfree(block_group);
+
+               spin_lock(&info->block_group_cache_lock);
        }
        spin_unlock(&info->block_group_cache_lock);
        return 0;