diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1e7c9e9ef772..f5d3b96890dc 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1465,6 +1465,37 @@ static inline int scsi_host_queue_ready(struct request_queue *q, | |||
1465 | } | 1465 | } |
1466 | 1466 | ||
1467 | /* | 1467 | /* |
1468 | * Busy state exporting function for request stacking drivers. | ||
1469 | * | ||
1470 | * For efficiency, no lock is taken to check the busy state of | ||
1471 | * shost/starget/sdev, since the returned value is not guaranteed and | ||
1472 | * may be changed after request stacking drivers call the function, | ||
1473 | * regardless of taking lock or not. | ||
1474 | * | ||
1475 | * When scsi can't dispatch I/Os anymore and needs to kill I/Os | ||
1476 | * (e.g. !sdev), scsi needs to return 'not busy'. | ||
1477 | * Otherwise, request stacking drivers may hold requests forever. | ||
1478 | */ | ||
1479 | static int scsi_lld_busy(struct request_queue *q) | ||
1480 | { | ||
1481 | struct scsi_device *sdev = q->queuedata; | ||
1482 | struct Scsi_Host *shost; | ||
1483 | struct scsi_target *starget; | ||
1484 | |||
1485 | if (!sdev) | ||
1486 | return 0; | ||
1487 | |||
1488 | shost = sdev->host; | ||
1489 | starget = scsi_target(sdev); | ||
1490 | |||
1491 | if (scsi_host_in_recovery(shost) || scsi_host_is_busy(shost) || | ||
1492 | scsi_target_is_busy(starget) || scsi_device_is_busy(sdev)) | ||
1493 | return 1; | ||
1494 | |||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | /* | ||
1468 | * Kill a request for a dead device | 1499 | * Kill a request for a dead device |
1469 | */ | 1500 | */ |
1470 | static void scsi_kill_request(struct request *req, struct request_queue *q) | 1501 | static void scsi_kill_request(struct request *req, struct request_queue *q) |
@@ -1767,6 +1798,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) | |||
1767 | blk_queue_prep_rq(q, scsi_prep_fn); | 1798 | blk_queue_prep_rq(q, scsi_prep_fn); |
1768 | blk_queue_softirq_done(q, scsi_softirq_done); | 1799 | blk_queue_softirq_done(q, scsi_softirq_done); |
1769 | blk_queue_rq_timed_out(q, scsi_times_out); | 1800 | blk_queue_rq_timed_out(q, scsi_times_out); |
1801 | blk_queue_lld_busy(q, scsi_lld_busy); | ||
1770 | return q; | 1802 | return q; |
1771 | } | 1803 | } |
1772 | 1804 | ||