aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2012-01-09 22:27:01 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-01-16 02:54:04 -0500
commit466c08c71a7dc19528e9b336c5bfa5ec41730c7c (patch)
tree586cdcc5d9bd5b5bccd5b8594a5b5379b722b79f /drivers/scsi/scsi_lib.c
parent05b080fc933bb068b32fa119db00e8efcc10e3bd (diff)
[SCSI] don't change sdev starvation list order without request dispatched
The sdev is deleted from starved list and then try to dispatch from this device. It's quite possible the sdev can't eventually dispatch a request, then the sdev will be in starved list tail. This isn't fair. There are two cases here: 1. unplug path. scsi_request_fn() calls to scsi_target_queue_ready(), then the dev is removed from starved list, but quite possible host queue isn't ready, the dev is moved to starved list without dispatching any request. 2. scsi_run_queue path. It deletes the dev from starved list first (both global and local starved lists), then handles the dev. Then we could have the same process like case 1. This patch fixes the first case. Case 2 isn't fixed, because there is a rare case scsi_run_queue finds host isn't busy but scsi_request_fn finds host is busy (other CPU is faster to get host queue depth). Not deleting the dev from starved list in scsi_run_queue will keep scsi_run_queue looping (though this is very rare case, because host will become busy). Fortunately fixing case 1 already gives big improvement for starvation in my test. In a 12 disk JBOD setup, running file creation under EXT4, this gives 12% more throughput. Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c7
1 files changed, 1 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f85cfa6c47b5..b2c95dbe9d65 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1316,15 +1316,10 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
1316 } 1316 }
1317 1317
1318 if (scsi_target_is_busy(starget)) { 1318 if (scsi_target_is_busy(starget)) {
1319 if (list_empty(&sdev->starved_entry)) 1319 list_move_tail(&sdev->starved_entry, &shost->starved_list);
1320 list_add_tail(&sdev->starved_entry,
1321 &shost->starved_list);
1322 return 0; 1320 return 0;
1323 } 1321 }
1324 1322
1325 /* We're OK to process the command, so we can't be starved */
1326 if (!list_empty(&sdev->starved_entry))
1327 list_del_init(&sdev->starved_entry);
1328 return 1; 1323 return 1;
1329} 1324}
1330 1325