aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-01-29 05:10:51 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 12:59:05 -0500
commit963d678b0f7649300e3a67f2513ca9d830c6e303 (patch)
tree4f7568f541891a7bbe8b279c98d21aec1cabe06f
parente2d845211eda9cf296e8edf6724b3d541f4fbfd5 (diff)
Btrfs: use percpu counter for fs_info->delalloc_bytes
fs_info->delalloc_bytes is accessed very frequently, so use percpu counter instead of the u64 variant for it to reduce the lock contention. This patch also fixed the problem that we access the variant without the lock protection.At worst, we would not flush the delalloc inodes, and just return ENOSPC error when we still have some free space in the fs. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
-rw-r--r--fs/btrfs/ctree.h7
-rw-r--r--fs/btrfs/disk-io.c18
-rw-r--r--fs/btrfs/extent-tree.c6
-rw-r--r--fs/btrfs/inode.c6
4 files changed, 26 insertions, 11 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 4c476281b66b..50def99f5379 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1392,6 +1392,7 @@ struct btrfs_fs_info {
1392 */ 1392 */
1393 struct list_head ordered_extents; 1393 struct list_head ordered_extents;
1394 1394
1395 spinlock_t delalloc_lock;
1395 /* 1396 /*
1396 * all of the inodes that have delalloc bytes. It is possible for 1397 * all of the inodes that have delalloc bytes. It is possible for
1397 * this list to be empty even when there is still dirty data=ordered 1398 * this list to be empty even when there is still dirty data=ordered
@@ -1452,7 +1453,10 @@ struct btrfs_fs_info {
1452 1453
1453 /* used to keep from writing metadata until there is a nice batch */ 1454 /* used to keep from writing metadata until there is a nice batch */
1454 struct percpu_counter dirty_metadata_bytes; 1455 struct percpu_counter dirty_metadata_bytes;
1456 struct percpu_counter delalloc_bytes;
1455 s32 dirty_metadata_batch; 1457 s32 dirty_metadata_batch;
1458 s32 delalloc_batch;
1459
1456 struct list_head dirty_cowonly_roots; 1460 struct list_head dirty_cowonly_roots;
1457 1461
1458 struct btrfs_fs_devices *fs_devices; 1462 struct btrfs_fs_devices *fs_devices;
@@ -1468,9 +1472,6 @@ struct btrfs_fs_info {
1468 1472
1469 struct reloc_control *reloc_ctl; 1473 struct reloc_control *reloc_ctl;
1470 1474
1471 spinlock_t delalloc_lock;
1472 u64 delalloc_bytes;
1473
1474 /* data_alloc_cluster is only used in ssd mode */ 1475 /* data_alloc_cluster is only used in ssd mode */
1475 struct btrfs_free_cluster data_alloc_cluster; 1476 struct btrfs_free_cluster data_alloc_cluster;
1476 1477
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 34ace168eebc..2c9498aefe86 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2010,10 +2010,16 @@ int open_ctree(struct super_block *sb,
2010 fs_info->dirty_metadata_batch = PAGE_CACHE_SIZE * 2010 fs_info->dirty_metadata_batch = PAGE_CACHE_SIZE *
2011 (1 + ilog2(nr_cpu_ids)); 2011 (1 + ilog2(nr_cpu_ids));
2012 2012
2013 ret = percpu_counter_init(&fs_info->delalloc_bytes, 0);
2014 if (ret) {
2015 err = ret;
2016 goto fail_dirty_metadata_bytes;
2017 }
2018
2013 fs_info->btree_inode = new_inode(sb); 2019 fs_info->btree_inode = new_inode(sb);
2014 if (!fs_info->btree_inode) { 2020 if (!fs_info->btree_inode) {
2015 err = -ENOMEM; 2021 err = -ENOMEM;
2016 goto fail_dirty_metadata_bytes; 2022 goto fail_delalloc_bytes;
2017 } 2023 }
2018 2024
2019 mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); 2025 mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
@@ -2269,6 +2275,7 @@ int open_ctree(struct super_block *sb,
2269 sectorsize = btrfs_super_sectorsize(disk_super); 2275 sectorsize = btrfs_super_sectorsize(disk_super);
2270 stripesize = btrfs_super_stripesize(disk_super); 2276 stripesize = btrfs_super_stripesize(disk_super);
2271 fs_info->dirty_metadata_batch = leafsize * (1 + ilog2(nr_cpu_ids)); 2277 fs_info->dirty_metadata_batch = leafsize * (1 + ilog2(nr_cpu_ids));
2278 fs_info->delalloc_batch = sectorsize * 512 * (1 + ilog2(nr_cpu_ids));
2272 2279
2273 /* 2280 /*
2274 * mixed block groups end up with duplicate but slightly offset 2281 * mixed block groups end up with duplicate but slightly offset
@@ -2731,6 +2738,8 @@ fail_iput:
2731 2738
2732 invalidate_inode_pages2(fs_info->btree_inode->i_mapping); 2739 invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
2733 iput(fs_info->btree_inode); 2740 iput(fs_info->btree_inode);
2741fail_delalloc_bytes:
2742 percpu_counter_destroy(&fs_info->delalloc_bytes);
2734fail_dirty_metadata_bytes: 2743fail_dirty_metadata_bytes:
2735 percpu_counter_destroy(&fs_info->dirty_metadata_bytes); 2744 percpu_counter_destroy(&fs_info->dirty_metadata_bytes);
2736fail_bdi: 2745fail_bdi:
@@ -3362,9 +3371,9 @@ int close_ctree(struct btrfs_root *root)
3362 3371
3363 btrfs_free_qgroup_config(root->fs_info); 3372 btrfs_free_qgroup_config(root->fs_info);
3364 3373
3365 if (fs_info->delalloc_bytes) { 3374 if (percpu_counter_sum(&fs_info->delalloc_bytes)) {
3366 printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n", 3375 printk(KERN_INFO "btrfs: at unmount delalloc count %lld\n",
3367 (unsigned long long)fs_info->delalloc_bytes); 3376 percpu_counter_sum(&fs_info->delalloc_bytes));
3368 } 3377 }
3369 3378
3370 free_extent_buffer(fs_info->extent_root->node); 3379 free_extent_buffer(fs_info->extent_root->node);
@@ -3412,6 +3421,7 @@ int close_ctree(struct btrfs_root *root)
3412 btrfs_mapping_tree_free(&fs_info->mapping_tree); 3421 btrfs_mapping_tree_free(&fs_info->mapping_tree);
3413 3422
3414 percpu_counter_destroy(&fs_info->dirty_metadata_bytes); 3423 percpu_counter_destroy(&fs_info->dirty_metadata_bytes);
3424 percpu_counter_destroy(&fs_info->delalloc_bytes);
3415 bdi_destroy(&fs_info->bdi); 3425 bdi_destroy(&fs_info->bdi);
3416 cleanup_srcu_struct(&fs_info->subvol_srcu); 3426 cleanup_srcu_struct(&fs_info->subvol_srcu);
3417 3427
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 174c4d5c692c..115d1646bf50 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3760,7 +3760,8 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
3760 space_info = block_rsv->space_info; 3760 space_info = block_rsv->space_info;
3761 3761
3762 smp_mb(); 3762 smp_mb();
3763 delalloc_bytes = root->fs_info->delalloc_bytes; 3763 delalloc_bytes = percpu_counter_sum_positive(
3764 &root->fs_info->delalloc_bytes);
3764 if (delalloc_bytes == 0) { 3765 if (delalloc_bytes == 0) {
3765 if (trans) 3766 if (trans)
3766 return; 3767 return;
@@ -3799,7 +3800,8 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
3799 break; 3800 break;
3800 } 3801 }
3801 smp_mb(); 3802 smp_mb();
3802 delalloc_bytes = root->fs_info->delalloc_bytes; 3803 delalloc_bytes = percpu_counter_sum_positive(
3804 &root->fs_info->delalloc_bytes);
3803 } 3805 }
3804} 3806}
3805 3807
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fc8aa8bf80a1..24c0b7805fe1 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1516,7 +1516,8 @@ static void btrfs_set_bit_hook(struct inode *inode,
1516 1516
1517 spin_lock(&root->fs_info->delalloc_lock); 1517 spin_lock(&root->fs_info->delalloc_lock);
1518 BTRFS_I(inode)->delalloc_bytes += len; 1518 BTRFS_I(inode)->delalloc_bytes += len;
1519 root->fs_info->delalloc_bytes += len; 1519 __percpu_counter_add(&root->fs_info->delalloc_bytes, len,
1520 root->fs_info->delalloc_batch);
1520 if (do_list && list_empty(&BTRFS_I(inode)->delalloc_inodes)) { 1521 if (do_list && list_empty(&BTRFS_I(inode)->delalloc_inodes)) {
1521 list_add_tail(&BTRFS_I(inode)->delalloc_inodes, 1522 list_add_tail(&BTRFS_I(inode)->delalloc_inodes,
1522 &root->fs_info->delalloc_inodes); 1523 &root->fs_info->delalloc_inodes);
@@ -1557,7 +1558,8 @@ static void btrfs_clear_bit_hook(struct inode *inode,
1557 btrfs_free_reserved_data_space(inode, len); 1558 btrfs_free_reserved_data_space(inode, len);
1558 1559
1559 spin_lock(&root->fs_info->delalloc_lock); 1560 spin_lock(&root->fs_info->delalloc_lock);
1560 root->fs_info->delalloc_bytes -= len; 1561 __percpu_counter_add(&root->fs_info->delalloc_bytes, -len,
1562 root->fs_info->delalloc_batch);
1561 BTRFS_I(inode)->delalloc_bytes -= len; 1563 BTRFS_I(inode)->delalloc_bytes -= len;
1562 1564
1563 if (do_list && BTRFS_I(inode)->delalloc_bytes == 0 && 1565 if (do_list && BTRFS_I(inode)->delalloc_bytes == 0 &&