aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2014-10-31 09:49:34 -0400
committerChris Mason <clm@fb.com>2014-11-20 20:20:04 -0500
commit633c0aad4c0243a506a3e8590551085ad78af82d (patch)
tree8cf20fe74c74e70409d4e60c80b65aab1c7f97b5
parentcd743fac42bbc2e6125ee14aaa8741601f92fe9a (diff)
Btrfs: move read only block groups onto their own list V2
Our gluster boxes were spending lots of time in statfs because our fs'es are huge. The problem is statfs loops through all of the block groups looking for read only block groups, and when you have several terabytes worth of data that ends up being a lot of block groups. Move the read only block groups onto a read only list and only proces that list in btrfs_account_ro_block_groups_free_space to reduce the amount of churn. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Reviewed-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/extent-tree.c36
2 files changed, 17 insertions, 23 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index b72b35867a7f..fa14081e3383 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1170,6 +1170,7 @@ struct btrfs_space_info {
1170 struct percpu_counter total_bytes_pinned; 1170 struct percpu_counter total_bytes_pinned;
1171 1171
1172 struct list_head list; 1172 struct list_head list;
1173 struct list_head ro_bgs;
1173 1174
1174 struct rw_semaphore groups_sem; 1175 struct rw_semaphore groups_sem;
1175 /* for block groups in our same type */ 1176 /* for block groups in our same type */
@@ -1305,6 +1306,9 @@ struct btrfs_block_group_cache {
1305 1306
1306 /* For delayed block group creation or deletion of empty block groups */ 1307 /* For delayed block group creation or deletion of empty block groups */
1307 struct list_head bg_list; 1308 struct list_head bg_list;
1309
1310 /* For read-only block groups */
1311 struct list_head ro_list;
1308}; 1312};
1309 1313
1310/* delayed seq elem */ 1314/* delayed seq elem */
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 47c1ba141082..cf3460e9b122 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3504,6 +3504,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
3504 found->chunk_alloc = 0; 3504 found->chunk_alloc = 0;
3505 found->flush = 0; 3505 found->flush = 0;
3506 init_waitqueue_head(&found->wait); 3506 init_waitqueue_head(&found->wait);
3507 INIT_LIST_HEAD(&found->ro_bgs);
3507 3508
3508 ret = kobject_init_and_add(&found->kobj, &space_info_ktype, 3509 ret = kobject_init_and_add(&found->kobj, &space_info_ktype,
3509 info->space_info_kobj, "%s", 3510 info->space_info_kobj, "%s",
@@ -8511,6 +8512,7 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache, int force)
8511 min_allocable_bytes <= sinfo->total_bytes) { 8512 min_allocable_bytes <= sinfo->total_bytes) {
8512 sinfo->bytes_readonly += num_bytes; 8513 sinfo->bytes_readonly += num_bytes;
8513 cache->ro = 1; 8514 cache->ro = 1;
8515 list_add_tail(&cache->ro_list, &sinfo->ro_bgs);
8514 ret = 0; 8516 ret = 0;
8515 } 8517 }
8516out: 8518out:
@@ -8565,15 +8567,20 @@ int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
8565 8567
8566/* 8568/*
8567 * helper to account the unused space of all the readonly block group in the 8569 * helper to account the unused space of all the readonly block group in the
8568 * list. takes mirrors into account. 8570 * space_info. takes mirrors into account.
8569 */ 8571 */
8570static u64 __btrfs_get_ro_block_group_free_space(struct list_head *groups_list) 8572u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo)
8571{ 8573{
8572 struct btrfs_block_group_cache *block_group; 8574 struct btrfs_block_group_cache *block_group;
8573 u64 free_bytes = 0; 8575 u64 free_bytes = 0;
8574 int factor; 8576 int factor;
8575 8577
8576 list_for_each_entry(block_group, groups_list, list) { 8578 /* It's df, we don't care if it's racey */
8579 if (list_empty(&sinfo->ro_bgs))
8580 return 0;
8581
8582 spin_lock(&sinfo->lock);
8583 list_for_each_entry(block_group, &sinfo->ro_bgs, ro_list) {
8577 spin_lock(&block_group->lock); 8584 spin_lock(&block_group->lock);
8578 8585
8579 if (!block_group->ro) { 8586 if (!block_group->ro) {
@@ -8594,26 +8601,6 @@ static u64 __btrfs_get_ro_block_group_free_space(struct list_head *groups_list)
8594 8601
8595 spin_unlock(&block_group->lock); 8602 spin_unlock(&block_group->lock);
8596 } 8603 }
8597
8598 return free_bytes;
8599}
8600
8601/*
8602 * helper to account the unused space of all the readonly block group in the
8603 * space_info. takes mirrors into account.
8604 */
8605u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo)
8606{
8607 int i;
8608 u64 free_bytes = 0;
8609
8610 spin_lock(&sinfo->lock);
8611
8612 for (i = 0; i < BTRFS_NR_RAID_TYPES; i++)
8613 if (!list_empty(&sinfo->block_groups[i]))
8614 free_bytes += __btrfs_get_ro_block_group_free_space(
8615 &sinfo->block_groups[i]);
8616
8617 spin_unlock(&sinfo->lock); 8604 spin_unlock(&sinfo->lock);
8618 8605
8619 return free_bytes; 8606 return free_bytes;
@@ -8633,6 +8620,7 @@ void btrfs_set_block_group_rw(struct btrfs_root *root,
8633 cache->bytes_super - btrfs_block_group_used(&cache->item); 8620 cache->bytes_super - btrfs_block_group_used(&cache->item);
8634 sinfo->bytes_readonly -= num_bytes; 8621 sinfo->bytes_readonly -= num_bytes;
8635 cache->ro = 0; 8622 cache->ro = 0;
8623 list_del_init(&cache->ro_list);
8636 spin_unlock(&cache->lock); 8624 spin_unlock(&cache->lock);
8637 spin_unlock(&sinfo->lock); 8625 spin_unlock(&sinfo->lock);
8638} 8626}
@@ -9002,6 +8990,7 @@ btrfs_create_block_group_cache(struct btrfs_root *root, u64 start, u64 size)
9002 INIT_LIST_HEAD(&cache->list); 8990 INIT_LIST_HEAD(&cache->list);
9003 INIT_LIST_HEAD(&cache->cluster_list); 8991 INIT_LIST_HEAD(&cache->cluster_list);
9004 INIT_LIST_HEAD(&cache->bg_list); 8992 INIT_LIST_HEAD(&cache->bg_list);
8993 INIT_LIST_HEAD(&cache->ro_list);
9005 btrfs_init_free_space_ctl(cache); 8994 btrfs_init_free_space_ctl(cache);
9006 8995
9007 return cache; 8996 return cache;
@@ -9411,6 +9400,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
9411 * are still on the list after taking the semaphore 9400 * are still on the list after taking the semaphore
9412 */ 9401 */
9413 list_del_init(&block_group->list); 9402 list_del_init(&block_group->list);
9403 list_del_init(&block_group->ro_list);
9414 if (list_empty(&block_group->space_info->block_groups[index])) { 9404 if (list_empty(&block_group->space_info->block_groups[index])) {
9415 kobj = block_group->space_info->block_group_kobjs[index]; 9405 kobj = block_group->space_info->block_group_kobjs[index];
9416 block_group->space_info->block_group_kobjs[index] = NULL; 9406 block_group->space_info->block_group_kobjs[index] = NULL;