summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik2011-05-13 20:49:23 +0200
committerJosef Bacik2011-05-23 19:03:16 +0200
commit207dde8289d9b005b665cb9d8d2bb9464256101d (patch)
treebbe7e61bdf6221468360c31ba293d50197745acb
parentBtrfs: don't try to allocate from a block group that doesn't have enough space (diff)
downloadkernel-qcow2-linux-207dde8289d9b005b665cb9d8d2bb9464256101d.tar.gz
kernel-qcow2-linux-207dde8289d9b005b665cb9d8d2bb9464256101d.tar.xz
kernel-qcow2-linux-207dde8289d9b005b665cb9d8d2bb9464256101d.zip
Btrfs: check for duplicate entries in the free space cache
If there are duplicate entries in the free space cache, discard the entire cache and load it the old fashioned way. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
-rw-r--r--fs/btrfs/free-space-cache.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 63731a1fb0a1..d634a7e42207 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -420,7 +420,14 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
spin_lock(&block_group->tree_lock);
ret = link_free_space(block_group, e);
spin_unlock(&block_group->tree_lock);
- BUG_ON(ret);
+ if (ret) {
+ printk(KERN_ERR "Duplicate entries in "
+ "free space cache, dumping\n");
+ kunmap(page);
+ unlock_page(page);
+ page_cache_release(page);
+ goto free_cache;
+ }
} else {
e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
if (!e->bitmap) {
@@ -437,6 +444,14 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
recalculate_thresholds(block_group);
spin_unlock(&block_group->tree_lock);
list_add_tail(&e->list, &bitmaps);
+ if (ret) {
+ printk(KERN_ERR "Duplicate entries in "
+ "free space cache, dumping\n");
+ kunmap(page);
+ unlock_page(page);
+ page_cache_release(page);
+ goto free_cache;
+ }
}
num_entries--;
@@ -909,10 +924,16 @@ static int tree_insert_offset(struct rb_root *root, u64 offset,
* logically.
*/
if (bitmap) {
- WARN_ON(info->bitmap);
+ if (info->bitmap) {
+ WARN_ON_ONCE(1);
+ return -EEXIST;
+ }
p = &(*p)->rb_right;
} else {
- WARN_ON(!info->bitmap);
+ if (!info->bitmap) {
+ WARN_ON_ONCE(1);
+ return -EEXIST;
+ }
p = &(*p)->rb_left;
}
}