* for the ones that remain
*/
#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/page.h>
-
+#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/string.h>
+#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-#include "scsi.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_request.h>
+#include <scsi/sg.h>
#include "scsi_logging.h"
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)))
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;
}
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);