diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b83269689542..112c737884c3 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1274,18 +1274,18 @@ static inline int scsi_dev_queue_ready(struct request_queue *q, | |||
1274 | /* | 1274 | /* |
1275 | * scsi_target_queue_ready: checks if there we can send commands to target | 1275 | * scsi_target_queue_ready: checks if there we can send commands to target |
1276 | * @sdev: scsi device on starget to check. | 1276 | * @sdev: scsi device on starget to check. |
1277 | * | ||
1278 | * Called with the host lock held. | ||
1279 | */ | 1277 | */ |
1280 | static inline int scsi_target_queue_ready(struct Scsi_Host *shost, | 1278 | static inline int scsi_target_queue_ready(struct Scsi_Host *shost, |
1281 | struct scsi_device *sdev) | 1279 | struct scsi_device *sdev) |
1282 | { | 1280 | { |
1283 | struct scsi_target *starget = scsi_target(sdev); | 1281 | struct scsi_target *starget = scsi_target(sdev); |
1282 | int ret = 0; | ||
1284 | 1283 | ||
1284 | spin_lock_irq(shost->host_lock); | ||
1285 | if (starget->single_lun) { | 1285 | if (starget->single_lun) { |
1286 | if (starget->starget_sdev_user && | 1286 | if (starget->starget_sdev_user && |
1287 | starget->starget_sdev_user != sdev) | 1287 | starget->starget_sdev_user != sdev) |
1288 | return 0; | 1288 | goto out; |
1289 | starget->starget_sdev_user = sdev; | 1289 | starget->starget_sdev_user = sdev; |
1290 | } | 1290 | } |
1291 | 1291 | ||
@@ -1293,57 +1293,66 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost, | |||
1293 | /* | 1293 | /* |
1294 | * unblock after target_blocked iterates to zero | 1294 | * unblock after target_blocked iterates to zero |
1295 | */ | 1295 | */ |
1296 | if (--starget->target_blocked == 0) { | 1296 | if (--starget->target_blocked != 0) |
1297 | SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget, | 1297 | goto out; |
1298 | "unblocking target at zero depth\n")); | 1298 | |
1299 | } else | 1299 | SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget, |
1300 | return 0; | 1300 | "unblocking target at zero depth\n")); |
1301 | } | 1301 | } |
1302 | 1302 | ||
1303 | if (scsi_target_is_busy(starget)) { | 1303 | if (scsi_target_is_busy(starget)) { |
1304 | list_move_tail(&sdev->starved_entry, &shost->starved_list); | 1304 | list_move_tail(&sdev->starved_entry, &shost->starved_list); |
1305 | return 0; | 1305 | goto out; |
1306 | } | 1306 | } |
1307 | 1307 | ||
1308 | return 1; | 1308 | scsi_target(sdev)->target_busy++; |
1309 | ret = 1; | ||
1310 | out: | ||
1311 | spin_unlock_irq(shost->host_lock); | ||
1312 | return ret; | ||
1309 | } | 1313 | } |
1310 | 1314 | ||
1311 | /* | 1315 | /* |
1312 | * scsi_host_queue_ready: if we can send requests to shost, return 1 else | 1316 | * scsi_host_queue_ready: if we can send requests to shost, return 1 else |
1313 | * return 0. We must end up running the queue again whenever 0 is | 1317 | * return 0. We must end up running the queue again whenever 0 is |
1314 | * returned, else IO can hang. | 1318 | * returned, else IO can hang. |
1315 | * | ||
1316 | * Called with host_lock held. | ||
1317 | */ | 1319 | */ |
1318 | static inline int scsi_host_queue_ready(struct request_queue *q, | 1320 | static inline int scsi_host_queue_ready(struct request_queue *q, |
1319 | struct Scsi_Host *shost, | 1321 | struct Scsi_Host *shost, |
1320 | struct scsi_device *sdev) | 1322 | struct scsi_device *sdev) |
1321 | { | 1323 | { |
1324 | int ret = 0; | ||
1325 | |||
1326 | spin_lock_irq(shost->host_lock); | ||
1327 | |||
1322 | if (scsi_host_in_recovery(shost)) | 1328 | if (scsi_host_in_recovery(shost)) |
1323 | return 0; | 1329 | goto out; |
1324 | if (shost->host_busy == 0 && shost->host_blocked) { | 1330 | if (shost->host_busy == 0 && shost->host_blocked) { |
1325 | /* | 1331 | /* |
1326 | * unblock after host_blocked iterates to zero | 1332 | * unblock after host_blocked iterates to zero |
1327 | */ | 1333 | */ |
1328 | if (--shost->host_blocked == 0) { | 1334 | if (--shost->host_blocked != 0) |
1329 | SCSI_LOG_MLQUEUE(3, | 1335 | goto out; |
1330 | shost_printk(KERN_INFO, shost, | 1336 | |
1331 | "unblocking host at zero depth\n")); | 1337 | SCSI_LOG_MLQUEUE(3, |
1332 | } else { | 1338 | shost_printk(KERN_INFO, shost, |
1333 | return 0; | 1339 | "unblocking host at zero depth\n")); |
1334 | } | ||
1335 | } | 1340 | } |
1336 | if (scsi_host_is_busy(shost)) { | 1341 | if (scsi_host_is_busy(shost)) { |
1337 | if (list_empty(&sdev->starved_entry)) | 1342 | if (list_empty(&sdev->starved_entry)) |
1338 | list_add_tail(&sdev->starved_entry, &shost->starved_list); | 1343 | list_add_tail(&sdev->starved_entry, &shost->starved_list); |
1339 | return 0; | 1344 | goto out; |
1340 | } | 1345 | } |
1341 | 1346 | ||
1342 | /* We're OK to process the command, so we can't be starved */ | 1347 | /* We're OK to process the command, so we can't be starved */ |
1343 | if (!list_empty(&sdev->starved_entry)) | 1348 | if (!list_empty(&sdev->starved_entry)) |
1344 | list_del_init(&sdev->starved_entry); | 1349 | list_del_init(&sdev->starved_entry); |
1345 | 1350 | ||
1346 | return 1; | 1351 | shost->host_busy++; |
1352 | ret = 1; | ||
1353 | out: | ||
1354 | spin_unlock_irq(shost->host_lock); | ||
1355 | return ret; | ||
1347 | } | 1356 | } |
1348 | 1357 | ||
1349 | /* | 1358 | /* |
@@ -1524,7 +1533,7 @@ static void scsi_request_fn(struct request_queue *q) | |||
1524 | blk_start_request(req); | 1533 | blk_start_request(req); |
1525 | sdev->device_busy++; | 1534 | sdev->device_busy++; |
1526 | 1535 | ||
1527 | spin_unlock(q->queue_lock); | 1536 | spin_unlock_irq(q->queue_lock); |
1528 | cmd = req->special; | 1537 | cmd = req->special; |
1529 | if (unlikely(cmd == NULL)) { | 1538 | if (unlikely(cmd == NULL)) { |
1530 | printk(KERN_CRIT "impossible request in %s.\n" | 1539 | printk(KERN_CRIT "impossible request in %s.\n" |
@@ -1534,7 +1543,6 @@ static void scsi_request_fn(struct request_queue *q) | |||
1534 | blk_dump_rq_flags(req, "foo"); | 1543 | blk_dump_rq_flags(req, "foo"); |
1535 | BUG(); | 1544 | BUG(); |
1536 | } | 1545 | } |
1537 | spin_lock(shost->host_lock); | ||
1538 | 1546 | ||
1539 | /* | 1547 | /* |
1540 | * We hit this when the driver is using a host wide | 1548 | * We hit this when the driver is using a host wide |
@@ -1545,9 +1553,11 @@ static void scsi_request_fn(struct request_queue *q) | |||
1545 | * a run when a tag is freed. | 1553 | * a run when a tag is freed. |
1546 | */ | 1554 | */ |
1547 | if (blk_queue_tagged(q) && !blk_rq_tagged(req)) { | 1555 | if (blk_queue_tagged(q) && !blk_rq_tagged(req)) { |
1556 | spin_lock_irq(shost->host_lock); | ||
1548 | if (list_empty(&sdev->starved_entry)) | 1557 | if (list_empty(&sdev->starved_entry)) |
1549 | list_add_tail(&sdev->starved_entry, | 1558 | list_add_tail(&sdev->starved_entry, |
1550 | &shost->starved_list); | 1559 | &shost->starved_list); |
1560 | spin_unlock_irq(shost->host_lock); | ||
1551 | goto not_ready; | 1561 | goto not_ready; |
1552 | } | 1562 | } |
1553 | 1563 | ||
@@ -1555,16 +1565,7 @@ static void scsi_request_fn(struct request_queue *q) | |||
1555 | goto not_ready; | 1565 | goto not_ready; |
1556 | 1566 | ||
1557 | if (!scsi_host_queue_ready(q, shost, sdev)) | 1567 | if (!scsi_host_queue_ready(q, shost, sdev)) |
1558 | goto not_ready; | 1568 | goto host_not_ready; |
1559 | |||
1560 | scsi_target(sdev)->target_busy++; | ||
1561 | shost->host_busy++; | ||
1562 | |||
1563 | /* | ||
1564 | * XXX(hch): This is rather suboptimal, scsi_dispatch_cmd will | ||
1565 | * take the lock again. | ||
1566 | */ | ||
1567 | spin_unlock_irq(shost->host_lock); | ||
1568 | 1569 | ||
1569 | /* | 1570 | /* |
1570 | * Finally, initialize any error handling parameters, and set up | 1571 | * Finally, initialize any error handling parameters, and set up |
@@ -1587,9 +1588,11 @@ static void scsi_request_fn(struct request_queue *q) | |||
1587 | 1588 | ||
1588 | return; | 1589 | return; |
1589 | 1590 | ||
1590 | not_ready: | 1591 | host_not_ready: |
1592 | spin_lock_irq(shost->host_lock); | ||
1593 | scsi_target(sdev)->target_busy--; | ||
1591 | spin_unlock_irq(shost->host_lock); | 1594 | spin_unlock_irq(shost->host_lock); |
1592 | 1595 | not_ready: | |
1593 | /* | 1596 | /* |
1594 | * lock q, handle tag, requeue req, and decrement device_busy. We | 1597 | * lock q, handle tag, requeue req, and decrement device_busy. We |
1595 | * must return with queue_lock held. | 1598 | * must return with queue_lock held. |