aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2010-05-16 10:46:25 -0400
committerChris Mason <chris.mason@oracle.com>2010-05-25 10:34:48 -0400
commit424499dbd0c4d88742bf581b5714b27fb44b9fef (patch)
treef46a76c8f23c7045b18b31a9206d0b22f324aad1 /fs/btrfs
parentb742bb82f1676d50103ade0ba89bfb79debabe73 (diff)
Btrfs: Kill allocate_wait in space_info
We already have fs_info->chunk_mutex to avoid concurrent chunk creation. Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c132
2 files changed, 58 insertions, 76 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 6132088a577c..a68f34603b9d 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -701,9 +701,7 @@ struct btrfs_space_info {
701 struct list_head list; 701 struct list_head list;
702 702
703 /* for controlling how we free up space for allocations */ 703 /* for controlling how we free up space for allocations */
704 wait_queue_head_t allocate_wait;
705 wait_queue_head_t flush_wait; 704 wait_queue_head_t flush_wait;
706 int allocating_chunk;
707 int flushing; 705 int flushing;
708 706
709 /* for block groups in our same type */ 707 /* for block groups in our same type */
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f5db03669ead..2c95507c9abb 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -71,6 +71,9 @@ static int find_next_key(struct btrfs_path *path, int level,
71 struct btrfs_key *key); 71 struct btrfs_key *key);
72static void dump_space_info(struct btrfs_space_info *info, u64 bytes, 72static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
73 int dump_block_groups); 73 int dump_block_groups);
74static int maybe_allocate_chunk(struct btrfs_trans_handle *trans,
75 struct btrfs_root *root,
76 struct btrfs_space_info *sinfo, u64 num_bytes);
74 77
75static noinline int 78static noinline int
76block_group_cache_done(struct btrfs_block_group_cache *cache) 79block_group_cache_done(struct btrfs_block_group_cache *cache)
@@ -2691,7 +2694,6 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
2691 INIT_LIST_HEAD(&found->block_groups[i]); 2694 INIT_LIST_HEAD(&found->block_groups[i]);
2692 init_rwsem(&found->groups_sem); 2695 init_rwsem(&found->groups_sem);
2693 init_waitqueue_head(&found->flush_wait); 2696 init_waitqueue_head(&found->flush_wait);
2694 init_waitqueue_head(&found->allocate_wait);
2695 spin_lock_init(&found->lock); 2697 spin_lock_init(&found->lock);
2696 found->flags = flags & (BTRFS_BLOCK_GROUP_DATA | 2698 found->flags = flags & (BTRFS_BLOCK_GROUP_DATA |
2697 BTRFS_BLOCK_GROUP_SYSTEM | 2699 BTRFS_BLOCK_GROUP_SYSTEM |
@@ -3004,71 +3006,6 @@ flush:
3004 wake_up(&info->flush_wait); 3006 wake_up(&info->flush_wait);
3005} 3007}
3006 3008
3007static int maybe_allocate_chunk(struct btrfs_root *root,
3008 struct btrfs_space_info *info)
3009{
3010 struct btrfs_super_block *disk_super = &root->fs_info->super_copy;
3011 struct btrfs_trans_handle *trans;
3012 bool wait = false;
3013 int ret = 0;
3014 u64 min_metadata;
3015 u64 free_space;
3016
3017 free_space = btrfs_super_total_bytes(disk_super);
3018 /*
3019 * we allow the metadata to grow to a max of either 10gb or 5% of the
3020 * space in the volume.
3021 */
3022 min_metadata = min((u64)10 * 1024 * 1024 * 1024,
3023 div64_u64(free_space * 5, 100));
3024 if (info->total_bytes >= min_metadata) {
3025 spin_unlock(&info->lock);
3026 return 0;
3027 }
3028
3029 if (info->full) {
3030 spin_unlock(&info->lock);
3031 return 0;
3032 }
3033
3034 if (!info->allocating_chunk) {
3035 info->force_alloc = 1;
3036 info->allocating_chunk = 1;
3037 } else {
3038 wait = true;
3039 }
3040
3041 spin_unlock(&info->lock);
3042
3043 if (wait) {
3044 wait_event(info->allocate_wait,
3045 !info->allocating_chunk);
3046 return 1;
3047 }
3048
3049 trans = btrfs_start_transaction(root, 1);
3050 if (!trans) {
3051 ret = -ENOMEM;
3052 goto out;
3053 }
3054
3055 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
3056 4096 + 2 * 1024 * 1024,
3057 info->flags, 0);
3058 btrfs_end_transaction(trans, root);
3059 if (ret)
3060 goto out;
3061out:
3062 spin_lock(&info->lock);
3063 info->allocating_chunk = 0;
3064 spin_unlock(&info->lock);
3065 wake_up(&info->allocate_wait);
3066
3067 if (ret)
3068 return 0;
3069 return 1;
3070}
3071
3072/* 3009/*
3073 * Reserve metadata space for delalloc. 3010 * Reserve metadata space for delalloc.
3074 */ 3011 */
@@ -3109,7 +3046,8 @@ again:
3109 flushed++; 3046 flushed++;
3110 3047
3111 if (flushed == 1) { 3048 if (flushed == 1) {
3112 if (maybe_allocate_chunk(root, meta_sinfo)) 3049 if (maybe_allocate_chunk(NULL, root, meta_sinfo,
3050 num_bytes))
3113 goto again; 3051 goto again;
3114 flushed++; 3052 flushed++;
3115 } else { 3053 } else {
@@ -3224,7 +3162,8 @@ again:
3224 if (used > meta_sinfo->total_bytes) { 3162 if (used > meta_sinfo->total_bytes) {
3225 retries++; 3163 retries++;
3226 if (retries == 1) { 3164 if (retries == 1) {
3227 if (maybe_allocate_chunk(root, meta_sinfo)) 3165 if (maybe_allocate_chunk(NULL, root, meta_sinfo,
3166 num_bytes))
3228 goto again; 3167 goto again;
3229 retries++; 3168 retries++;
3230 } else { 3169 } else {
@@ -3421,13 +3360,28 @@ static void force_metadata_allocation(struct btrfs_fs_info *info)
3421 rcu_read_unlock(); 3360 rcu_read_unlock();
3422} 3361}
3423 3362
3363static int should_alloc_chunk(struct btrfs_space_info *sinfo,
3364 u64 alloc_bytes)
3365{
3366 u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly;
3367
3368 if (sinfo->bytes_used + sinfo->bytes_reserved +
3369 alloc_bytes + 256 * 1024 * 1024 < num_bytes)
3370 return 0;
3371
3372 if (sinfo->bytes_used + sinfo->bytes_reserved +
3373 alloc_bytes < div_factor(num_bytes, 8))
3374 return 0;
3375
3376 return 1;
3377}
3378
3424static int do_chunk_alloc(struct btrfs_trans_handle *trans, 3379static int do_chunk_alloc(struct btrfs_trans_handle *trans,
3425 struct btrfs_root *extent_root, u64 alloc_bytes, 3380 struct btrfs_root *extent_root, u64 alloc_bytes,
3426 u64 flags, int force) 3381 u64 flags, int force)
3427{ 3382{
3428 struct btrfs_space_info *space_info; 3383 struct btrfs_space_info *space_info;
3429 struct btrfs_fs_info *fs_info = extent_root->fs_info; 3384 struct btrfs_fs_info *fs_info = extent_root->fs_info;
3430 u64 thresh;
3431 int ret = 0; 3385 int ret = 0;
3432 3386
3433 mutex_lock(&fs_info->chunk_mutex); 3387 mutex_lock(&fs_info->chunk_mutex);
@@ -3450,11 +3404,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
3450 goto out; 3404 goto out;
3451 } 3405 }
3452 3406
3453 thresh = space_info->total_bytes - space_info->bytes_readonly; 3407 if (!force && !should_alloc_chunk(space_info, alloc_bytes)) {
3454 thresh = div_factor(thresh, 8);
3455 if (!force &&
3456 (space_info->bytes_used + space_info->bytes_pinned +
3457 space_info->bytes_reserved + alloc_bytes) < thresh) {
3458 spin_unlock(&space_info->lock); 3408 spin_unlock(&space_info->lock);
3459 goto out; 3409 goto out;
3460 } 3410 }
@@ -3476,6 +3426,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
3476 spin_lock(&space_info->lock); 3426 spin_lock(&space_info->lock);
3477 if (ret) 3427 if (ret)
3478 space_info->full = 1; 3428 space_info->full = 1;
3429 else
3430 ret = 1;
3479 space_info->force_alloc = 0; 3431 space_info->force_alloc = 0;
3480 spin_unlock(&space_info->lock); 3432 spin_unlock(&space_info->lock);
3481out: 3433out:
@@ -3483,6 +3435,38 @@ out:
3483 return ret; 3435 return ret;
3484} 3436}
3485 3437
3438static int maybe_allocate_chunk(struct btrfs_trans_handle *trans,
3439 struct btrfs_root *root,
3440 struct btrfs_space_info *sinfo, u64 num_bytes)
3441{
3442 int ret;
3443 int end_trans = 0;
3444
3445 if (sinfo->full)
3446 return 0;
3447
3448 spin_lock(&sinfo->lock);
3449 ret = should_alloc_chunk(sinfo, num_bytes + 2 * 1024 * 1024);
3450 spin_unlock(&sinfo->lock);
3451 if (!ret)
3452 return 0;
3453
3454 if (!trans) {
3455 trans = btrfs_join_transaction(root, 1);
3456 BUG_ON(IS_ERR(trans));
3457 end_trans = 1;
3458 }
3459
3460 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
3461 num_bytes + 2 * 1024 * 1024,
3462 get_alloc_profile(root, sinfo->flags), 0);
3463
3464 if (end_trans)
3465 btrfs_end_transaction(trans, root);
3466
3467 return ret == 1 ? 1 : 0;
3468}
3469
3486static int update_block_group(struct btrfs_trans_handle *trans, 3470static int update_block_group(struct btrfs_trans_handle *trans,
3487 struct btrfs_root *root, 3471 struct btrfs_root *root,
3488 u64 bytenr, u64 num_bytes, int alloc, 3472 u64 bytenr, u64 num_bytes, int alloc,