Commit 826a70a08b1210bbfdbda812ab43eb986e25b5c2

Authored by Ming Lei
Committed by Jens Axboe
1 parent e4f36b249b

SCSI: don't get target/host busy_count in scsi_mq_get_budget()

It is very expensive to atomic_inc/atomic_dec the host wide counter of
host->busy_count, and it should have been avoided via blk-mq's mechanism
of getting driver tag, which uses the more efficient way of sbitmap queue.

Also we don't check atomic_read(&sdev->device_busy) in scsi_mq_get_budget()
and don't run queue if the counter becomes zero, so IO hang may be caused
if all requests are completed just before the current SCSI device
is added to shost->starved_list.

Fixes: 0df21c86bdbf(scsi: implement .get_budget and .put_budget for blk-mq)
Reported-by: Bart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

Showing 1 changed file with 13 additions and 16 deletions Side-by-side Diff

drivers/scsi/scsi_lib.c
... ... @@ -1950,11 +1950,7 @@
1950 1950 {
1951 1951 struct request_queue *q = hctx->queue;
1952 1952 struct scsi_device *sdev = q->queuedata;
1953   - struct Scsi_Host *shost = sdev->host;
1954 1953  
1955   - atomic_dec(&shost->host_busy);
1956   - if (scsi_target(sdev)->can_queue > 0)
1957   - atomic_dec(&scsi_target(sdev)->target_busy);
1958 1954 atomic_dec(&sdev->device_busy);
1959 1955 put_device(&sdev->sdev_gendev);
1960 1956 }
... ... @@ -1963,7 +1959,6 @@
1963 1959 {
1964 1960 struct request_queue *q = hctx->queue;
1965 1961 struct scsi_device *sdev = q->queuedata;
1966   - struct Scsi_Host *shost = sdev->host;
1967 1962 blk_status_t ret;
1968 1963  
1969 1964 ret = prep_to_mq(scsi_prep_state_check(sdev, NULL));
1970 1965  
... ... @@ -1974,18 +1969,9 @@
1974 1969 goto out;
1975 1970 if (!scsi_dev_queue_ready(q, sdev))
1976 1971 goto out_put_device;
1977   - if (!scsi_target_queue_ready(shost, sdev))
1978   - goto out_dec_device_busy;
1979   - if (!scsi_host_queue_ready(q, shost, sdev))
1980   - goto out_dec_target_busy;
1981 1972  
1982 1973 return BLK_STS_OK;
1983 1974  
1984   -out_dec_target_busy:
1985   - if (scsi_target(sdev)->can_queue > 0)
1986   - atomic_dec(&scsi_target(sdev)->target_busy);
1987   -out_dec_device_busy:
1988   - atomic_dec(&sdev->device_busy);
1989 1975 out_put_device:
1990 1976 put_device(&sdev->sdev_gendev);
1991 1977 out:
... ... @@ -1998,6 +1984,7 @@
1998 1984 struct request *req = bd->rq;
1999 1985 struct request_queue *q = req->q;
2000 1986 struct scsi_device *sdev = q->queuedata;
  1987 + struct Scsi_Host *shost = sdev->host;
2001 1988 struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
2002 1989 blk_status_t ret;
2003 1990 int reason;
2004 1991  
... ... @@ -2007,10 +1994,15 @@
2007 1994 goto out_put_budget;
2008 1995  
2009 1996 ret = BLK_STS_RESOURCE;
  1997 + if (!scsi_target_queue_ready(shost, sdev))
  1998 + goto out_put_budget;
  1999 + if (!scsi_host_queue_ready(q, shost, sdev))
  2000 + goto out_dec_target_busy;
  2001 +
2010 2002 if (!(req->rq_flags & RQF_DONTPREP)) {
2011 2003 ret = prep_to_mq(scsi_mq_prep_fn(req));
2012 2004 if (ret != BLK_STS_OK)
2013   - goto out_put_budget;
  2005 + goto out_dec_host_busy;
2014 2006 req->rq_flags |= RQF_DONTPREP;
2015 2007 } else {
2016 2008 blk_mq_start_request(req);
2017 2009  
... ... @@ -2028,11 +2020,16 @@
2028 2020 if (reason) {
2029 2021 scsi_set_blocked(cmd, reason);
2030 2022 ret = BLK_STS_RESOURCE;
2031   - goto out_put_budget;
  2023 + goto out_dec_host_busy;
2032 2024 }
2033 2025  
2034 2026 return BLK_STS_OK;
2035 2027  
  2028 +out_dec_host_busy:
  2029 + atomic_dec(&shost->host_busy);
  2030 +out_dec_target_busy:
  2031 + if (scsi_target(sdev)->can_queue > 0)
  2032 + atomic_dec(&scsi_target(sdev)->target_busy);
2036 2033 out_put_budget:
2037 2034 scsi_mq_put_budget(hctx);
2038 2035 switch (ret) {