diff options
author | Christoph Hellwig <hch@lst.de> | 2014-10-11 06:06:47 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-11-12 05:16:10 -0500 |
commit | 176aa9d6ee2db582e7e856dbe1983004a82869b4 (patch) | |
tree | 5c1e97cbdc98dd9162ef6f81af19eca932f8117e /drivers/scsi | |
parent | 1ee8e889d946b3b1c2cc8b99e29eac47d1581dfd (diff) |
scsi: refactor scsi_reset_provider handling
Pull the common code from the two callers into the function,
and rename it to scsi_ioctl_reset.
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')
-rw-r--r-- | drivers/scsi/scsi_error.c | 76 | ||||
-rw-r--r-- | drivers/scsi/scsi_ioctl.c | 33 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 34 |
3 files changed, 40 insertions, 103 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 95c9abb64183..a6f6b9222b51 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <scsi/scsi_transport.h> | 36 | #include <scsi/scsi_transport.h> |
37 | #include <scsi/scsi_host.h> | 37 | #include <scsi/scsi_host.h> |
38 | #include <scsi/scsi_ioctl.h> | 38 | #include <scsi/scsi_ioctl.h> |
39 | #include <scsi/sg.h> | ||
39 | 40 | ||
40 | #include "scsi_priv.h" | 41 | #include "scsi_priv.h" |
41 | #include "scsi_logging.h" | 42 | #include "scsi_logging.h" |
@@ -2311,39 +2312,36 @@ scsi_reset_provider_done_command(struct scsi_cmnd *scmd) | |||
2311 | { | 2312 | { |
2312 | } | 2313 | } |
2313 | 2314 | ||
2314 | /* | 2315 | /** |
2315 | * Function: scsi_reset_provider | 2316 | * scsi_ioctl_reset: explicitly reset a host/bus/target/device |
2316 | * | 2317 | * @dev: scsi_device to operate on |
2317 | * Purpose: Send requested reset to a bus or device at any phase. | 2318 | * @arg: reset type (see sg.h) |
2318 | * | ||
2319 | * Arguments: device - device to send reset to | ||
2320 | * flag - reset type (see scsi.h) | ||
2321 | * | ||
2322 | * Returns: SUCCESS/FAILURE. | ||
2323 | * | ||
2324 | * Notes: This is used by the SCSI Generic driver to provide | ||
2325 | * Bus/Device reset capability. | ||
2326 | */ | 2319 | */ |
2327 | int | 2320 | int |
2328 | scsi_reset_provider(struct scsi_device *dev, int flag) | 2321 | scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) |
2329 | { | 2322 | { |
2330 | struct scsi_cmnd *scmd; | 2323 | struct scsi_cmnd *scmd; |
2331 | struct Scsi_Host *shost = dev->host; | 2324 | struct Scsi_Host *shost = dev->host; |
2332 | struct request req; | 2325 | struct request req; |
2333 | unsigned long flags; | 2326 | unsigned long flags; |
2334 | int rtn; | 2327 | int error = 0, rtn, val; |
2328 | |||
2329 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | ||
2330 | return -EACCES; | ||
2331 | |||
2332 | error = get_user(val, arg); | ||
2333 | if (error) | ||
2334 | return error; | ||
2335 | 2335 | ||
2336 | if (scsi_autopm_get_host(shost) < 0) | 2336 | if (scsi_autopm_get_host(shost) < 0) |
2337 | return FAILED; | 2337 | return -EIO; |
2338 | 2338 | ||
2339 | if (!get_device(&dev->sdev_gendev)) { | 2339 | error = -EIO; |
2340 | rtn = FAILED; | 2340 | if (!get_device(&dev->sdev_gendev)) |
2341 | goto out_put_autopm_host; | 2341 | goto out_put_autopm_host; |
2342 | } | ||
2343 | 2342 | ||
2344 | scmd = scsi_get_command(dev, GFP_KERNEL); | 2343 | scmd = scsi_get_command(dev, GFP_KERNEL); |
2345 | if (!scmd) { | 2344 | if (!scmd) { |
2346 | rtn = FAILED; | ||
2347 | put_device(&dev->sdev_gendev); | 2345 | put_device(&dev->sdev_gendev); |
2348 | goto out_put_autopm_host; | 2346 | goto out_put_autopm_host; |
2349 | } | 2347 | } |
@@ -2364,39 +2362,37 @@ scsi_reset_provider(struct scsi_device *dev, int flag) | |||
2364 | shost->tmf_in_progress = 1; | 2362 | shost->tmf_in_progress = 1; |
2365 | spin_unlock_irqrestore(shost->host_lock, flags); | 2363 | spin_unlock_irqrestore(shost->host_lock, flags); |
2366 | 2364 | ||
2367 | switch (flag) { | 2365 | switch (val & ~SG_SCSI_RESET_NO_ESCALATE) { |
2368 | case SCSI_TRY_RESET_DEVICE: | 2366 | case SG_SCSI_RESET_NOTHING: |
2367 | rtn = SUCCESS; | ||
2368 | break; | ||
2369 | case SG_SCSI_RESET_DEVICE: | ||
2369 | rtn = scsi_try_bus_device_reset(scmd); | 2370 | rtn = scsi_try_bus_device_reset(scmd); |
2370 | if (rtn == SUCCESS) | 2371 | if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) |
2371 | break; | 2372 | break; |
2372 | /* FALLTHROUGH */ | 2373 | /* FALLTHROUGH */ |
2373 | case SCSI_TRY_RESET_TARGET: | 2374 | case SG_SCSI_RESET_TARGET: |
2374 | rtn = scsi_try_target_reset(scmd); | 2375 | rtn = scsi_try_target_reset(scmd); |
2375 | if (rtn == SUCCESS) | 2376 | if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) |
2376 | break; | 2377 | break; |
2377 | /* FALLTHROUGH */ | 2378 | /* FALLTHROUGH */ |
2378 | case SCSI_TRY_RESET_BUS: | 2379 | case SG_SCSI_RESET_BUS: |
2379 | rtn = scsi_try_bus_reset(scmd); | 2380 | rtn = scsi_try_bus_reset(scmd); |
2380 | if (rtn == SUCCESS) | 2381 | if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) |
2381 | break; | 2382 | break; |
2382 | /* FALLTHROUGH */ | 2383 | /* FALLTHROUGH */ |
2383 | case SCSI_TRY_RESET_HOST: | 2384 | case SG_SCSI_RESET_HOST: |
2384 | case SCSI_TRY_RESET_HOST | SCSI_TRY_RESET_NO_ESCALATE: | ||
2385 | rtn = scsi_try_host_reset(scmd); | 2385 | rtn = scsi_try_host_reset(scmd); |
2386 | break; | 2386 | if (rtn == SUCCESS) |
2387 | case SCSI_TRY_RESET_DEVICE | SCSI_TRY_RESET_NO_ESCALATE: | 2387 | break; |
2388 | rtn = scsi_try_bus_device_reset(scmd); | ||
2389 | break; | ||
2390 | case SCSI_TRY_RESET_TARGET | SCSI_TRY_RESET_NO_ESCALATE: | ||
2391 | rtn = scsi_try_target_reset(scmd); | ||
2392 | break; | ||
2393 | case SCSI_TRY_RESET_BUS | SCSI_TRY_RESET_NO_ESCALATE: | ||
2394 | rtn = scsi_try_bus_reset(scmd); | ||
2395 | break; | ||
2396 | default: | 2388 | default: |
2389 | /* FALLTHROUGH */ | ||
2397 | rtn = FAILED; | 2390 | rtn = FAILED; |
2391 | break; | ||
2398 | } | 2392 | } |
2399 | 2393 | ||
2394 | error = (rtn == SUCCESS) ? 0 : -EIO; | ||
2395 | |||
2400 | spin_lock_irqsave(shost->host_lock, flags); | 2396 | spin_lock_irqsave(shost->host_lock, flags); |
2401 | shost->tmf_in_progress = 0; | 2397 | shost->tmf_in_progress = 0; |
2402 | spin_unlock_irqrestore(shost->host_lock, flags); | 2398 | spin_unlock_irqrestore(shost->host_lock, flags); |
@@ -2416,9 +2412,9 @@ scsi_reset_provider(struct scsi_device *dev, int flag) | |||
2416 | scsi_next_command(scmd); | 2412 | scsi_next_command(scmd); |
2417 | out_put_autopm_host: | 2413 | out_put_autopm_host: |
2418 | scsi_autopm_put_host(shost); | 2414 | scsi_autopm_put_host(shost); |
2419 | return rtn; | 2415 | return error; |
2420 | } | 2416 | } |
2421 | EXPORT_SYMBOL(scsi_reset_provider); | 2417 | EXPORT_SYMBOL(scsi_ioctl_reset); |
2422 | 2418 | ||
2423 | /** | 2419 | /** |
2424 | * scsi_normalize_sense - normalize main elements from either fixed or | 2420 | * scsi_normalize_sense - normalize main elements from either fixed or |
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 5207274574f5..5ddc08f39987 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c | |||
@@ -292,8 +292,6 @@ EXPORT_SYMBOL(scsi_ioctl); | |||
292 | int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | 292 | int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, |
293 | void __user *arg, int ndelay) | 293 | void __user *arg, int ndelay) |
294 | { | 294 | { |
295 | int val, val2, result; | ||
296 | |||
297 | /* The first set of iocts may be executed even if we're doing | 295 | /* The first set of iocts may be executed even if we're doing |
298 | * error processing, as long as the device was opened | 296 | * error processing, as long as the device was opened |
299 | * non-blocking */ | 297 | * non-blocking */ |
@@ -305,36 +303,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | |||
305 | 303 | ||
306 | switch (cmd) { | 304 | switch (cmd) { |
307 | case SG_SCSI_RESET: | 305 | case SG_SCSI_RESET: |
308 | result = get_user(val, (int __user *)arg); | 306 | return scsi_ioctl_reset(sdev, arg); |
309 | if (result) | ||
310 | return result; | ||
311 | if (val & SG_SCSI_RESET_NO_ESCALATE) { | ||
312 | val &= ~SG_SCSI_RESET_NO_ESCALATE; | ||
313 | val2 = SCSI_TRY_RESET_NO_ESCALATE; | ||
314 | } else | ||
315 | val2 = 0; | ||
316 | if (val == SG_SCSI_RESET_NOTHING) | ||
317 | return 0; | ||
318 | switch (val) { | ||
319 | case SG_SCSI_RESET_DEVICE: | ||
320 | val2 |= SCSI_TRY_RESET_DEVICE; | ||
321 | break; | ||
322 | case SG_SCSI_RESET_TARGET: | ||
323 | val2 |= SCSI_TRY_RESET_TARGET; | ||
324 | break; | ||
325 | case SG_SCSI_RESET_BUS: | ||
326 | val2 |= SCSI_TRY_RESET_BUS; | ||
327 | break; | ||
328 | case SG_SCSI_RESET_HOST: | ||
329 | val2 |= SCSI_TRY_RESET_HOST; | ||
330 | break; | ||
331 | default: | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | ||
335 | return -EACCES; | ||
336 | return (scsi_reset_provider(sdev, val2) == | ||
337 | SUCCESS) ? 0 : -EIO; | ||
338 | } | 307 | } |
339 | return -ENODEV; | 308 | return -ENODEV; |
340 | } | 309 | } |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2fe2701d86db..7c55cacceb7c 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -847,7 +847,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) | |||
847 | { | 847 | { |
848 | void __user *p = (void __user *)arg; | 848 | void __user *p = (void __user *)arg; |
849 | int __user *ip = p; | 849 | int __user *ip = p; |
850 | int result, val, val2, read_only; | 850 | int result, val, read_only; |
851 | Sg_device *sdp; | 851 | Sg_device *sdp; |
852 | Sg_fd *sfp; | 852 | Sg_fd *sfp; |
853 | Sg_request *srp; | 853 | Sg_request *srp; |
@@ -1079,36 +1079,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) | |||
1079 | return -EBUSY; | 1079 | return -EBUSY; |
1080 | } else if (!scsi_block_when_processing_errors(sdp->device)) | 1080 | } else if (!scsi_block_when_processing_errors(sdp->device)) |
1081 | return -EBUSY; | 1081 | return -EBUSY; |
1082 | result = get_user(val, ip); | 1082 | |
1083 | if (result) | 1083 | return scsi_ioctl_reset(sdp->device, ip); |
1084 | return result; | ||
1085 | if (val & SG_SCSI_RESET_NO_ESCALATE) { | ||
1086 | val &= ~SG_SCSI_RESET_NO_ESCALATE; | ||
1087 | val2 = SCSI_TRY_RESET_NO_ESCALATE; | ||
1088 | } else | ||
1089 | val2 = 0; | ||
1090 | if (SG_SCSI_RESET_NOTHING == val) | ||
1091 | return 0; | ||
1092 | switch (val) { | ||
1093 | case SG_SCSI_RESET_DEVICE: | ||
1094 | val2 |= SCSI_TRY_RESET_DEVICE; | ||
1095 | break; | ||
1096 | case SG_SCSI_RESET_TARGET: | ||
1097 | val2 |= SCSI_TRY_RESET_TARGET; | ||
1098 | break; | ||
1099 | case SG_SCSI_RESET_BUS: | ||
1100 | val2 |= SCSI_TRY_RESET_BUS; | ||
1101 | break; | ||
1102 | case SG_SCSI_RESET_HOST: | ||
1103 | val2 |= SCSI_TRY_RESET_HOST; | ||
1104 | break; | ||
1105 | default: | ||
1106 | return -EINVAL; | ||
1107 | } | ||
1108 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | ||
1109 | return -EACCES; | ||
1110 | return (scsi_reset_provider(sdp->device, val2) == | ||
1111 | SUCCESS) ? 0 : -EIO; | ||
1112 | case SCSI_IOCTL_SEND_COMMAND: | 1084 | case SCSI_IOCTL_SEND_COMMAND: |
1113 | if (atomic_read(&sdp->detaching)) | 1085 | if (atomic_read(&sdp->detaching)) |
1114 | return -ENODEV; | 1086 | return -ENODEV; |