Commit 2e27f576 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Martin K. Petersen

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.deSigned-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 4f07bfc5
...@@ -877,7 +877,7 @@ static long ch_ioctl(struct file *file, ...@@ -877,7 +877,7 @@ static long ch_ioctl(struct file *file,
} }
default: default:
return scsi_ioctl(ch->device, cmd, argp); return scsi_ioctl(ch->device, NULL, file->f_mode, cmd, argp);
} }
} }
......
...@@ -192,6 +192,8 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg) ...@@ -192,6 +192,8 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg)
/** /**
* scsi_ioctl - Dispatch ioctl to scsi device * scsi_ioctl - Dispatch ioctl to scsi device
* @sdev: scsi device receiving ioctl * @sdev: scsi device receiving ioctl
* @disk: disk receiving the ioctl
* @mode: mode the block/char device is opened with
* @cmd: which ioctl is it * @cmd: which ioctl is it
* @arg: data associated with ioctl * @arg: data associated with ioctl
* *
...@@ -199,10 +201,13 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg) ...@@ -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 * does not take a major/minor number as the dev field. Rather, it takes
* a pointer to a &struct scsi_device. * 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]; char scsi_cmd[MAX_COMMAND_SIZE];
struct scsi_sense_hdr sense_hdr; struct scsi_sense_hdr sense_hdr;
int error;
/* Check for deprecated ioctls ... all the ioctls which don't /* Check for deprecated ioctls ... all the ioctls which don't
* follow the new unique numbering scheme are deprecated */ * follow the new unique numbering scheme are deprecated */
...@@ -220,6 +225,12 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) ...@@ -220,6 +225,12 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
break; 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) { switch (cmd) {
case SCSI_IOCTL_GET_IDLUN: { case SCSI_IOCTL_GET_IDLUN: {
struct scsi_idlun v = { struct scsi_idlun v = {
...@@ -237,10 +248,6 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) ...@@ -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); return put_user(sdev->host->host_no, (int __user *)arg);
case SCSI_IOCTL_PROBE_HOST: case SCSI_IOCTL_PROBE_HOST:
return ioctl_probe(sdev->host, arg); 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: case SCSI_IOCTL_DOORLOCK:
return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
case SCSI_IOCTL_DOORUNLOCK: case SCSI_IOCTL_DOORUNLOCK:
......
...@@ -1571,23 +1571,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -1571,23 +1571,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
if (is_sed_ioctl(cmd)) if (is_sed_ioctl(cmd))
return sed_ioctl(sdkp->opal_dev, cmd, p); return sed_ioctl(sdkp->opal_dev, cmd, p);
return scsi_ioctl(sdp, disk, mode, 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);
} }
static void set_media_not_present(struct scsi_disk *sdkp) static void set_media_not_present(struct scsi_disk *sdkp)
......
...@@ -1165,7 +1165,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) ...@@ -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); ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
if (ret != -ENOIOCTLCMD) if (ret != -ENOIOCTLCMD)
return ret; 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 static __poll_t
......
...@@ -574,24 +574,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, ...@@ -574,24 +574,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
scsi_autopm_get_device(sdev); scsi_autopm_get_device(sdev);
/* if (ret != CDROMCLOSETRAY && ret != CDROMEJECT) {
* 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;
ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
if (ret != -ENOSYS) if (ret != -ENOSYS)
goto put; goto put;
} }
ret = scsi_ioctl(sdev, disk, mode, cmd, argp);
ret = scsi_ioctl(sdev, cmd, argp);
put: put:
scsi_autopm_put_device(sdev); scsi_autopm_put_device(sdev);
......
...@@ -3823,24 +3823,16 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) ...@@ -3823,24 +3823,16 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
mutex_unlock(&STp->lock); mutex_unlock(&STp->lock);
switch (cmd_in) { switch (cmd_in) {
case SCSI_IOCTL_GET_IDLUN:
case SCSI_IOCTL_GET_BUS_NUMBER:
break;
case SG_IO: case SG_IO:
case SCSI_IOCTL_SEND_COMMAND: case SCSI_IOCTL_SEND_COMMAND:
case CDROM_SEND_PACKET: case CDROM_SEND_PACKET:
if (!capable(CAP_SYS_RAWIO)) if (!capable(CAP_SYS_RAWIO))
return -EPERM; return -EPERM;
fallthrough;
default: default:
retval = scsi_cmd_ioctl(STp->disk->queue, STp->disk,
file->f_mode, cmd_in, p);
if (retval != -ENOTTY)
return retval;
break; 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) { if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) {
/* unload */ /* unload */
STp->rew_at_close = 0; STp->rew_at_close = 0;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
struct gendisk;
struct scsi_device; struct scsi_device;
/* /*
...@@ -43,7 +44,8 @@ typedef struct scsi_fctargaddress { ...@@ -43,7 +44,8 @@ typedef struct scsi_fctargaddress {
int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
int cmd, bool ndelay); 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 /* __KERNEL__ */
#endif /* _SCSI_IOCTL_H */ #endif /* _SCSI_IOCTL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment