aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-09-07 11:44:01 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:23:52 -0500
commit3ff5588d3f8afad65ded52ac0e4191462fe034cb (patch)
treed75858a35c3f9042dc234e17772fe9d713e2ca9c
parent29687512c0b084957112cc2c0743ce34cd0d5055 (diff)
[SCSI] sd: improve logic and efficiecy of media-change detection
This patch (as1415) improves the formerly incomprehensible logic in sd_media_changed() (the current code refers to "changed" as a state, whereas in fact it is a relation between two states). It also adds a big comment so that everyone can understand what is really going on. The patch also improves efficiency by not reporting a media change when no medium was ever present. If no medium was present the last time we checked and there's still no medium, it's not necessary to tell the caller that a change occurred. Doing so merely causes the caller to attempt to revalidate a non-existent disk, which is a waste of time. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/sd.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 956496182c80..26f9d54a9c92 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -583,7 +583,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
583 * quietly refuse to do anything to a changed disc until 583 * quietly refuse to do anything to a changed disc until
584 * the changed bit has been reset 584 * the changed bit has been reset
585 */ 585 */
586 /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ 586 /* printk("SCSI disk has been changed or is not present. Prohibiting further I/O.\n"); */
587 goto out; 587 goto out;
588 } 588 }
589 589
@@ -1023,7 +1023,6 @@ static int sd_media_changed(struct gendisk *disk)
1023 */ 1023 */
1024 if (!scsi_device_online(sdp)) { 1024 if (!scsi_device_online(sdp)) {
1025 set_media_not_present(sdkp); 1025 set_media_not_present(sdkp);
1026 retval = 1;
1027 goto out; 1026 goto out;
1028 } 1027 }
1029 1028
@@ -1054,7 +1053,6 @@ static int sd_media_changed(struct gendisk *disk)
1054 /* 0x3a is medium not present */ 1053 /* 0x3a is medium not present */
1055 sshdr->asc == 0x3a)) { 1054 sshdr->asc == 0x3a)) {
1056 set_media_not_present(sdkp); 1055 set_media_not_present(sdkp);
1057 retval = 1;
1058 goto out; 1056 goto out;
1059 } 1057 }
1060 1058
@@ -1065,12 +1063,27 @@ static int sd_media_changed(struct gendisk *disk)
1065 */ 1063 */
1066 sdkp->media_present = 1; 1064 sdkp->media_present = 1;
1067 1065
1068 retval = sdp->changed;
1069 sdp->changed = 0;
1070out: 1066out:
1071 if (retval != sdkp->previous_state) 1067 /*
1068 * Report a media change under the following conditions:
1069 *
1070 * Medium is present now and wasn't present before.
1071 * Medium wasn't present before and is present now.
1072 * Medium was present at all times, but it changed while
1073 * we weren't looking (sdp->changed is set).
1074 *
1075 * If there was no medium before and there is no medium now then
1076 * don't report a change, even if a medium was inserted and removed
1077 * while we weren't looking.
1078 */
1079 retval = (sdkp->media_present != sdkp->previous_state ||
1080 (sdkp->media_present && sdp->changed));
1081 if (retval)
1072 sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL); 1082 sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL);
1073 sdkp->previous_state = retval; 1083 sdkp->previous_state = sdkp->media_present;
1084
1085 /* sdp->changed indicates medium was changed or is not present */
1086 sdp->changed = !sdkp->media_present;
1074 kfree(sshdr); 1087 kfree(sshdr);
1075 return retval; 1088 return retval;
1076} 1089}