Commit cb03c743 authored by Chris Mason's avatar Chris Mason

Btrfs: Change the congestion functions to meter the number of async submits as well

The async submit workqueue was absorbing too many requests, leading to long
stalls where the async submitters were stalling.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 211c17f5
...@@ -522,6 +522,7 @@ struct btrfs_fs_info { ...@@ -522,6 +522,7 @@ struct btrfs_fs_info {
struct work_struct async_submit_work; struct work_struct async_submit_work;
spinlock_t end_io_work_lock; spinlock_t end_io_work_lock;
spinlock_t async_submit_work_lock; spinlock_t async_submit_work_lock;
atomic_t nr_async_submits;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
struct work_struct trans_work; struct work_struct trans_work;
......
...@@ -453,6 +453,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, ...@@ -453,6 +453,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
spin_lock(&fs_info->async_submit_work_lock); spin_lock(&fs_info->async_submit_work_lock);
list_add_tail(&async->list, &fs_info->async_submit_work_list); list_add_tail(&async->list, &fs_info->async_submit_work_list);
atomic_inc(&fs_info->nr_async_submits);
spin_unlock(&fs_info->async_submit_work_lock); spin_unlock(&fs_info->async_submit_work_lock);
queue_work(async_submit_workqueue, &fs_info->async_submit_work); queue_work(async_submit_workqueue, &fs_info->async_submit_work);
...@@ -906,10 +907,16 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) ...@@ -906,10 +907,16 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
{ {
struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data; struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data;
int ret = 0; int ret = 0;
int limit = 256 * info->fs_devices->open_devices;
struct list_head *cur; struct list_head *cur;
struct btrfs_device *device; struct btrfs_device *device;
struct backing_dev_info *bdi; struct backing_dev_info *bdi;
if ((bdi_bits & (1 << BDI_write_congested)) &&
atomic_read(&info->nr_async_submits) > limit) {
return 1;
}
list_for_each(cur, &info->fs_devices->devices) { list_for_each(cur, &info->fs_devices->devices) {
device = list_entry(cur, struct btrfs_device, dev_list); device = list_entry(cur, struct btrfs_device, dev_list);
if (!device->bdev) if (!device->bdev)
...@@ -1117,6 +1124,7 @@ static void btrfs_async_submit_work(struct work_struct *work) ...@@ -1117,6 +1124,7 @@ static void btrfs_async_submit_work(struct work_struct *work)
} }
next = fs_info->async_submit_work_list.next; next = fs_info->async_submit_work_list.next;
list_del(next); list_del(next);
atomic_dec(&fs_info->nr_async_submits);
spin_unlock(&fs_info->async_submit_work_lock); spin_unlock(&fs_info->async_submit_work_lock);
async = list_entry(next, struct async_submit_bio, list); async = list_entry(next, struct async_submit_bio, list);
...@@ -1179,6 +1187,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1179,6 +1187,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
INIT_LIST_HEAD(&fs_info->space_info); INIT_LIST_HEAD(&fs_info->space_info);
btrfs_mapping_init(&fs_info->mapping_tree); btrfs_mapping_init(&fs_info->mapping_tree);
atomic_set(&fs_info->nr_async_submits, 0);
fs_info->sb = sb; fs_info->sb = sb;
fs_info->max_extent = (u64)-1; fs_info->max_extent = (u64)-1;
fs_info->max_inline = 8192 * 1024; fs_info->max_inline = 8192 * 1024;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment