aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-02-28 05:04:33 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-28 13:33:54 -0500
commitd5c1207017cd8387b4d3224dd7ab6cf5cd7f1c9a (patch)
tree7208d1c89aa625fa6eb349fdafa2e49a00bbe078 /fs/btrfs/extent-tree.c
parente9662f701c85ebc99f532bf8bb53208c0648846a (diff)
Btrfs: fix wrong reserved space in qgroup during snap/subv creation
There are two problems in the space reservation of the snapshot/ subvolume creation. - don't reserve the space for the root item insertion - the space which is reserved in the qgroup is different with the free space reservation. we need reserve free space for 7 items, but in qgroup reservation, we need reserve space only for 3 items. So we implement new metadata reservation functions for the snapshot/subvolume creation. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 5681a91ed400..7cb9d734f6e5 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4560,19 +4560,60 @@ void btrfs_orphan_release_metadata(struct inode *inode)
4560 btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes); 4560 btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes);
4561} 4561}
4562 4562
4563int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, 4563/*
4564 struct btrfs_pending_snapshot *pending) 4564 * btrfs_subvolume_reserve_metadata() - reserve space for subvolume operation
4565 * root: the root of the parent directory
4566 * rsv: block reservation
4567 * items: the number of items that we need do reservation
4568 * qgroup_reserved: used to return the reserved size in qgroup
4569 *
4570 * This function is used to reserve the space for snapshot/subvolume
4571 * creation and deletion. Those operations are different with the
4572 * common file/directory operations, they change two fs/file trees
4573 * and root tree, the number of items that the qgroup reserves is
4574 * different with the free space reservation. So we can not use
4575 * the space reseravtion mechanism in start_transaction().
4576 */
4577int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
4578 struct btrfs_block_rsv *rsv,
4579 int items,
4580 u64 *qgroup_reserved)
4565{ 4581{
4566 struct btrfs_root *root = pending->root; 4582 u64 num_bytes;
4567 struct btrfs_block_rsv *src_rsv = get_block_rsv(trans, root); 4583 int ret;
4568 struct btrfs_block_rsv *dst_rsv = &pending->block_rsv; 4584
4569 /* 4585 if (root->fs_info->quota_enabled) {
4570 * two for root back/forward refs, two for directory entries, 4586 /* One for parent inode, two for dir entries */
4571 * one for root of the snapshot and one for parent inode. 4587 num_bytes = 3 * root->leafsize;
4572 */ 4588 ret = btrfs_qgroup_reserve(root, num_bytes);
4573 u64 num_bytes = btrfs_calc_trans_metadata_size(root, 6); 4589 if (ret)
4574 dst_rsv->space_info = src_rsv->space_info; 4590 return ret;
4575 return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes); 4591 } else {
4592 num_bytes = 0;
4593 }
4594
4595 *qgroup_reserved = num_bytes;
4596
4597 num_bytes = btrfs_calc_trans_metadata_size(root, items);
4598 rsv->space_info = __find_space_info(root->fs_info,
4599 BTRFS_BLOCK_GROUP_METADATA);
4600 ret = btrfs_block_rsv_add(root, rsv, num_bytes,
4601 BTRFS_RESERVE_FLUSH_ALL);
4602 if (ret) {
4603 if (*qgroup_reserved)
4604 btrfs_qgroup_free(root, *qgroup_reserved);
4605 }
4606
4607 return ret;
4608}
4609
4610void btrfs_subvolume_release_metadata(struct btrfs_root *root,
4611 struct btrfs_block_rsv *rsv,
4612 u64 qgroup_reserved)
4613{
4614 btrfs_block_rsv_release(root, rsv, (u64)-1);
4615 if (qgroup_reserved)
4616 btrfs_qgroup_free(root, qgroup_reserved);
4576} 4617}
4577 4618
4578/** 4619/**