diff options
Diffstat (limited to 'block/blk-mq.c')
-rw-r--r-- | block/blk-mq.c | 103 |
1 files changed, 54 insertions, 49 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c index 9690f4f8de7e..af4dc8227954 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
@@ -1792,78 +1792,83 @@ static blk_status_t __blk_mq_issue_directly(struct blk_mq_hw_ctx *hctx, | |||
1792 | return ret; | 1792 | return ret; |
1793 | } | 1793 | } |
1794 | 1794 | ||
1795 | static blk_status_t __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, | 1795 | static blk_status_t blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, |
1796 | struct request *rq, | 1796 | struct request *rq, |
1797 | blk_qc_t *cookie, | 1797 | blk_qc_t *cookie, |
1798 | bool bypass_insert, bool last) | 1798 | bool bypass, bool last) |
1799 | { | 1799 | { |
1800 | struct request_queue *q = rq->q; | 1800 | struct request_queue *q = rq->q; |
1801 | bool run_queue = true; | 1801 | bool run_queue = true; |
1802 | blk_status_t ret = BLK_STS_RESOURCE; | ||
1803 | int srcu_idx; | ||
1804 | bool force = false; | ||
1802 | 1805 | ||
1806 | hctx_lock(hctx, &srcu_idx); | ||
1803 | /* | 1807 | /* |
1804 | * RCU or SRCU read lock is needed before checking quiesced flag. | 1808 | * hctx_lock is needed before checking quiesced flag. |
1805 | * | 1809 | * |
1806 | * When queue is stopped or quiesced, ignore 'bypass_insert' from | 1810 | * When queue is stopped or quiesced, ignore 'bypass', insert |
1807 | * blk_mq_request_issue_directly(), and return BLK_STS_OK to caller, | 1811 | * and return BLK_STS_OK to caller, and avoid driver to try to |
1808 | * and avoid driver to try to dispatch again. | 1812 | * dispatch again. |
1809 | */ | 1813 | */ |
1810 | if (blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(q)) { | 1814 | if (unlikely(blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(q))) { |
1811 | run_queue = false; | 1815 | run_queue = false; |
1812 | bypass_insert = false; | 1816 | bypass = false; |
1813 | goto insert; | 1817 | goto out_unlock; |
1814 | } | 1818 | } |
1815 | 1819 | ||
1816 | if (q->elevator && !bypass_insert) | 1820 | if (unlikely(q->elevator && !bypass)) |
1817 | goto insert; | 1821 | goto out_unlock; |
1818 | 1822 | ||
1819 | if (!blk_mq_get_dispatch_budget(hctx)) | 1823 | if (!blk_mq_get_dispatch_budget(hctx)) |
1820 | goto insert; | 1824 | goto out_unlock; |
1821 | 1825 | ||
1822 | if (!blk_mq_get_driver_tag(rq)) { | 1826 | if (!blk_mq_get_driver_tag(rq)) { |
1823 | blk_mq_put_dispatch_budget(hctx); | 1827 | blk_mq_put_dispatch_budget(hctx); |
1824 | goto insert; | 1828 | goto out_unlock; |
1825 | } | 1829 | } |
1826 | 1830 | ||
1827 | return __blk_mq_issue_directly(hctx, rq, cookie, last); | 1831 | /* |
1828 | insert: | 1832 | * Always add a request that has been through |
1829 | if (bypass_insert) | 1833 | *.queue_rq() to the hardware dispatch list. |
1830 | return BLK_STS_RESOURCE; | 1834 | */ |
1831 | 1835 | force = true; | |
1832 | blk_mq_request_bypass_insert(rq, run_queue); | 1836 | ret = __blk_mq_issue_directly(hctx, rq, cookie, last); |
1833 | return BLK_STS_OK; | 1837 | out_unlock: |
1834 | } | ||
1835 | |||
1836 | static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, | ||
1837 | struct request *rq, blk_qc_t *cookie) | ||
1838 | { | ||
1839 | blk_status_t ret; | ||
1840 | int srcu_idx; | ||
1841 | |||
1842 | might_sleep_if(hctx->flags & BLK_MQ_F_BLOCKING); | ||
1843 | |||
1844 | hctx_lock(hctx, &srcu_idx); | ||
1845 | |||
1846 | ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false, true); | ||
1847 | if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) | ||
1848 | blk_mq_request_bypass_insert(rq, true); | ||
1849 | else if (ret != BLK_STS_OK) | ||
1850 | blk_mq_end_request(rq, ret); | ||
1851 | |||
1852 | hctx_unlock(hctx, srcu_idx); | 1838 | hctx_unlock(hctx, srcu_idx); |
1839 | switch (ret) { | ||
1840 | case BLK_STS_OK: | ||
1841 | break; | ||
1842 | case BLK_STS_DEV_RESOURCE: | ||
1843 | case BLK_STS_RESOURCE: | ||
1844 | if (force) { | ||
1845 | blk_mq_request_bypass_insert(rq, run_queue); | ||
1846 | /* | ||
1847 | * We have to return BLK_STS_OK for the DM | ||
1848 | * to avoid livelock. Otherwise, we return | ||
1849 | * the real result to indicate whether the | ||
1850 | * request is direct-issued successfully. | ||
1851 | */ | ||
1852 | ret = bypass ? BLK_STS_OK : ret; | ||
1853 | } else if (!bypass) { | ||
1854 | blk_mq_sched_insert_request(rq, false, | ||
1855 | run_queue, false); | ||
1856 | } | ||
1857 | break; | ||
1858 | default: | ||
1859 | if (!bypass) | ||
1860 | blk_mq_end_request(rq, ret); | ||
1861 | break; | ||
1862 | } | ||
1863 | |||
1864 | return ret; | ||
1853 | } | 1865 | } |
1854 | 1866 | ||
1855 | blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last) | 1867 | blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last) |
1856 | { | 1868 | { |
1857 | blk_status_t ret; | 1869 | blk_qc_t unused; |
1858 | int srcu_idx; | ||
1859 | blk_qc_t unused_cookie; | ||
1860 | struct blk_mq_hw_ctx *hctx = rq->mq_hctx; | ||
1861 | 1870 | ||
1862 | hctx_lock(hctx, &srcu_idx); | 1871 | return blk_mq_try_issue_directly(rq->mq_hctx, rq, &unused, true, last); |
1863 | ret = __blk_mq_try_issue_directly(hctx, rq, &unused_cookie, true, last); | ||
1864 | hctx_unlock(hctx, srcu_idx); | ||
1865 | |||
1866 | return ret; | ||
1867 | } | 1872 | } |
1868 | 1873 | ||
1869 | void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, | 1874 | void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, |
@@ -2004,13 +2009,13 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) | |||
2004 | if (same_queue_rq) { | 2009 | if (same_queue_rq) { |
2005 | data.hctx = same_queue_rq->mq_hctx; | 2010 | data.hctx = same_queue_rq->mq_hctx; |
2006 | blk_mq_try_issue_directly(data.hctx, same_queue_rq, | 2011 | blk_mq_try_issue_directly(data.hctx, same_queue_rq, |
2007 | &cookie); | 2012 | &cookie, false, true); |
2008 | } | 2013 | } |
2009 | } else if ((q->nr_hw_queues > 1 && is_sync) || (!q->elevator && | 2014 | } else if ((q->nr_hw_queues > 1 && is_sync) || (!q->elevator && |
2010 | !data.hctx->dispatch_busy)) { | 2015 | !data.hctx->dispatch_busy)) { |
2011 | blk_mq_put_ctx(data.ctx); | 2016 | blk_mq_put_ctx(data.ctx); |
2012 | blk_mq_bio_to_request(rq, bio); | 2017 | blk_mq_bio_to_request(rq, bio); |
2013 | blk_mq_try_issue_directly(data.hctx, rq, &cookie); | 2018 | blk_mq_try_issue_directly(data.hctx, rq, &cookie, false, true); |
2014 | } else { | 2019 | } else { |
2015 | blk_mq_put_ctx(data.ctx); | 2020 | blk_mq_put_ctx(data.ctx); |
2016 | blk_mq_bio_to_request(rq, bio); | 2021 | blk_mq_bio_to_request(rq, bio); |