scsi: scsi_ioctl: Call scsi_cmd_ioctl() from scsi_ioctl()
authorChristoph Hellwig <hch@lst.de>
Sat, 24 Jul 2021 07:20:20 +0000 (09:20 +0200)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 29 Jul 2021 02:24:25 +0000 (22:24 -0400)
Ensure SCSI ULD only has to call a single ioctl helper.  This also adds a
bunch of missing ioctls to the ch driver, and removes the need for a
duplicate implementation of SCSI_IOCTL_SEND_COMMAND command.

Link: https://lore.kernel.org/r/20210724072033.1284840-12-hch@lst.de
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/ch.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/scsi/st.c
include/scsi/scsi_ioctl.h

index e354a95..2701290 100644 (file)
@@ -877,7 +877,7 @@ static long ch_ioctl(struct file *file,
        }
 
        default:
-               return scsi_ioctl(ch->device, cmd, argp);
+               return scsi_ioctl(ch->device, NULL, file->f_mode, cmd, argp);
 
        }
 }
index 7b2e3cc..7739575 100644 (file)
@@ -192,6 +192,8 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg)
 /**
  * scsi_ioctl - Dispatch ioctl to scsi device
  * @sdev: scsi device receiving ioctl
+ * @disk: disk receiving the ioctl
+ * @mode: mode the block/char device is opened with
  * @cmd: which ioctl is it
  * @arg: data associated with ioctl
  *
@@ -199,10 +201,13 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg)
  * does not take a major/minor number as the dev field.  Rather, it takes
  * a pointer to a &struct scsi_device.
  */
-int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
+               int cmd, void __user *arg)
 {
+       struct request_queue *q = sdev->request_queue;
        char scsi_cmd[MAX_COMMAND_SIZE];
        struct scsi_sense_hdr sense_hdr;
+       int error;
 
        /* Check for deprecated ioctls ... all the ioctls which don't
         * follow the new unique numbering scheme are deprecated */
@@ -220,6 +225,12 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
                break;
        }
 
+       if (cmd != SCSI_IOCTL_GET_IDLUN && cmd != SCSI_IOCTL_GET_BUS_NUMBER) {
+               error = scsi_cmd_ioctl(q, disk, mode, cmd, arg);
+               if (error != -ENOTTY)
+                       return error;
+       }
+
        switch (cmd) {
        case SCSI_IOCTL_GET_IDLUN: {
                struct scsi_idlun v = {
@@ -237,10 +248,6 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
                return put_user(sdev->host->host_no, (int __user *)arg);
        case SCSI_IOCTL_PROBE_HOST:
                return ioctl_probe(sdev->host, arg);
-       case SCSI_IOCTL_SEND_COMMAND:
-               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-                       return -EACCES;
-               return sg_scsi_ioctl(sdev->request_queue, NULL, 0, arg);
        case SCSI_IOCTL_DOORLOCK:
                return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
        case SCSI_IOCTL_DOORUNLOCK:
index bcc4b13..c1b75f1 100644 (file)
@@ -1571,23 +1571,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
 
        if (is_sed_ioctl(cmd))
                return sed_ioctl(sdkp->opal_dev, cmd, p);
-
-       /*
-        * Send SCSI addressing ioctls directly to mid level, send other
-        * ioctls to block level and then onto mid level if they can't be
-        * resolved.
-        */
-       switch (cmd) {
-       case SCSI_IOCTL_GET_IDLUN:
-       case SCSI_IOCTL_GET_BUS_NUMBER:
-               break;
-       default:
-               error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
-               if (error != -ENOTTY)
-                       return error;
-       }
-
-       return scsi_ioctl(sdp, cmd, p);
+       return scsi_ioctl(sdp, disk, mode, cmd, p);
 }
 
 static void set_media_not_present(struct scsi_disk *sdkp)
index c3562c2..6cb1e4b 100644 (file)
@@ -1165,7 +1165,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
        ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
        if (ret != -ENOIOCTLCMD)
                return ret;
-       return scsi_ioctl(sdp->device, cmd_in, p);
+       return scsi_ioctl(sdp->device, NULL, filp->f_mode, cmd_in, p);
 }
 
 static __poll_t
index e6eadba..b98e77f 100644 (file)
@@ -574,24 +574,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 
        scsi_autopm_get_device(sdev);
 
-       /*
-        * Send SCSI addressing ioctls directly to mid level, send other
-        * ioctls to cdrom/block level.
-        */
-       switch (cmd) {
-       case SCSI_IOCTL_GET_IDLUN:
-       case SCSI_IOCTL_GET_BUS_NUMBER:
-               break;
-       default:
-               ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
-               if (ret != -ENOTTY)
-                       goto put;
+       if (ret != CDROMCLOSETRAY && ret != CDROMEJECT) {
                ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
                if (ret != -ENOSYS)
                        goto put;
        }
-
-       ret = scsi_ioctl(sdev, cmd, argp);
+       ret = scsi_ioctl(sdev, disk, mode, cmd, argp);
 
 put:
        scsi_autopm_put_device(sdev);
index 9274f66..2d1b059 100644 (file)
@@ -3823,24 +3823,16 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
        mutex_unlock(&STp->lock);
 
        switch (cmd_in) {
-       case SCSI_IOCTL_GET_IDLUN:
-       case SCSI_IOCTL_GET_BUS_NUMBER:
-               break;
        case SG_IO:
        case SCSI_IOCTL_SEND_COMMAND:
        case CDROM_SEND_PACKET:
                if (!capable(CAP_SYS_RAWIO))
                        return -EPERM;
-               fallthrough;
        default:
-               retval = scsi_cmd_ioctl(STp->disk->queue, STp->disk,
-                                       file->f_mode, cmd_in, p);
-               if (retval != -ENOTTY)
-                       return retval;
                break;
        }
 
-       retval = scsi_ioctl(STp->device, cmd_in, p);
+       retval = scsi_ioctl(STp->device, STp->disk, file->f_mode, cmd_in, p);
        if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) {
                /* unload */
                STp->rew_at_close = 0;
index cdb3ba3..defbe80 100644 (file)
@@ -18,6 +18,7 @@
 
 #ifdef __KERNEL__
 
+struct gendisk;
 struct scsi_device;
 
 /*
@@ -43,7 +44,8 @@ typedef struct scsi_fctargaddress {
 
 int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
                int cmd, bool ndelay);
-extern int scsi_ioctl(struct scsi_device *, int, void __user *);
+int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
+               int cmd, void __user *arg);
 
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */