aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_ioctl.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2014-10-11 10:25:31 -0400
committerChristoph Hellwig <hch@lst.de>2014-11-12 05:16:11 -0500
commit906d15fbd23c1267addab361063c1c8119992215 (patch)
tree419ba148925c3651fe9337af24a932097e2c3d8a /drivers/scsi/scsi_ioctl.c
parent176aa9d6ee2db582e7e856dbe1983004a82869b4 (diff)
scsi: split scsi_nonblockable_ioctl
The calling conventions for this function are bad as it could return -ENODEV both for a device not currently online and a not recognized ioctl. Add a new scsi_ioctl_block_when_processing_errors function that wraps scsi_block_when_processing_errors with the a special case for the SG_SCSI_RESET ioctl command, and handle the SG_SCSI_RESET case itself in scsi_ioctl. All callers of scsi_ioctl now must call the above helper to check for the EH state, so that the ioctl handler itself doesn't have to. Reported-by: Robert Elliott <Elliott@hp.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Hannes Reinecke <hare@suse.de>
Diffstat (limited to 'drivers/scsi/scsi_ioctl.c')
-rw-r--r--drivers/scsi/scsi_ioctl.c47
1 files changed, 13 insertions, 34 deletions
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}
282EXPORT_SYMBOL(scsi_ioctl); 271EXPORT_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 */
292int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, 276int 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}
310EXPORT_SYMBOL(scsi_nonblockable_ioctl); 289EXPORT_SYMBOL_GPL(scsi_ioctl_block_when_processing_errors);