X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fscsi_ioctl.c;h=d459bb7a09944c5c69ae16af00e84b091234c7c0;hb=ca2b99eacafb345c16648535f68ea0f5b160f230;hp=faab1a00a48587a288c7528a17c8d414ec168ea8;hpb=e686509282835a634ee3285c39a1b5b04ee2a88f;p=linux-2.6.git diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index faab1a00a..d459bb7a0 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -5,23 +5,22 @@ * for the ones that remain */ #include - -#include -#include -#include -#include - +#include #include #include #include #include #include #include +#include -#include -#include "scsi.h" +#include +#include +#include #include #include +#include +#include #include "scsi_logging.h" @@ -393,6 +392,21 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) if (!scsi_block_when_processing_errors(sdev)) return -ENODEV; + /* Check for deprecated ioctls ... all the ioctls which don't + * follow the new unique numbering scheme are deprecated */ + switch (cmd) { + case SCSI_IOCTL_SEND_COMMAND: + case SCSI_IOCTL_TEST_UNIT_READY: + case SCSI_IOCTL_BENCHMARK_COMMAND: + case SCSI_IOCTL_SYNC: + case SCSI_IOCTL_START_UNIT: + case SCSI_IOCTL_STOP_UNIT: + printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm); + break; + default: + break; + } + switch (cmd) { case SCSI_IOCTL_GET_IDLUN: if (verify_area(VERIFY_WRITE, arg, sizeof(struct scsi_idlun))) @@ -419,12 +433,8 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) case SCSI_IOCTL_DOORUNLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); case SCSI_IOCTL_TEST_UNIT_READY: - scsi_cmd[0] = TEST_UNIT_READY; - scsi_cmd[1] = 0; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = 0; - return ioctl_internal_command(sdev, scsi_cmd, - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); + return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT, + NORMAL_RETRIES); case SCSI_IOCTL_START_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = 0; @@ -447,3 +457,51 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) } return -EINVAL; } + +/* + * the scsi_nonblock_ioctl() function is designed for ioctls which may + * be executed even if the device is in recovery. + */ +int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, + void __user *arg, struct file *filp) +{ + int val, result; + + /* The first set of iocts may be executed even if we're doing + * error processing, as long as the device was opened + * non-blocking */ + if (filp && filp->f_flags & O_NONBLOCK) { + if (test_bit(SHOST_RECOVERY, + &sdev->host->shost_state)) + return -ENODEV; + } else if (!scsi_block_when_processing_errors(sdev)) + return -ENODEV; + + switch (cmd) { + case SG_SCSI_RESET: + result = get_user(val, (int __user *)arg); + if (result) + return result; + if (val == SG_SCSI_RESET_NOTHING) + return 0; + switch (val) { + case SG_SCSI_RESET_DEVICE: + val = SCSI_TRY_RESET_DEVICE; + break; + case SG_SCSI_RESET_BUS: + val = SCSI_TRY_RESET_BUS; + break; + case SG_SCSI_RESET_HOST: + val = SCSI_TRY_RESET_HOST; + break; + default: + return -EINVAL; + } + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + return (scsi_reset_provider(sdev, val) == + SUCCESS) ? 0 : -EIO; + } + return -ENODEV; +} +EXPORT_SYMBOL(scsi_nonblockable_ioctl);