aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-09-25 09:47:45 -0400
committerChris Mason <chris.mason@fusionio.com>2013-11-11 21:54:28 -0500
commit20dd2cbf01888a91fdd921403040a710b275a1ff (patch)
treec669c83c8f9d84782ff653c31907ac9b26745350 /fs/btrfs/transaction.c
parent0a4e558609dd4df30a58a07d9eb14c5ddc2c1241 (diff)
Btrfs: fix BUG_ON() casued by the reserved space migration
When we did space balance and snapshot creation at the same time, we might meet the following oops: kernel BUG at fs/btrfs/inode.c:3038! [SNIP] Call Trace: [<ffffffffa0411ec7>] btrfs_orphan_cleanup+0x293/0x407 [btrfs] [<ffffffffa042dc45>] btrfs_mksubvol.isra.28+0x259/0x373 [btrfs] [<ffffffffa042de85>] btrfs_ioctl_snap_create_transid+0x126/0x156 [btrfs] [<ffffffffa042dff1>] btrfs_ioctl_snap_create_v2+0xd0/0x121 [btrfs] [<ffffffffa0430b2c>] btrfs_ioctl+0x414/0x1854 [btrfs] [<ffffffff813b60b7>] ? __do_page_fault+0x305/0x379 [<ffffffff811215a9>] vfs_ioctl+0x1d/0x39 [<ffffffff81121d7c>] do_vfs_ioctl+0x32d/0x3e2 [<ffffffff81057fe7>] ? finish_task_switch+0x80/0xb8 [<ffffffff81121e88>] SyS_ioctl+0x57/0x83 [<ffffffff813b39ff>] ? do_device_not_available+0x12/0x14 [<ffffffff813b99c2>] system_call_fastpath+0x16/0x1b [SNIP] RIP [<ffffffffa040da40>] btrfs_orphan_add+0xc3/0x126 [btrfs] The reason of the problem is that the relocation root creation stole the reserved space, which was reserved for orphan item deletion. There are several ways to fix this problem, one is to increasing the reserved space size of the space balace, and then we can use that space to create the relocation tree for each fs/file trees. But it is hard to calculate the suitable size because we doesn't know how many fs/file trees we need relocate. We fixed this problem by reserving the space for relocation root creation actively since the space it need is very small (one tree block, used for root node copy), then we use that reserved space to create the relocation tree. If we don't reserve space for relocation tree creation, we will use the reserved space of the balance. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 134039fd59bb..a213bafe68ec 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -353,6 +353,17 @@ static int may_wait_transaction(struct btrfs_root *root, int type)
353 return 0; 353 return 0;
354} 354}
355 355
356static inline bool need_reserve_reloc_root(struct btrfs_root *root)
357{
358 if (!root->fs_info->reloc_ctl ||
359 !root->ref_cows ||
360 root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID ||
361 root->reloc_root)
362 return false;
363
364 return true;
365}
366
356static struct btrfs_trans_handle * 367static struct btrfs_trans_handle *
357start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type, 368start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type,
358 enum btrfs_reserve_flush_enum flush) 369 enum btrfs_reserve_flush_enum flush)
@@ -360,8 +371,9 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type,
360 struct btrfs_trans_handle *h; 371 struct btrfs_trans_handle *h;
361 struct btrfs_transaction *cur_trans; 372 struct btrfs_transaction *cur_trans;
362 u64 num_bytes = 0; 373 u64 num_bytes = 0;
363 int ret;
364 u64 qgroup_reserved = 0; 374 u64 qgroup_reserved = 0;
375 bool reloc_reserved = false;
376 int ret;
365 377
366 if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) 378 if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
367 return ERR_PTR(-EROFS); 379 return ERR_PTR(-EROFS);
@@ -390,6 +402,14 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type,
390 } 402 }
391 403
392 num_bytes = btrfs_calc_trans_metadata_size(root, num_items); 404 num_bytes = btrfs_calc_trans_metadata_size(root, num_items);
405 /*
406 * Do the reservation for the relocation root creation
407 */
408 if (unlikely(need_reserve_reloc_root(root))) {
409 num_bytes += root->nodesize;
410 reloc_reserved = true;
411 }
412
393 ret = btrfs_block_rsv_add(root, 413 ret = btrfs_block_rsv_add(root,
394 &root->fs_info->trans_block_rsv, 414 &root->fs_info->trans_block_rsv,
395 num_bytes, flush); 415 num_bytes, flush);
@@ -451,6 +471,7 @@ again:
451 h->delayed_ref_elem.seq = 0; 471 h->delayed_ref_elem.seq = 0;
452 h->type = type; 472 h->type = type;
453 h->allocating_chunk = false; 473 h->allocating_chunk = false;
474 h->reloc_reserved = false;
454 INIT_LIST_HEAD(&h->qgroup_ref_list); 475 INIT_LIST_HEAD(&h->qgroup_ref_list);
455 INIT_LIST_HEAD(&h->new_bgs); 476 INIT_LIST_HEAD(&h->new_bgs);
456 477
@@ -466,6 +487,7 @@ again:
466 h->transid, num_bytes, 1); 487 h->transid, num_bytes, 1);
467 h->block_rsv = &root->fs_info->trans_block_rsv; 488 h->block_rsv = &root->fs_info->trans_block_rsv;
468 h->bytes_reserved = num_bytes; 489 h->bytes_reserved = num_bytes;
490 h->reloc_reserved = reloc_reserved;
469 } 491 }
470 h->qgroup_reserved = qgroup_reserved; 492 h->qgroup_reserved = qgroup_reserved;
471 493