aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2010-05-16 10:49:58 -0400
committerChris Mason <chris.mason@oracle.com>2010-05-25 10:34:52 -0400
commit8929ecfa50f266163832eeacfbc3642ed5eb83b6 (patch)
treee0177748af36d49d5f652cff0e421a8268cf7194 /fs/btrfs/extent-tree.c
parent0ca1f7ceb1991099ed5273885ebcf4323948c72e (diff)
Btrfs: Introduce global metadata reservation
Reserve metadata space for extent tree, checksum tree and root tree Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c147
1 files changed, 128 insertions, 19 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index b1822e752b4a..cb814a71800d 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2895,10 +2895,9 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes)
2895again: 2895again:
2896 /* make sure we have enough space to handle the data first */ 2896 /* make sure we have enough space to handle the data first */
2897 spin_lock(&data_sinfo->lock); 2897 spin_lock(&data_sinfo->lock);
2898 used = data_sinfo->bytes_used + data_sinfo->bytes_delalloc + 2898 used = data_sinfo->bytes_used + data_sinfo->bytes_reserved +
2899 data_sinfo->bytes_reserved + data_sinfo->bytes_pinned + 2899 data_sinfo->bytes_pinned + data_sinfo->bytes_readonly +
2900 data_sinfo->bytes_readonly + data_sinfo->bytes_may_use + 2900 data_sinfo->bytes_may_use;
2901 data_sinfo->bytes_super;
2902 2901
2903 if (used + bytes > data_sinfo->total_bytes) { 2902 if (used + bytes > data_sinfo->total_bytes) {
2904 struct btrfs_trans_handle *trans; 2903 struct btrfs_trans_handle *trans;
@@ -2922,7 +2921,7 @@ alloc:
2922 bytes + 2 * 1024 * 1024, 2921 bytes + 2 * 1024 * 1024,
2923 alloc_target, 0); 2922 alloc_target, 0);
2924 btrfs_end_transaction(trans, root); 2923 btrfs_end_transaction(trans, root);
2925 if (ret) 2924 if (ret < 0)
2926 return ret; 2925 return ret;
2927 2926
2928 if (!data_sinfo) { 2927 if (!data_sinfo) {
@@ -2945,11 +2944,10 @@ alloc:
2945 goto again; 2944 goto again;
2946 } 2945 }
2947 2946
2948 printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes" 2947 printk(KERN_ERR "no space left, need %llu, %llu bytes_used, "
2949 ", %llu bytes_used, %llu bytes_reserved, " 2948 "%llu bytes_reserved, " "%llu bytes_pinned, "
2950 "%llu bytes_pinned, %llu bytes_readonly, %llu may use " 2949 "%llu bytes_readonly, %llu may use %llu total\n",
2951 "%llu total\n", (unsigned long long)bytes, 2950 (unsigned long long)bytes,
2952 (unsigned long long)data_sinfo->bytes_delalloc,
2953 (unsigned long long)data_sinfo->bytes_used, 2951 (unsigned long long)data_sinfo->bytes_used,
2954 (unsigned long long)data_sinfo->bytes_reserved, 2952 (unsigned long long)data_sinfo->bytes_reserved,
2955 (unsigned long long)data_sinfo->bytes_pinned, 2953 (unsigned long long)data_sinfo->bytes_pinned,
@@ -3464,6 +3462,91 @@ void btrfs_block_rsv_release(struct btrfs_root *root,
3464 block_rsv_release_bytes(block_rsv, global_rsv, num_bytes); 3462 block_rsv_release_bytes(block_rsv, global_rsv, num_bytes);
3465} 3463}
3466 3464
3465/*
3466 * helper to calculate size of global block reservation.
3467 * the desired value is sum of space used by extent tree,
3468 * checksum tree and root tree
3469 */
3470static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
3471{
3472 struct btrfs_space_info *sinfo;
3473 u64 num_bytes;
3474 u64 meta_used;
3475 u64 data_used;
3476 int csum_size = btrfs_super_csum_size(&fs_info->super_copy);
3477#if 0
3478 /*
3479 * per tree used space accounting can be inaccuracy, so we
3480 * can't rely on it.
3481 */
3482 spin_lock(&fs_info->extent_root->accounting_lock);
3483 num_bytes = btrfs_root_used(&fs_info->extent_root->root_item);
3484 spin_unlock(&fs_info->extent_root->accounting_lock);
3485
3486 spin_lock(&fs_info->csum_root->accounting_lock);
3487 num_bytes += btrfs_root_used(&fs_info->csum_root->root_item);
3488 spin_unlock(&fs_info->csum_root->accounting_lock);
3489
3490 spin_lock(&fs_info->tree_root->accounting_lock);
3491 num_bytes += btrfs_root_used(&fs_info->tree_root->root_item);
3492 spin_unlock(&fs_info->tree_root->accounting_lock);
3493#endif
3494 sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA);
3495 spin_lock(&sinfo->lock);
3496 data_used = sinfo->bytes_used;
3497 spin_unlock(&sinfo->lock);
3498
3499 sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
3500 spin_lock(&sinfo->lock);
3501 meta_used = sinfo->bytes_used;
3502 spin_unlock(&sinfo->lock);
3503
3504 num_bytes = (data_used >> fs_info->sb->s_blocksize_bits) *
3505 csum_size * 2;
3506 num_bytes += div64_u64(data_used + meta_used, 50);
3507
3508 if (num_bytes * 3 > meta_used)
3509 num_bytes = div64_u64(meta_used, 3);
3510
3511 return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
3512}
3513
3514static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
3515{
3516 struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
3517 struct btrfs_space_info *sinfo = block_rsv->space_info;
3518 u64 num_bytes;
3519
3520 num_bytes = calc_global_metadata_size(fs_info);
3521
3522 spin_lock(&block_rsv->lock);
3523 spin_lock(&sinfo->lock);
3524
3525 block_rsv->size = num_bytes;
3526
3527 num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
3528 sinfo->bytes_reserved + sinfo->bytes_readonly;
3529
3530 if (sinfo->total_bytes > num_bytes) {
3531 num_bytes = sinfo->total_bytes - num_bytes;
3532 block_rsv->reserved += num_bytes;
3533 sinfo->bytes_reserved += num_bytes;
3534 }
3535
3536 if (block_rsv->reserved >= block_rsv->size) {
3537 num_bytes = block_rsv->reserved - block_rsv->size;
3538 sinfo->bytes_reserved -= num_bytes;
3539 block_rsv->reserved = block_rsv->size;
3540 block_rsv->full = 1;
3541 }
3542#if 0
3543 printk(KERN_INFO"global block rsv size %llu reserved %llu\n",
3544 block_rsv->size, block_rsv->reserved);
3545#endif
3546 spin_unlock(&sinfo->lock);
3547 spin_unlock(&block_rsv->lock);
3548}
3549
3467static void init_global_block_rsv(struct btrfs_fs_info *fs_info) 3550static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
3468{ 3551{
3469 struct btrfs_space_info *space_info; 3552 struct btrfs_space_info *space_info;
@@ -3473,11 +3556,36 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
3473 fs_info->chunk_block_rsv.priority = 10; 3556 fs_info->chunk_block_rsv.priority = 10;
3474 3557
3475 space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); 3558 space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
3559 fs_info->global_block_rsv.space_info = space_info;
3560 fs_info->global_block_rsv.priority = 10;
3561 fs_info->global_block_rsv.refill_used = 1;
3562 fs_info->delalloc_block_rsv.space_info = space_info;
3476 fs_info->trans_block_rsv.space_info = space_info; 3563 fs_info->trans_block_rsv.space_info = space_info;
3477 fs_info->empty_block_rsv.space_info = space_info; 3564 fs_info->empty_block_rsv.space_info = space_info;
3478 fs_info->empty_block_rsv.priority = 10; 3565 fs_info->empty_block_rsv.priority = 10;
3479 3566
3567 fs_info->extent_root->block_rsv = &fs_info->global_block_rsv;
3568 fs_info->csum_root->block_rsv = &fs_info->global_block_rsv;
3569 fs_info->dev_root->block_rsv = &fs_info->global_block_rsv;
3570 fs_info->tree_root->block_rsv = &fs_info->global_block_rsv;
3480 fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv; 3571 fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv;
3572
3573 btrfs_add_durable_block_rsv(fs_info, &fs_info->global_block_rsv);
3574
3575 btrfs_add_durable_block_rsv(fs_info, &fs_info->delalloc_block_rsv);
3576
3577 update_global_block_rsv(fs_info);
3578}
3579
3580static void release_global_block_rsv(struct btrfs_fs_info *fs_info)
3581{
3582 block_rsv_release_bytes(&fs_info->global_block_rsv, NULL, (u64)-1);
3583 WARN_ON(fs_info->delalloc_block_rsv.size > 0);
3584 WARN_ON(fs_info->delalloc_block_rsv.reserved > 0);
3585 WARN_ON(fs_info->trans_block_rsv.size > 0);
3586 WARN_ON(fs_info->trans_block_rsv.reserved > 0);
3587 WARN_ON(fs_info->chunk_block_rsv.size > 0);
3588 WARN_ON(fs_info->chunk_block_rsv.reserved > 0);
3481} 3589}
3482 3590
3483static u64 calc_trans_metadata_size(struct btrfs_root *root, int num_items) 3591static u64 calc_trans_metadata_size(struct btrfs_root *root, int num_items)
@@ -3826,6 +3934,8 @@ int btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
3826 fs_info->pinned_extents = &fs_info->freed_extents[0]; 3934 fs_info->pinned_extents = &fs_info->freed_extents[0];
3827 3935
3828 up_write(&fs_info->extent_commit_sem); 3936 up_write(&fs_info->extent_commit_sem);
3937
3938 update_global_block_rsv(fs_info);
3829 return 0; 3939 return 0;
3830} 3940}
3831 3941
@@ -4818,19 +4928,16 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
4818 printk(KERN_INFO "space_info has %llu free, is %sfull\n", 4928 printk(KERN_INFO "space_info has %llu free, is %sfull\n",
4819 (unsigned long long)(info->total_bytes - info->bytes_used - 4929 (unsigned long long)(info->total_bytes - info->bytes_used -
4820 info->bytes_pinned - info->bytes_reserved - 4930 info->bytes_pinned - info->bytes_reserved -
4821 info->bytes_super), 4931 info->bytes_readonly),
4822 (info->full) ? "" : "not "); 4932 (info->full) ? "" : "not ");
4823 printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu," 4933 printk(KERN_INFO "space_info total=%llu, used=%llu, pinned=%llu, "
4824 " may_use=%llu, used=%llu, root=%llu, super=%llu, reserved=%llu" 4934 "reserved=%llu, may_use=%llu, readonly=%llu\n",
4825 "\n",
4826 (unsigned long long)info->total_bytes, 4935 (unsigned long long)info->total_bytes,
4936 (unsigned long long)info->bytes_used,
4827 (unsigned long long)info->bytes_pinned, 4937 (unsigned long long)info->bytes_pinned,
4828 (unsigned long long)info->bytes_delalloc, 4938 (unsigned long long)info->bytes_reserved,
4829 (unsigned long long)info->bytes_may_use, 4939 (unsigned long long)info->bytes_may_use,
4830 (unsigned long long)info->bytes_used, 4940 (unsigned long long)info->bytes_readonly);
4831 (unsigned long long)info->bytes_root,
4832 (unsigned long long)info->bytes_super,
4833 (unsigned long long)info->bytes_reserved);
4834 spin_unlock(&info->lock); 4941 spin_unlock(&info->lock);
4835 4942
4836 if (!dump_block_groups) 4943 if (!dump_block_groups)
@@ -7727,6 +7834,8 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
7727 */ 7834 */
7728 synchronize_rcu(); 7835 synchronize_rcu();
7729 7836
7837 release_global_block_rsv(info);
7838
7730 while(!list_empty(&info->space_info)) { 7839 while(!list_empty(&info->space_info)) {
7731 space_info = list_entry(info->space_info.next, 7840 space_info = list_entry(info->space_info.next,
7732 struct btrfs_space_info, 7841 struct btrfs_space_info,