aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-12-16 23:01:12 -0500
committerChris Mason <clm@fb.com>2014-01-28 16:20:03 -0500
commit536cd96401dcb986f681bac385b5146b45a44e66 (patch)
treef4263aefbe815bc5ff74b1b18b8988722e8631be /fs/btrfs/extent-tree.c
parent180589efde8a01b4a30af273f670ac81c8abf9c5 (diff)
Btrfs: fix double initialization of the raid kobject
We met the following oops when doing space balance: kobject (ffff88081b590278): tried to init an initialized object, something is seriously wrong. ... Call Trace: [<ffffffff81937262>] dump_stack+0x49/0x5f [<ffffffff8137d259>] kobject_init+0x89/0xa0 [<ffffffff8137d36a>] kobject_init_and_add+0x2a/0x70 [<ffffffffa009bd79>] ? clear_extent_bit+0x199/0x470 [btrfs] [<ffffffffa005e82c>] __link_block_group+0xfc/0x120 [btrfs] [<ffffffffa006b9db>] btrfs_make_block_group+0x24b/0x370 [btrfs] [<ffffffffa00a899b>] __btrfs_alloc_chunk+0x54b/0x7e0 [btrfs] [<ffffffffa00a8c6f>] btrfs_alloc_chunk+0x3f/0x50 [btrfs] [<ffffffffa0060123>] do_chunk_alloc+0x363/0x440 [btrfs] [<ffffffffa00633d4>] btrfs_check_data_free_space+0x104/0x310 [btrfs] [<ffffffffa0069f4d>] btrfs_write_dirty_block_groups+0x48d/0x600 [btrfs] [<ffffffffa007aad4>] commit_cowonly_roots+0x184/0x250 [btrfs] ... Steps to reproduce: # mkfs.btrfs -f <dev> # mount -o nospace_cache <dev> <mnt> # btrfs balance start <mnt> # dd if=/dev/zero of=<mnt>/tmpfile bs=1M count=1 The reason of this problem is that we initialized the raid kobject when we added a block group into a empty raid list. As we know, when we mounted a btrfs filesystem, the raid list was empty, we would initialize the raid kobject when we added the first block group. But if there was not data stored in the block group, the block group would be freed when doing balance, and the raid list would be empty. And then if we allocated a new block group and added it into the raid list, we would initialize the raid kobject again, the oops happened. Fix this problem by initializing the raid kobject just when mounting the fs. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Reported-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f08f6dda949f..9e524b0a7b3c 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3463,8 +3463,10 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
3463 return ret; 3463 return ret;
3464 } 3464 }
3465 3465
3466 for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) 3466 for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
3467 INIT_LIST_HEAD(&found->block_groups[i]); 3467 INIT_LIST_HEAD(&found->block_groups[i]);
3468 kobject_init(&found->block_group_kobjs[i], &btrfs_raid_ktype);
3469 }
3468 init_rwsem(&found->groups_sem); 3470 init_rwsem(&found->groups_sem);
3469 spin_lock_init(&found->lock); 3471 spin_lock_init(&found->lock);
3470 found->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; 3472 found->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
@@ -8422,9 +8424,8 @@ static void __link_block_group(struct btrfs_space_info *space_info,
8422 int ret; 8424 int ret;
8423 8425
8424 kobject_get(&space_info->kobj); /* put in release */ 8426 kobject_get(&space_info->kobj); /* put in release */
8425 ret = kobject_init_and_add(kobj, &btrfs_raid_ktype, 8427 ret = kobject_add(kobj, &space_info->kobj, "%s",
8426 &space_info->kobj, "%s", 8428 get_raid_name(index));
8427 get_raid_name(index));
8428 if (ret) { 8429 if (ret) {
8429 pr_warn("btrfs: failed to add kobject for block cache. ignoring.\n"); 8430 pr_warn("btrfs: failed to add kobject for block cache. ignoring.\n");
8430 kobject_put(&space_info->kobj); 8431 kobject_put(&space_info->kobj);