diff options
-rw-r--r-- | drivers/scsi/ch.c | 5 | ||||
-rw-r--r-- | drivers/scsi/osst.c | 6 | ||||
-rw-r--r-- | drivers/scsi/scsi_ioctl.c | 47 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 6 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 33 | ||||
-rw-r--r-- | drivers/scsi/sr.c | 15 | ||||
-rw-r--r-- | drivers/scsi/st.c | 7 | ||||
-rw-r--r-- | include/scsi/scsi_ioctl.h | 4 |
8 files changed, 49 insertions, 74 deletions
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 226ef771efff..4f502f95f3b8 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c | |||
@@ -616,6 +616,11 @@ static long ch_ioctl(struct file *file, | |||
616 | int retval; | 616 | int retval; |
617 | void __user *argp = (void __user *)arg; | 617 | void __user *argp = (void __user *)arg; |
618 | 618 | ||
619 | retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd, | ||
620 | file->f_flags & O_NDELAY); | ||
621 | if (retval) | ||
622 | return retval; | ||
623 | |||
619 | switch (cmd) { | 624 | switch (cmd) { |
620 | case CHIOGPARAMS: | 625 | case CHIOGPARAMS: |
621 | { | 626 | { |
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 3d0d13c4da15..b6d63d636692 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c | |||
@@ -4969,10 +4969,10 @@ static long osst_ioctl(struct file * file, | |||
4969 | * may try and take the device offline, in which case all further | 4969 | * may try and take the device offline, in which case all further |
4970 | * access to the device is prohibited. | 4970 | * access to the device is prohibited. |
4971 | */ | 4971 | */ |
4972 | if( !scsi_block_when_processing_errors(STp->device) ) { | 4972 | retval = scsi_ioctl_block_when_processing_errors(STp->device, cmd_in, |
4973 | retval = (-ENXIO); | 4973 | file->f_flags & O_NDELAY); |
4974 | if (retval) | ||
4974 | goto out; | 4975 | goto out; |
4975 | } | ||
4976 | 4976 | ||
4977 | cmd_type = _IOC_TYPE(cmd_in); | 4977 | cmd_type = _IOC_TYPE(cmd_in); |
4978 | cmd_nr = _IOC_NR(cmd_in); | 4978 | cmd_nr = _IOC_NR(cmd_in); |
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 5ddc08f39987..712f159ebb69 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c | |||
@@ -200,19 +200,6 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | |||
200 | { | 200 | { |
201 | char scsi_cmd[MAX_COMMAND_SIZE]; | 201 | char scsi_cmd[MAX_COMMAND_SIZE]; |
202 | 202 | ||
203 | /* No idea how this happens.... */ | ||
204 | if (!sdev) | ||
205 | return -ENXIO; | ||
206 | |||
207 | /* | ||
208 | * If we are in the middle of error recovery, don't let anyone | ||
209 | * else try and use this device. Also, if error recovery fails, it | ||
210 | * may try and take the device offline, in which case all further | ||
211 | * access to the device is prohibited. | ||
212 | */ | ||
213 | if (!scsi_block_when_processing_errors(sdev)) | ||
214 | return -ENODEV; | ||
215 | |||
216 | /* Check for deprecated ioctls ... all the ioctls which don't | 203 | /* Check for deprecated ioctls ... all the ioctls which don't |
217 | * follow the new unique numbering scheme are deprecated */ | 204 | * follow the new unique numbering scheme are deprecated */ |
218 | switch (cmd) { | 205 | switch (cmd) { |
@@ -273,6 +260,8 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | |||
273 | START_STOP_TIMEOUT, NORMAL_RETRIES); | 260 | START_STOP_TIMEOUT, NORMAL_RETRIES); |
274 | case SCSI_IOCTL_GET_PCI: | 261 | case SCSI_IOCTL_GET_PCI: |
275 | return scsi_ioctl_get_pci(sdev, arg); | 262 | return scsi_ioctl_get_pci(sdev, arg); |
263 | case SG_SCSI_RESET: | ||
264 | return scsi_ioctl_reset(sdev, arg); | ||
276 | default: | 265 | default: |
277 | if (sdev->host->hostt->ioctl) | 266 | if (sdev->host->hostt->ioctl) |
278 | return sdev->host->hostt->ioctl(sdev, cmd, arg); | 267 | return sdev->host->hostt->ioctl(sdev, cmd, arg); |
@@ -281,30 +270,20 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | |||
281 | } | 270 | } |
282 | EXPORT_SYMBOL(scsi_ioctl); | 271 | EXPORT_SYMBOL(scsi_ioctl); |
283 | 272 | ||
284 | /** | 273 | /* |
285 | * scsi_nonblockable_ioctl() - Handle SG_SCSI_RESET | 274 | * We can process a reset even when a device isn't fully operable. |
286 | * @sdev: scsi device receiving ioctl | ||
287 | * @cmd: Must be SC_SCSI_RESET | ||
288 | * @arg: pointer to int containing SG_SCSI_RESET_{DEVICE,TARGET,BUS,HOST} | ||
289 | * possibly OR-ed with SG_SCSI_RESET_NO_ESCALATE | ||
290 | * @ndelay: file mode O_NDELAY flag | ||
291 | */ | 275 | */ |
292 | int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | 276 | int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, int cmd, |
293 | void __user *arg, int ndelay) | 277 | bool ndelay) |
294 | { | 278 | { |
295 | /* The first set of iocts may be executed even if we're doing | 279 | if (cmd == SG_SCSI_RESET && ndelay) { |
296 | * error processing, as long as the device was opened | ||
297 | * non-blocking */ | ||
298 | if (ndelay) { | ||
299 | if (scsi_host_in_recovery(sdev->host)) | 280 | if (scsi_host_in_recovery(sdev->host)) |
300 | return -ENODEV; | 281 | return -ENODEV; |
301 | } else if (!scsi_block_when_processing_errors(sdev)) | 282 | } else { |
302 | return -ENODEV; | 283 | if (!scsi_block_when_processing_errors(sdev)) |
303 | 284 | return -ENODEV; | |
304 | switch (cmd) { | ||
305 | case SG_SCSI_RESET: | ||
306 | return scsi_ioctl_reset(sdev, arg); | ||
307 | } | 285 | } |
308 | return -ENODEV; | 286 | |
287 | return 0; | ||
309 | } | 288 | } |
310 | EXPORT_SYMBOL(scsi_nonblockable_ioctl); | 289 | EXPORT_SYMBOL_GPL(scsi_ioctl_block_when_processing_errors); |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 242f9b177285..ddf763ad3b83 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1334,9 +1334,9 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, | |||
1334 | * may try and take the device offline, in which case all further | 1334 | * may try and take the device offline, in which case all further |
1335 | * access to the device is prohibited. | 1335 | * access to the device is prohibited. |
1336 | */ | 1336 | */ |
1337 | error = scsi_nonblockable_ioctl(sdp, cmd, p, | 1337 | error = scsi_ioctl_block_when_processing_errors(sdp, cmd, |
1338 | (mode & FMODE_NDELAY) != 0); | 1338 | (mode & FMODE_NDELAY) != 0); |
1339 | if (!scsi_block_when_processing_errors(sdp) || !error) | 1339 | if (error) |
1340 | goto out; | 1340 | goto out; |
1341 | 1341 | ||
1342 | /* | 1342 | /* |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 7c55cacceb7c..b14f64cb9724 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1071,16 +1071,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) | |||
1071 | if (atomic_read(&sdp->detaching)) | 1071 | if (atomic_read(&sdp->detaching)) |
1072 | return -ENODEV; | 1072 | return -ENODEV; |
1073 | return put_user(sdp->device->host->hostt->emulated, ip); | 1073 | return put_user(sdp->device->host->hostt->emulated, ip); |
1074 | case SG_SCSI_RESET: | ||
1075 | if (atomic_read(&sdp->detaching)) | ||
1076 | return -ENODEV; | ||
1077 | if (filp->f_flags & O_NONBLOCK) { | ||
1078 | if (scsi_host_in_recovery(sdp->device->host)) | ||
1079 | return -EBUSY; | ||
1080 | } else if (!scsi_block_when_processing_errors(sdp->device)) | ||
1081 | return -EBUSY; | ||
1082 | |||
1083 | return scsi_ioctl_reset(sdp->device, ip); | ||
1084 | case SCSI_IOCTL_SEND_COMMAND: | 1074 | case SCSI_IOCTL_SEND_COMMAND: |
1085 | if (atomic_read(&sdp->detaching)) | 1075 | if (atomic_read(&sdp->detaching)) |
1086 | return -ENODEV; | 1076 | return -ENODEV; |
@@ -1100,13 +1090,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) | |||
1100 | return result; | 1090 | return result; |
1101 | sdp->sgdebug = (char) val; | 1091 | sdp->sgdebug = (char) val; |
1102 | return 0; | 1092 | return 0; |
1103 | case SCSI_IOCTL_GET_IDLUN: | ||
1104 | case SCSI_IOCTL_GET_BUS_NUMBER: | ||
1105 | case SCSI_IOCTL_PROBE_HOST: | ||
1106 | case SG_GET_TRANSFORM: | ||
1107 | if (atomic_read(&sdp->detaching)) | ||
1108 | return -ENODEV; | ||
1109 | return scsi_ioctl(sdp->device, cmd_in, p); | ||
1110 | case BLKSECTGET: | 1093 | case BLKSECTGET: |
1111 | return put_user(max_sectors_bytes(sdp->device->request_queue), | 1094 | return put_user(max_sectors_bytes(sdp->device->request_queue), |
1112 | ip); | 1095 | ip); |
@@ -1122,11 +1105,25 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) | |||
1122 | return blk_trace_startstop(sdp->device->request_queue, 0); | 1105 | return blk_trace_startstop(sdp->device->request_queue, 0); |
1123 | case BLKTRACETEARDOWN: | 1106 | case BLKTRACETEARDOWN: |
1124 | return blk_trace_remove(sdp->device->request_queue); | 1107 | return blk_trace_remove(sdp->device->request_queue); |
1108 | case SCSI_IOCTL_GET_IDLUN: | ||
1109 | case SCSI_IOCTL_GET_BUS_NUMBER: | ||
1110 | case SCSI_IOCTL_PROBE_HOST: | ||
1111 | case SG_GET_TRANSFORM: | ||
1112 | case SG_SCSI_RESET: | ||
1113 | if (atomic_read(&sdp->detaching)) | ||
1114 | return -ENODEV; | ||
1115 | break; | ||
1125 | default: | 1116 | default: |
1126 | if (read_only) | 1117 | if (read_only) |
1127 | return -EPERM; /* don't know so take safe approach */ | 1118 | return -EPERM; /* don't know so take safe approach */ |
1128 | return scsi_ioctl(sdp->device, cmd_in, p); | 1119 | break; |
1129 | } | 1120 | } |
1121 | |||
1122 | result = scsi_ioctl_block_when_processing_errors(sdp->device, | ||
1123 | cmd_in, filp->f_flags & O_NDELAY); | ||
1124 | if (result) | ||
1125 | return result; | ||
1126 | return scsi_ioctl(sdp->device, cmd_in, p); | ||
1130 | } | 1127 | } |
1131 | 1128 | ||
1132 | #ifdef CONFIG_COMPAT | 1129 | #ifdef CONFIG_COMPAT |
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 2de44cc58b1a..3d5399e341af 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
@@ -549,6 +549,11 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
549 | 549 | ||
550 | mutex_lock(&sr_mutex); | 550 | mutex_lock(&sr_mutex); |
551 | 551 | ||
552 | ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, | ||
553 | (mode & FMODE_NDELAY) != 0); | ||
554 | if (ret) | ||
555 | goto out; | ||
556 | |||
552 | /* | 557 | /* |
553 | * Send SCSI addressing ioctls directly to mid level, send other | 558 | * Send SCSI addressing ioctls directly to mid level, send other |
554 | * ioctls to cdrom/block level. | 559 | * ioctls to cdrom/block level. |
@@ -564,16 +569,6 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
564 | if (ret != -ENOSYS) | 569 | if (ret != -ENOSYS) |
565 | goto out; | 570 | goto out; |
566 | 571 | ||
567 | /* | ||
568 | * ENODEV means that we didn't recognise the ioctl, or that we | ||
569 | * cannot execute it in the current device state. In either | ||
570 | * case fall through to scsi_ioctl, which will return ENDOEV again | ||
571 | * if it doesn't recognise the ioctl | ||
572 | */ | ||
573 | ret = scsi_nonblockable_ioctl(sdev, cmd, argp, | ||
574 | (mode & FMODE_NDELAY) != 0); | ||
575 | if (ret != -ENODEV) | ||
576 | goto out; | ||
577 | ret = scsi_ioctl(sdev, cmd, argp); | 572 | ret = scsi_ioctl(sdev, cmd, argp); |
578 | 573 | ||
579 | out: | 574 | out: |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 63c35ed3c88d..7d2e036c75c1 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -3376,11 +3376,10 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) | |||
3376 | * may try and take the device offline, in which case all further | 3376 | * may try and take the device offline, in which case all further |
3377 | * access to the device is prohibited. | 3377 | * access to the device is prohibited. |
3378 | */ | 3378 | */ |
3379 | retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p, | 3379 | retval = scsi_ioctl_block_when_processing_errors(STp->device, cmd_in, |
3380 | file->f_flags & O_NDELAY); | 3380 | file->f_flags & O_NDELAY); |
3381 | if (!scsi_block_when_processing_errors(STp->device) || retval != -ENODEV) | 3381 | if (retval) |
3382 | goto out; | 3382 | goto out; |
3383 | retval = 0; | ||
3384 | 3383 | ||
3385 | cmd_type = _IOC_TYPE(cmd_in); | 3384 | cmd_type = _IOC_TYPE(cmd_in); |
3386 | cmd_nr = _IOC_NR(cmd_in); | 3385 | cmd_nr = _IOC_NR(cmd_in); |
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h index b9006848b813..8d19d1d233c3 100644 --- a/include/scsi/scsi_ioctl.h +++ b/include/scsi/scsi_ioctl.h | |||
@@ -40,9 +40,9 @@ typedef struct scsi_fctargaddress { | |||
40 | unsigned char host_wwn[8]; // include NULL term. | 40 | unsigned char host_wwn[8]; // include NULL term. |
41 | } Scsi_FCTargAddress; | 41 | } Scsi_FCTargAddress; |
42 | 42 | ||
43 | int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, | ||
44 | int cmd, bool ndelay); | ||
43 | extern int scsi_ioctl(struct scsi_device *, int, void __user *); | 45 | extern int scsi_ioctl(struct scsi_device *, int, void __user *); |
44 | extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | ||
45 | void __user *arg, int ndelay); | ||
46 | 46 | ||
47 | #endif /* __KERNEL__ */ | 47 | #endif /* __KERNEL__ */ |
48 | #endif /* _SCSI_IOCTL_H */ | 48 | #endif /* _SCSI_IOCTL_H */ |