aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJun'ichi Nomura <j-nomura@ce.jp.nec.com>2012-05-22 05:57:17 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-05-23 04:34:17 -0400
commitb7e94a1686c5daef4f649f7f4f839cc294f07710 (patch)
treee50da550b9b6d7805df8e1f6f3e93b3b48417861
parent4886b1afee5aaccc2fb3202620a5608caf0c9284 (diff)
[SCSI] Fix dm-multipath starvation when scsi host is busy
block congestion control doesn't have any concept of fairness across multiple queues. This means that if SCSI reports the host as busy in the queue congestion control it can result in an unfair starvation situation in dm-mp if there are multiple multipath devices on the same host. For example: http://www.redhat.com/archives/dm-devel/2012-May/msg00123.html The fix for this is to report only the sdev busy state (and ignore the host busy state) in the block congestion control call back. The host is still congested, but the SCSI subsystem will sort out the congestion in a fair way because it knows the relation between the queues and the host. [jejb: fixed up trailing whitespace] Reported-by: Bernd Schubert <bernd.schubert@itwm.fraunhofer.de> Tested-by: Bernd Schubert <bernd.schubert@itwm.fraunhofer.de> Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com> Cc: <stable@vger.kernel.org> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/scsi_lib.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 62ddfd31d4ce..6dfb9785d345 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1378,16 +1378,19 @@ static int scsi_lld_busy(struct request_queue *q)
1378{ 1378{
1379 struct scsi_device *sdev = q->queuedata; 1379 struct scsi_device *sdev = q->queuedata;
1380 struct Scsi_Host *shost; 1380 struct Scsi_Host *shost;
1381 struct scsi_target *starget;
1382 1381
1383 if (!sdev) 1382 if (!sdev)
1384 return 0; 1383 return 0;
1385 1384
1386 shost = sdev->host; 1385 shost = sdev->host;
1387 starget = scsi_target(sdev);
1388 1386
1389 if (scsi_host_in_recovery(shost) || scsi_host_is_busy(shost) || 1387 /*
1390 scsi_target_is_busy(starget) || scsi_device_is_busy(sdev)) 1388 * Ignore host/starget busy state.
1389 * Since block layer does not have a concept of fairness across
1390 * multiple queues, congestion of host/starget needs to be handled
1391 * in SCSI layer.
1392 */
1393 if (scsi_host_in_recovery(shost) || scsi_device_is_busy(sdev))
1391 return 1; 1394 return 1;
1392 1395
1393 return 0; 1396 return 0;