aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2014-11-03 08:56:50 -0500
committerChris Mason <clm@fb.com>2014-11-20 20:20:05 -0500
commit7e33fd993a74b3fda39c756803ba8b24bef72df5 (patch)
treeff2ddc1af7bc7e6f4949ca70519cccf7964c9ae8 /fs
parent633c0aad4c0243a506a3e8590551085ad78af82d (diff)
Btrfs: don't take the chunk_mutex/dev_list mutex in statfs V2
Our gluster boxes get several thousand statfs() calls per second, which begins to suck hardcore with all of the lock contention on the chunk mutex and dev list mutex. We don't really need to hold these things, if we have transient weirdness with statfs() because of the chunk allocator we don't care, so remove this locking. We still need the dev_list lock if you mount with -o alloc_start however, which is a good argument for nuking that thing from orbit, but that's a patch for another day. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/super.c72
1 files changed, 47 insertions, 25 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 54bd91ece35b..dc337d14ef5c 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1644,8 +1644,20 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
1644 int i = 0, nr_devices; 1644 int i = 0, nr_devices;
1645 int ret; 1645 int ret;
1646 1646
1647 /*
1648 * We aren't under the device list lock, so this is racey-ish, but good
1649 * enough for our purposes.
1650 */
1647 nr_devices = fs_info->fs_devices->open_devices; 1651 nr_devices = fs_info->fs_devices->open_devices;
1648 BUG_ON(!nr_devices); 1652 if (!nr_devices) {
1653 smp_mb();
1654 nr_devices = fs_info->fs_devices->open_devices;
1655 ASSERT(nr_devices);
1656 if (!nr_devices) {
1657 *free_bytes = 0;
1658 return 0;
1659 }
1660 }
1649 1661
1650 devices_info = kmalloc_array(nr_devices, sizeof(*devices_info), 1662 devices_info = kmalloc_array(nr_devices, sizeof(*devices_info),
1651 GFP_NOFS); 1663 GFP_NOFS);
@@ -1670,11 +1682,17 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
1670 else 1682 else
1671 min_stripe_size = BTRFS_STRIPE_LEN; 1683 min_stripe_size = BTRFS_STRIPE_LEN;
1672 1684
1673 list_for_each_entry(device, &fs_devices->devices, dev_list) { 1685 if (fs_info->alloc_start)
1686 mutex_lock(&fs_devices->device_list_mutex);
1687 rcu_read_lock();
1688 list_for_each_entry_rcu(device, &fs_devices->devices, dev_list) {
1674 if (!device->in_fs_metadata || !device->bdev || 1689 if (!device->in_fs_metadata || !device->bdev ||
1675 device->is_tgtdev_for_dev_replace) 1690 device->is_tgtdev_for_dev_replace)
1676 continue; 1691 continue;
1677 1692
1693 if (i >= nr_devices)
1694 break;
1695
1678 avail_space = device->total_bytes - device->bytes_used; 1696 avail_space = device->total_bytes - device->bytes_used;
1679 1697
1680 /* align with stripe_len */ 1698 /* align with stripe_len */
@@ -1689,24 +1707,32 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
1689 skip_space = 1024 * 1024; 1707 skip_space = 1024 * 1024;
1690 1708
1691 /* user can set the offset in fs_info->alloc_start. */ 1709 /* user can set the offset in fs_info->alloc_start. */
1692 if (fs_info->alloc_start + BTRFS_STRIPE_LEN <= 1710 if (fs_info->alloc_start &&
1693 device->total_bytes) 1711 fs_info->alloc_start + BTRFS_STRIPE_LEN <=
1712 device->total_bytes) {
1713 rcu_read_unlock();
1694 skip_space = max(fs_info->alloc_start, skip_space); 1714 skip_space = max(fs_info->alloc_start, skip_space);
1695 1715
1696 /* 1716 /*
1697 * btrfs can not use the free space in [0, skip_space - 1], 1717 * btrfs can not use the free space in
1698 * we must subtract it from the total. In order to implement 1718 * [0, skip_space - 1], we must subtract it from the
1699 * it, we account the used space in this range first. 1719 * total. In order to implement it, we account the used
1700 */ 1720 * space in this range first.
1701 ret = btrfs_account_dev_extents_size(device, 0, skip_space - 1, 1721 */
1702 &used_space); 1722 ret = btrfs_account_dev_extents_size(device, 0,
1703 if (ret) { 1723 skip_space - 1,
1704 kfree(devices_info); 1724 &used_space);
1705 return ret; 1725 if (ret) {
1706 } 1726 kfree(devices_info);
1727 mutex_unlock(&fs_devices->device_list_mutex);
1728 return ret;
1729 }
1707 1730
1708 /* calc the free space in [0, skip_space - 1] */ 1731 rcu_read_lock();
1709 skip_space -= used_space; 1732
1733 /* calc the free space in [0, skip_space - 1] */
1734 skip_space -= used_space;
1735 }
1710 1736
1711 /* 1737 /*
1712 * we can use the free space in [0, skip_space - 1], subtract 1738 * we can use the free space in [0, skip_space - 1], subtract
@@ -1725,6 +1751,9 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
1725 1751
1726 i++; 1752 i++;
1727 } 1753 }
1754 rcu_read_unlock();
1755 if (fs_info->alloc_start)
1756 mutex_unlock(&fs_devices->device_list_mutex);
1728 1757
1729 nr_devices = i; 1758 nr_devices = i;
1730 1759
@@ -1787,8 +1816,6 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1787 * holding chunk_muext to avoid allocating new chunks, holding 1816 * holding chunk_muext to avoid allocating new chunks, holding
1788 * device_list_mutex to avoid the device being removed 1817 * device_list_mutex to avoid the device being removed
1789 */ 1818 */
1790 mutex_lock(&fs_info->fs_devices->device_list_mutex);
1791 mutex_lock(&fs_info->chunk_mutex);
1792 rcu_read_lock(); 1819 rcu_read_lock();
1793 list_for_each_entry_rcu(found, head, list) { 1820 list_for_each_entry_rcu(found, head, list) {
1794 if (found->flags & BTRFS_BLOCK_GROUP_DATA) { 1821 if (found->flags & BTRFS_BLOCK_GROUP_DATA) {
@@ -1826,15 +1853,10 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1826 1853
1827 buf->f_bavail = total_free_data; 1854 buf->f_bavail = total_free_data;
1828 ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data); 1855 ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data);
1829 if (ret) { 1856 if (ret)
1830 mutex_unlock(&fs_info->chunk_mutex);
1831 mutex_unlock(&fs_info->fs_devices->device_list_mutex);
1832 return ret; 1857 return ret;
1833 }
1834 buf->f_bavail += div_u64(total_free_data, factor); 1858 buf->f_bavail += div_u64(total_free_data, factor);
1835 buf->f_bavail = buf->f_bavail >> bits; 1859 buf->f_bavail = buf->f_bavail >> bits;
1836 mutex_unlock(&fs_info->chunk_mutex);
1837 mutex_unlock(&fs_info->fs_devices->device_list_mutex);
1838 1860
1839 buf->f_type = BTRFS_SUPER_MAGIC; 1861 buf->f_type = BTRFS_SUPER_MAGIC;
1840 buf->f_bsize = dentry->d_sb->s_blocksize; 1862 buf->f_bsize = dentry->d_sb->s_blocksize;