aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-10-02 19:11:56 -0400
committerChris Mason <chris.mason@oracle.com>2009-10-05 09:44:45 -0400
commit61d92c328c16419fc96dc50dd16f8b8c695409ec (patch)
treee9cd82eb56ff5f38f64d9f35229d15496e5d53de /fs/btrfs/disk-io.c
parentfbf190874407f23d2891b53ffdf7d3c6be8d47ff (diff)
Btrfs: fix deadlock on async thread startup
The btrfs async worker threads are used for a wide variety of things, including processing bio end_io functions. This means that when the endio threads aren't running, the rest of the FS isn't able to do the final processing required to clear PageWriteback. The endio threads also try to exit as they become idle and start more as the work piles up. The problem is that starting more threads means kthreadd may need to allocate ram, and that allocation may wait until the global number of writeback pages on the system is below a certain limit. The result of that throttling is that end IO threads wait on kthreadd, who is waiting on IO to end, which will never happen. This commit fixes the deadlock by handing off thread startup to a dedicated thread. It also fixes a bug where the on-demand thread creation was creating far too many threads because it didn't take into account threads being started by other procs. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c42
1 files changed, 23 insertions, 19 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 69dce50aabd2..9903f042765d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1746,21 +1746,22 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1746 err = -EINVAL; 1746 err = -EINVAL;
1747 goto fail_iput; 1747 goto fail_iput;
1748 } 1748 }
1749printk("thread pool is %d\n", fs_info->thread_pool_size); 1749
1750 /* 1750 btrfs_init_workers(&fs_info->generic_worker,
1751 * we need to start all the end_io workers up front because the 1751 "genwork", 1, NULL);
1752 * queue work function gets called at interrupt time, and so it 1752
1753 * cannot dynamically grow.
1754 */
1755 btrfs_init_workers(&fs_info->workers, "worker", 1753 btrfs_init_workers(&fs_info->workers, "worker",
1756 fs_info->thread_pool_size); 1754 fs_info->thread_pool_size,
1755 &fs_info->generic_worker);
1757 1756
1758 btrfs_init_workers(&fs_info->delalloc_workers, "delalloc", 1757 btrfs_init_workers(&fs_info->delalloc_workers, "delalloc",
1759 fs_info->thread_pool_size); 1758 fs_info->thread_pool_size,
1759 &fs_info->generic_worker);
1760 1760
1761 btrfs_init_workers(&fs_info->submit_workers, "submit", 1761 btrfs_init_workers(&fs_info->submit_workers, "submit",
1762 min_t(u64, fs_devices->num_devices, 1762 min_t(u64, fs_devices->num_devices,
1763 fs_info->thread_pool_size)); 1763 fs_info->thread_pool_size),
1764 &fs_info->generic_worker);
1764 1765
1765 /* a higher idle thresh on the submit workers makes it much more 1766 /* a higher idle thresh on the submit workers makes it much more
1766 * likely that bios will be send down in a sane order to the 1767 * likely that bios will be send down in a sane order to the
@@ -1774,15 +1775,20 @@ printk("thread pool is %d\n", fs_info->thread_pool_size);
1774 fs_info->delalloc_workers.idle_thresh = 2; 1775 fs_info->delalloc_workers.idle_thresh = 2;
1775 fs_info->delalloc_workers.ordered = 1; 1776 fs_info->delalloc_workers.ordered = 1;
1776 1777
1777 btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1); 1778 btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1,
1779 &fs_info->generic_worker);
1778 btrfs_init_workers(&fs_info->endio_workers, "endio", 1780 btrfs_init_workers(&fs_info->endio_workers, "endio",
1779 fs_info->thread_pool_size); 1781 fs_info->thread_pool_size,
1782 &fs_info->generic_worker);
1780 btrfs_init_workers(&fs_info->endio_meta_workers, "endio-meta", 1783 btrfs_init_workers(&fs_info->endio_meta_workers, "endio-meta",
1781 fs_info->thread_pool_size); 1784 fs_info->thread_pool_size,
1785 &fs_info->generic_worker);
1782 btrfs_init_workers(&fs_info->endio_meta_write_workers, 1786 btrfs_init_workers(&fs_info->endio_meta_write_workers,
1783 "endio-meta-write", fs_info->thread_pool_size); 1787 "endio-meta-write", fs_info->thread_pool_size,
1788 &fs_info->generic_worker);
1784 btrfs_init_workers(&fs_info->endio_write_workers, "endio-write", 1789 btrfs_init_workers(&fs_info->endio_write_workers, "endio-write",
1785 fs_info->thread_pool_size); 1790 fs_info->thread_pool_size,
1791 &fs_info->generic_worker);
1786 1792
1787 /* 1793 /*
1788 * endios are largely parallel and should have a very 1794 * endios are largely parallel and should have a very
@@ -1794,12 +1800,8 @@ printk("thread pool is %d\n", fs_info->thread_pool_size);
1794 fs_info->endio_write_workers.idle_thresh = 2; 1800 fs_info->endio_write_workers.idle_thresh = 2;
1795 fs_info->endio_meta_write_workers.idle_thresh = 2; 1801 fs_info->endio_meta_write_workers.idle_thresh = 2;
1796 1802
1797 fs_info->endio_workers.atomic_worker_start = 1;
1798 fs_info->endio_meta_workers.atomic_worker_start = 1;
1799 fs_info->endio_write_workers.atomic_worker_start = 1;
1800 fs_info->endio_meta_write_workers.atomic_worker_start = 1;
1801
1802 btrfs_start_workers(&fs_info->workers, 1); 1803 btrfs_start_workers(&fs_info->workers, 1);
1804 btrfs_start_workers(&fs_info->generic_worker, 1);
1803 btrfs_start_workers(&fs_info->submit_workers, 1); 1805 btrfs_start_workers(&fs_info->submit_workers, 1);
1804 btrfs_start_workers(&fs_info->delalloc_workers, 1); 1806 btrfs_start_workers(&fs_info->delalloc_workers, 1);
1805 btrfs_start_workers(&fs_info->fixup_workers, 1); 1807 btrfs_start_workers(&fs_info->fixup_workers, 1);
@@ -2012,6 +2014,7 @@ fail_chunk_root:
2012 free_extent_buffer(chunk_root->node); 2014 free_extent_buffer(chunk_root->node);
2013 free_extent_buffer(chunk_root->commit_root); 2015 free_extent_buffer(chunk_root->commit_root);
2014fail_sb_buffer: 2016fail_sb_buffer:
2017 btrfs_stop_workers(&fs_info->generic_worker);
2015 btrfs_stop_workers(&fs_info->fixup_workers); 2018 btrfs_stop_workers(&fs_info->fixup_workers);
2016 btrfs_stop_workers(&fs_info->delalloc_workers); 2019 btrfs_stop_workers(&fs_info->delalloc_workers);
2017 btrfs_stop_workers(&fs_info->workers); 2020 btrfs_stop_workers(&fs_info->workers);
@@ -2437,6 +2440,7 @@ int close_ctree(struct btrfs_root *root)
2437 2440
2438 iput(fs_info->btree_inode); 2441 iput(fs_info->btree_inode);
2439 2442
2443 btrfs_stop_workers(&fs_info->generic_worker);
2440 btrfs_stop_workers(&fs_info->fixup_workers); 2444 btrfs_stop_workers(&fs_info->fixup_workers);
2441 btrfs_stop_workers(&fs_info->delalloc_workers); 2445 btrfs_stop_workers(&fs_info->delalloc_workers);
2442 btrfs_stop_workers(&fs_info->workers); 2446 btrfs_stop_workers(&fs_info->workers);