diff options
| -rw-r--r-- | fs/xfs/xfs_buf.c | 60 |
1 files changed, 35 insertions, 25 deletions
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index e71cfbd5acb3..efa2a734268f 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
| @@ -1774,18 +1774,33 @@ xfs_buf_cmp( | |||
| 1774 | return 0; | 1774 | return 0; |
| 1775 | } | 1775 | } |
| 1776 | 1776 | ||
| 1777 | /* | ||
| 1778 | * submit buffers for write. | ||
| 1779 | * | ||
| 1780 | * When we have a large buffer list, we do not want to hold all the buffers | ||
| 1781 | * locked while we block on the request queue waiting for IO dispatch. To avoid | ||
| 1782 | * this problem, we lock and submit buffers in groups of 50, thereby minimising | ||
| 1783 | * the lock hold times for lists which may contain thousands of objects. | ||
| 1784 | * | ||
| 1785 | * To do this, we sort the buffer list before we walk the list to lock and | ||
| 1786 | * submit buffers, and we plug and unplug around each group of buffers we | ||
| 1787 | * submit. | ||
| 1788 | */ | ||
| 1777 | static int | 1789 | static int |
| 1778 | __xfs_buf_delwri_submit( | 1790 | xfs_buf_delwri_submit_buffers( |
| 1779 | struct list_head *buffer_list, | 1791 | struct list_head *buffer_list, |
| 1780 | struct list_head *io_list, | 1792 | struct list_head *wait_list) |
| 1781 | bool wait) | ||
| 1782 | { | 1793 | { |
| 1783 | struct blk_plug plug; | ||
| 1784 | struct xfs_buf *bp, *n; | 1794 | struct xfs_buf *bp, *n; |
| 1795 | LIST_HEAD (submit_list); | ||
| 1785 | int pinned = 0; | 1796 | int pinned = 0; |
| 1797 | struct blk_plug plug; | ||
| 1798 | |||
| 1799 | list_sort(NULL, buffer_list, xfs_buf_cmp); | ||
| 1786 | 1800 | ||
| 1801 | blk_start_plug(&plug); | ||
| 1787 | list_for_each_entry_safe(bp, n, buffer_list, b_list) { | 1802 | list_for_each_entry_safe(bp, n, buffer_list, b_list) { |
| 1788 | if (!wait) { | 1803 | if (!wait_list) { |
| 1789 | if (xfs_buf_ispinned(bp)) { | 1804 | if (xfs_buf_ispinned(bp)) { |
| 1790 | pinned++; | 1805 | pinned++; |
| 1791 | continue; | 1806 | continue; |
| @@ -1808,25 +1823,21 @@ __xfs_buf_delwri_submit( | |||
| 1808 | continue; | 1823 | continue; |
| 1809 | } | 1824 | } |
| 1810 | 1825 | ||
| 1811 | list_move_tail(&bp->b_list, io_list); | ||
| 1812 | trace_xfs_buf_delwri_split(bp, _RET_IP_); | 1826 | trace_xfs_buf_delwri_split(bp, _RET_IP_); |
| 1813 | } | ||
| 1814 | |||
| 1815 | list_sort(NULL, io_list, xfs_buf_cmp); | ||
| 1816 | |||
| 1817 | blk_start_plug(&plug); | ||
| 1818 | list_for_each_entry_safe(bp, n, io_list, b_list) { | ||
| 1819 | bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL); | ||
| 1820 | bp->b_flags |= XBF_WRITE | XBF_ASYNC; | ||
| 1821 | 1827 | ||
| 1822 | /* | 1828 | /* |
| 1823 | * we do all Io submission async. This means if we need to wait | 1829 | * We do all IO submission async. This means if we need |
| 1824 | * for IO completion we need to take an extra reference so the | 1830 | * to wait for IO completion we need to take an extra |
| 1825 | * buffer is still valid on the other side. | 1831 | * reference so the buffer is still valid on the other |
| 1832 | * side. We need to move the buffer onto the io_list | ||
| 1833 | * at this point so the caller can still access it. | ||
| 1826 | */ | 1834 | */ |
| 1827 | if (wait) | 1835 | bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL); |
| 1836 | bp->b_flags |= XBF_WRITE | XBF_ASYNC; | ||
| 1837 | if (wait_list) { | ||
| 1828 | xfs_buf_hold(bp); | 1838 | xfs_buf_hold(bp); |
| 1829 | else | 1839 | list_move_tail(&bp->b_list, wait_list); |
| 1840 | } else | ||
| 1830 | list_del_init(&bp->b_list); | 1841 | list_del_init(&bp->b_list); |
| 1831 | 1842 | ||
| 1832 | xfs_buf_submit(bp); | 1843 | xfs_buf_submit(bp); |
| @@ -1849,8 +1860,7 @@ int | |||
| 1849 | xfs_buf_delwri_submit_nowait( | 1860 | xfs_buf_delwri_submit_nowait( |
| 1850 | struct list_head *buffer_list) | 1861 | struct list_head *buffer_list) |
| 1851 | { | 1862 | { |
| 1852 | LIST_HEAD (io_list); | 1863 | return xfs_buf_delwri_submit_buffers(buffer_list, NULL); |
| 1853 | return __xfs_buf_delwri_submit(buffer_list, &io_list, false); | ||
| 1854 | } | 1864 | } |
| 1855 | 1865 | ||
| 1856 | /* | 1866 | /* |
| @@ -1865,15 +1875,15 @@ int | |||
| 1865 | xfs_buf_delwri_submit( | 1875 | xfs_buf_delwri_submit( |
| 1866 | struct list_head *buffer_list) | 1876 | struct list_head *buffer_list) |
| 1867 | { | 1877 | { |
| 1868 | LIST_HEAD (io_list); | 1878 | LIST_HEAD (wait_list); |
| 1869 | int error = 0, error2; | 1879 | int error = 0, error2; |
| 1870 | struct xfs_buf *bp; | 1880 | struct xfs_buf *bp; |
| 1871 | 1881 | ||
| 1872 | __xfs_buf_delwri_submit(buffer_list, &io_list, true); | 1882 | xfs_buf_delwri_submit_buffers(buffer_list, &wait_list); |
| 1873 | 1883 | ||
| 1874 | /* Wait for IO to complete. */ | 1884 | /* Wait for IO to complete. */ |
| 1875 | while (!list_empty(&io_list)) { | 1885 | while (!list_empty(&wait_list)) { |
| 1876 | bp = list_first_entry(&io_list, struct xfs_buf, b_list); | 1886 | bp = list_first_entry(&wait_list, struct xfs_buf, b_list); |
| 1877 | 1887 | ||
| 1878 | list_del_init(&bp->b_list); | 1888 | list_del_init(&bp->b_list); |
| 1879 | 1889 | ||
