summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2021-07-24 09:20:20 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2021-07-28 22:24:25 -0400
commit2e27f576abc6f056e63ef207b9911b1a04d07020 (patch)
treeccec24aa14279c5a8140c42feebaa96633b03364
parent4f07bfc56157ebc689ef54879e90c48a47294083 (diff)
downloadlwn-2e27f576abc6f056e63ef207b9911b1a04d07020.tar.gz
lwn-2e27f576abc6f056e63ef207b9911b1a04d07020.zip
scsi: scsi_ioctl: Call scsi_cmd_ioctl() from scsi_ioctl()
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>
-rw-r--r--drivers/scsi/ch.c2
-rw-r--r--drivers/scsi/scsi_ioctl.c17
-rw-r--r--drivers/scsi/sd.c18
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/scsi/sr.c16
-rw-r--r--drivers/scsi/st.c10
-rw-r--r--include/scsi/scsi_ioctl.h4
7 files changed, 21 insertions, 48 deletions
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index e354a95c56af..27012908b586 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -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);
}
}
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 7b2e3cc85e66..7739575b5229 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -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:
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index bcc4b1339e21..c1b75f159e0c 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -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)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index c3562c2d0dca..6cb1e4b6eac2 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -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
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index e6eadba4d638..b98e77fe700b 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -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);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 9274f665bc0f..2d1b0594af69 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -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;
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index cdb3ba3451e7..defbe8084eb8 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -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 */