diff options
author | Dave Chinner <david@fromorbit.com> | 2009-04-06 12:42:11 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@brick.lst.de> | 2009-04-06 12:42:11 -0400 |
commit | c626d174cfe38e7f0545d074c299527892cd8c45 (patch) | |
tree | 8f7dfa34a77bc415d9dc604d79fbae98ffe47a14 /fs/xfs/linux-2.6/xfs_buf.c | |
parent | 705db3fd4660174a27418bbcb874d209a76044eb (diff) |
xfs: prevent unwritten extent conversion from blocking I/O completion
Unwritten extent conversion can recurse back into the filesystem due
to memory allocation. Memory reclaim requires I/O completions to be
processed to allow the callers to make progress. If the I/O
completion workqueue thread is doing the recursion, then we have a
deadlock situation.
Move unwritten extent completion into it's own workqueue so it
doesn't block I/O completions for normal delayed allocation or
overwrite data.
Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_buf.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index aa1016bb9134..e28800a9f2b5 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -51,6 +51,7 @@ static struct shrinker xfs_buf_shake = { | |||
51 | 51 | ||
52 | static struct workqueue_struct *xfslogd_workqueue; | 52 | static struct workqueue_struct *xfslogd_workqueue; |
53 | struct workqueue_struct *xfsdatad_workqueue; | 53 | struct workqueue_struct *xfsdatad_workqueue; |
54 | struct workqueue_struct *xfsconvertd_workqueue; | ||
54 | 55 | ||
55 | #ifdef XFS_BUF_TRACE | 56 | #ifdef XFS_BUF_TRACE |
56 | void | 57 | void |
@@ -1775,6 +1776,7 @@ xfs_flush_buftarg( | |||
1775 | xfs_buf_t *bp, *n; | 1776 | xfs_buf_t *bp, *n; |
1776 | int pincount = 0; | 1777 | int pincount = 0; |
1777 | 1778 | ||
1779 | xfs_buf_runall_queues(xfsconvertd_workqueue); | ||
1778 | xfs_buf_runall_queues(xfsdatad_workqueue); | 1780 | xfs_buf_runall_queues(xfsdatad_workqueue); |
1779 | xfs_buf_runall_queues(xfslogd_workqueue); | 1781 | xfs_buf_runall_queues(xfslogd_workqueue); |
1780 | 1782 | ||
@@ -1831,9 +1833,15 @@ xfs_buf_init(void) | |||
1831 | if (!xfsdatad_workqueue) | 1833 | if (!xfsdatad_workqueue) |
1832 | goto out_destroy_xfslogd_workqueue; | 1834 | goto out_destroy_xfslogd_workqueue; |
1833 | 1835 | ||
1836 | xfsconvertd_workqueue = create_workqueue("xfsconvertd"); | ||
1837 | if (!xfsconvertd_workqueue) | ||
1838 | goto out_destroy_xfsdatad_workqueue; | ||
1839 | |||
1834 | register_shrinker(&xfs_buf_shake); | 1840 | register_shrinker(&xfs_buf_shake); |
1835 | return 0; | 1841 | return 0; |
1836 | 1842 | ||
1843 | out_destroy_xfsdatad_workqueue: | ||
1844 | destroy_workqueue(xfsdatad_workqueue); | ||
1837 | out_destroy_xfslogd_workqueue: | 1845 | out_destroy_xfslogd_workqueue: |
1838 | destroy_workqueue(xfslogd_workqueue); | 1846 | destroy_workqueue(xfslogd_workqueue); |
1839 | out_free_buf_zone: | 1847 | out_free_buf_zone: |
@@ -1849,6 +1857,7 @@ void | |||
1849 | xfs_buf_terminate(void) | 1857 | xfs_buf_terminate(void) |
1850 | { | 1858 | { |
1851 | unregister_shrinker(&xfs_buf_shake); | 1859 | unregister_shrinker(&xfs_buf_shake); |
1860 | destroy_workqueue(xfsconvertd_workqueue); | ||
1852 | destroy_workqueue(xfsdatad_workqueue); | 1861 | destroy_workqueue(xfsdatad_workqueue); |
1853 | destroy_workqueue(xfslogd_workqueue); | 1862 | destroy_workqueue(xfslogd_workqueue); |
1854 | kmem_zone_destroy(xfs_buf_zone); | 1863 | kmem_zone_destroy(xfs_buf_zone); |