diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 175 |
1 files changed, 90 insertions, 85 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 35419901124..638cff41d43 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -32,7 +32,6 @@ | |||
32 | * than the level indicated above to trigger output. | 32 | * than the level indicated above to trigger output. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/config.h> | ||
36 | #include <linux/module.h> | 35 | #include <linux/module.h> |
37 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
38 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
@@ -208,6 +207,23 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf, | |||
208 | return count; | 207 | return count; |
209 | } | 208 | } |
210 | 209 | ||
210 | static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf, | ||
211 | size_t count) | ||
212 | { | ||
213 | struct scsi_disk *sdkp = to_scsi_disk(cdev); | ||
214 | struct scsi_device *sdp = sdkp->device; | ||
215 | |||
216 | if (!capable(CAP_SYS_ADMIN)) | ||
217 | return -EACCES; | ||
218 | |||
219 | if (sdp->type != TYPE_DISK) | ||
220 | return -EINVAL; | ||
221 | |||
222 | sdp->allow_restart = simple_strtoul(buf, NULL, 10); | ||
223 | |||
224 | return count; | ||
225 | } | ||
226 | |||
211 | static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf) | 227 | static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf) |
212 | { | 228 | { |
213 | struct scsi_disk *sdkp = to_scsi_disk(cdev); | 229 | struct scsi_disk *sdkp = to_scsi_disk(cdev); |
@@ -223,10 +239,19 @@ static ssize_t sd_show_fua(struct class_device *cdev, char *buf) | |||
223 | return snprintf(buf, 20, "%u\n", sdkp->DPOFUA); | 239 | return snprintf(buf, 20, "%u\n", sdkp->DPOFUA); |
224 | } | 240 | } |
225 | 241 | ||
242 | static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf) | ||
243 | { | ||
244 | struct scsi_disk *sdkp = to_scsi_disk(cdev); | ||
245 | |||
246 | return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart); | ||
247 | } | ||
248 | |||
226 | static struct class_device_attribute sd_disk_attrs[] = { | 249 | static struct class_device_attribute sd_disk_attrs[] = { |
227 | __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, | 250 | __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, |
228 | sd_store_cache_type), | 251 | sd_store_cache_type), |
229 | __ATTR(FUA, S_IRUGO, sd_show_fua, NULL), | 252 | __ATTR(FUA, S_IRUGO, sd_show_fua, NULL), |
253 | __ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart, | ||
254 | sd_store_allow_restart), | ||
230 | __ATTR_NULL, | 255 | __ATTR_NULL, |
231 | }; | 256 | }; |
232 | 257 | ||
@@ -477,8 +502,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
477 | SCpnt->cmnd[4] = (unsigned char) this_count; | 502 | SCpnt->cmnd[4] = (unsigned char) this_count; |
478 | SCpnt->cmnd[5] = 0; | 503 | SCpnt->cmnd[5] = 0; |
479 | } | 504 | } |
480 | SCpnt->request_bufflen = SCpnt->bufflen = | 505 | SCpnt->request_bufflen = this_count * sdp->sector_size; |
481 | this_count * sdp->sector_size; | ||
482 | 506 | ||
483 | /* | 507 | /* |
484 | * We shouldn't disconnect in the middle of a sector, so with a dumb | 508 | * We shouldn't disconnect in the middle of a sector, so with a dumb |
@@ -891,11 +915,10 @@ static struct block_device_operations sd_fops = { | |||
891 | static void sd_rw_intr(struct scsi_cmnd * SCpnt) | 915 | static void sd_rw_intr(struct scsi_cmnd * SCpnt) |
892 | { | 916 | { |
893 | int result = SCpnt->result; | 917 | int result = SCpnt->result; |
894 | int this_count = SCpnt->request_bufflen; | 918 | unsigned int xfer_size = SCpnt->request_bufflen; |
895 | int good_bytes = (result == 0 ? this_count : 0); | 919 | unsigned int good_bytes = result ? 0 : xfer_size; |
896 | sector_t block_sectors = 1; | 920 | u64 start_lba = SCpnt->request->sector; |
897 | u64 first_err_block; | 921 | u64 bad_lba; |
898 | sector_t error_sector; | ||
899 | struct scsi_sense_hdr sshdr; | 922 | struct scsi_sense_hdr sshdr; |
900 | int sense_valid = 0; | 923 | int sense_valid = 0; |
901 | int sense_deferred = 0; | 924 | int sense_deferred = 0; |
@@ -906,7 +929,6 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) | |||
906 | if (sense_valid) | 929 | if (sense_valid) |
907 | sense_deferred = scsi_sense_is_deferred(&sshdr); | 930 | sense_deferred = scsi_sense_is_deferred(&sshdr); |
908 | } | 931 | } |
909 | |||
910 | #ifdef CONFIG_SCSI_LOGGING | 932 | #ifdef CONFIG_SCSI_LOGGING |
911 | SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", | 933 | SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", |
912 | SCpnt->request->rq_disk->disk_name, result)); | 934 | SCpnt->request->rq_disk->disk_name, result)); |
@@ -916,89 +938,72 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) | |||
916 | sshdr.sense_key, sshdr.asc, sshdr.ascq)); | 938 | sshdr.sense_key, sshdr.asc, sshdr.ascq)); |
917 | } | 939 | } |
918 | #endif | 940 | #endif |
919 | /* | 941 | if (driver_byte(result) != DRIVER_SENSE && |
920 | Handle MEDIUM ERRORs that indicate partial success. Since this is a | 942 | (!sense_valid || sense_deferred)) |
921 | relatively rare error condition, no care is taken to avoid | 943 | goto out; |
922 | unnecessary additional work such as memcpy's that could be avoided. | ||
923 | */ | ||
924 | if (driver_byte(result) != 0 && | ||
925 | sense_valid && !sense_deferred) { | ||
926 | switch (sshdr.sense_key) { | ||
927 | case MEDIUM_ERROR: | ||
928 | if (!blk_fs_request(SCpnt->request)) | ||
929 | break; | ||
930 | info_valid = scsi_get_sense_info_fld( | ||
931 | SCpnt->sense_buffer, SCSI_SENSE_BUFFERSIZE, | ||
932 | &first_err_block); | ||
933 | /* | ||
934 | * May want to warn and skip if following cast results | ||
935 | * in actual truncation (if sector_t < 64 bits) | ||
936 | */ | ||
937 | error_sector = (sector_t)first_err_block; | ||
938 | if (SCpnt->request->bio != NULL) | ||
939 | block_sectors = bio_sectors(SCpnt->request->bio); | ||
940 | switch (SCpnt->device->sector_size) { | ||
941 | case 1024: | ||
942 | error_sector <<= 1; | ||
943 | if (block_sectors < 2) | ||
944 | block_sectors = 2; | ||
945 | break; | ||
946 | case 2048: | ||
947 | error_sector <<= 2; | ||
948 | if (block_sectors < 4) | ||
949 | block_sectors = 4; | ||
950 | break; | ||
951 | case 4096: | ||
952 | error_sector <<=3; | ||
953 | if (block_sectors < 8) | ||
954 | block_sectors = 8; | ||
955 | break; | ||
956 | case 256: | ||
957 | error_sector >>= 1; | ||
958 | break; | ||
959 | default: | ||
960 | break; | ||
961 | } | ||
962 | 944 | ||
963 | error_sector &= ~(block_sectors - 1); | 945 | switch (sshdr.sense_key) { |
964 | good_bytes = (error_sector - SCpnt->request->sector) << 9; | 946 | case HARDWARE_ERROR: |
965 | if (good_bytes < 0 || good_bytes >= this_count) | 947 | case MEDIUM_ERROR: |
966 | good_bytes = 0; | 948 | if (!blk_fs_request(SCpnt->request)) |
949 | goto out; | ||
950 | info_valid = scsi_get_sense_info_fld(SCpnt->sense_buffer, | ||
951 | SCSI_SENSE_BUFFERSIZE, | ||
952 | &bad_lba); | ||
953 | if (!info_valid) | ||
954 | goto out; | ||
955 | if (xfer_size <= SCpnt->device->sector_size) | ||
956 | goto out; | ||
957 | switch (SCpnt->device->sector_size) { | ||
958 | case 256: | ||
959 | start_lba <<= 1; | ||
967 | break; | 960 | break; |
968 | 961 | case 512: | |
969 | case RECOVERED_ERROR: /* an error occurred, but it recovered */ | ||
970 | case NO_SENSE: /* LLDD got sense data */ | ||
971 | /* | ||
972 | * Inform the user, but make sure that it's not treated | ||
973 | * as a hard error. | ||
974 | */ | ||
975 | scsi_print_sense("sd", SCpnt); | ||
976 | SCpnt->result = 0; | ||
977 | memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | ||
978 | good_bytes = this_count; | ||
979 | break; | 962 | break; |
980 | 963 | case 1024: | |
981 | case ILLEGAL_REQUEST: | 964 | start_lba >>= 1; |
982 | if (SCpnt->device->use_10_for_rw && | 965 | break; |
983 | (SCpnt->cmnd[0] == READ_10 || | 966 | case 2048: |
984 | SCpnt->cmnd[0] == WRITE_10)) | 967 | start_lba >>= 2; |
985 | SCpnt->device->use_10_for_rw = 0; | 968 | break; |
986 | if (SCpnt->device->use_10_for_ms && | 969 | case 4096: |
987 | (SCpnt->cmnd[0] == MODE_SENSE_10 || | 970 | start_lba >>= 3; |
988 | SCpnt->cmnd[0] == MODE_SELECT_10)) | ||
989 | SCpnt->device->use_10_for_ms = 0; | ||
990 | break; | 971 | break; |
991 | |||
992 | default: | 972 | default: |
973 | /* Print something here with limiting frequency. */ | ||
974 | goto out; | ||
993 | break; | 975 | break; |
994 | } | 976 | } |
977 | /* This computation should always be done in terms of | ||
978 | * the resolution of the device's medium. | ||
979 | */ | ||
980 | good_bytes = (bad_lba - start_lba)*SCpnt->device->sector_size; | ||
981 | break; | ||
982 | case RECOVERED_ERROR: | ||
983 | case NO_SENSE: | ||
984 | /* Inform the user, but make sure that it's not treated | ||
985 | * as a hard error. | ||
986 | */ | ||
987 | scsi_print_sense("sd", SCpnt); | ||
988 | SCpnt->result = 0; | ||
989 | memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | ||
990 | good_bytes = xfer_size; | ||
991 | break; | ||
992 | case ILLEGAL_REQUEST: | ||
993 | if (SCpnt->device->use_10_for_rw && | ||
994 | (SCpnt->cmnd[0] == READ_10 || | ||
995 | SCpnt->cmnd[0] == WRITE_10)) | ||
996 | SCpnt->device->use_10_for_rw = 0; | ||
997 | if (SCpnt->device->use_10_for_ms && | ||
998 | (SCpnt->cmnd[0] == MODE_SENSE_10 || | ||
999 | SCpnt->cmnd[0] == MODE_SELECT_10)) | ||
1000 | SCpnt->device->use_10_for_ms = 0; | ||
1001 | break; | ||
1002 | default: | ||
1003 | break; | ||
995 | } | 1004 | } |
996 | /* | 1005 | out: |
997 | * This calls the generic completion function, now that we know | 1006 | scsi_io_completion(SCpnt, good_bytes); |
998 | * how many actual sectors finished, and how many sectors we need | ||
999 | * to say have failed. | ||
1000 | */ | ||
1001 | scsi_io_completion(SCpnt, good_bytes, block_sectors << 9); | ||
1002 | } | 1007 | } |
1003 | 1008 | ||
1004 | static int media_not_present(struct scsi_disk *sdkp, | 1009 | static int media_not_present(struct scsi_disk *sdkp, |
@@ -1210,7 +1215,7 @@ repeat: | |||
1210 | /* Either no media are present but the drive didn't tell us, | 1215 | /* Either no media are present but the drive didn't tell us, |
1211 | or they are present but the read capacity command fails */ | 1216 | or they are present but the read capacity command fails */ |
1212 | /* sdkp->media_present = 0; -- not always correct */ | 1217 | /* sdkp->media_present = 0; -- not always correct */ |
1213 | sdkp->capacity = 0x200000; /* 1 GB - random */ | 1218 | sdkp->capacity = 0; /* unknown mapped to zero - as usual */ |
1214 | 1219 | ||
1215 | return; | 1220 | return; |
1216 | } else if (the_result && longrc) { | 1221 | } else if (the_result && longrc) { |