linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* cleanup SCSI ioctl support
@ 2021-07-12  5:47 Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 01/24] bsg: remove support for SCSI_IOCTL_SEND_COMMAND Christoph Hellwig
                   ` (24 more replies)
  0 siblings, 25 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:47 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Hi all,

this series cleans up the scsi ioctl handler and merges the "block layer"
SCSI ioctl code that is only used by the SCSI layer and its drivers now
into the main SCSI ioctl handler.

Diffstat:
 b/block/Kconfig                |   26 -
 b/block/Makefile               |    3 
 b/block/bsg.c                  |  123 +----
 b/drivers/block/Kconfig        |    3 
 b/drivers/block/paride/Kconfig |    1 
 b/drivers/cdrom/cdrom.c        |    7 
 b/drivers/scsi/Kconfig         |   18 
 b/drivers/scsi/Makefile        |    3 
 b/drivers/scsi/ch.c            |   73 ---
 b/drivers/scsi/scsi_bsg.c      |   95 ++++
 b/drivers/scsi/scsi_common.c   |    6 
 b/drivers/scsi/scsi_ioctl.c    |  848 ++++++++++++++++++++++++++++++++++-----
 b/drivers/scsi/scsi_lib.c      |    7 
 b/drivers/scsi/scsi_priv.h     |   10 
 b/drivers/scsi/sd.c            |   66 ---
 b/drivers/scsi/sg.c            |   33 -
 b/drivers/scsi/sr.c            |   74 ---
 b/drivers/scsi/st.c            |   72 +--
 b/drivers/target/Kconfig       |    2 
 b/fs/nfsd/Kconfig              |    2 
 b/include/linux/blkdev.h       |   21 
 b/include/linux/bsg.h          |   11 
 b/include/scsi/scsi_ioctl.h    |    9 
 b/include/scsi/scsi_request.h  |    2 
 block/scsi_ioctl.c             |  890 -----------------------------------------
 25 files changed, 1011 insertions(+), 1394 deletions(-)

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH 01/24] bsg: remove support for SCSI_IOCTL_SEND_COMMAND
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
@ 2021-07-12  5:47 ` Christoph Hellwig
  2021-07-22 17:31   ` Bart Van Assche
  2021-07-12  5:47 ` [PATCH 02/24] sr: consolidate compat ioctl handling Christoph Hellwig
                   ` (23 subsequent siblings)
  24 siblings, 1 reply; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:47 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

SCSI_IOCTL_SEND_COMMAND has been deprecated longer than bsg exists
and has been warning for just as long.  More importantly it harcodes
SCSI CDBs and thus will do the wrong thing on non-scsi bsg nodes.

Fixes: aa387cc89567 ("block: add bsg helper library")
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bsg.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/block/bsg.c b/block/bsg.c
index 1f196563ae6c..79b42c5cafeb 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -373,10 +373,13 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case SG_GET_RESERVED_SIZE:
 	case SG_SET_RESERVED_SIZE:
 	case SG_EMULATED_HOST:
-	case SCSI_IOCTL_SEND_COMMAND:
 		return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg);
 	case SG_IO:
 		return bsg_sg_io(bd->queue, file->f_mode, uarg);
+	case SCSI_IOCTL_SEND_COMMAND:
+		pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND\n",
+				current->comm);
+		return -EINVAL;
 	default:
 		return -ENOTTY;
 	}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 02/24] sr: consolidate compat ioctl handling
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 01/24] bsg: remove support for SCSI_IOCTL_SEND_COMMAND Christoph Hellwig
@ 2021-07-12  5:47 ` Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 03/24] sd: " Christoph Hellwig
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:47 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Merge the native and compat ioctl handlers into a single one using
in_compat_syscall().

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/sr.c | 64 +++++++----------------------------------------
 1 file changed, 9 insertions(+), 55 deletions(-)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 94c254e9012e..b34f06924659 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -577,68 +577,24 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 	switch (cmd) {
 	case SCSI_IOCTL_GET_IDLUN:
 	case SCSI_IOCTL_GET_BUS_NUMBER:
-		ret = scsi_ioctl(sdev, cmd, argp);
-		goto put;
+		break;
+	default:
+		ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
+		if (ret != -ENOSYS)
+			goto put;
 	}
 
-	ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
-	if (ret != -ENOSYS)
-		goto put;
-
-	ret = scsi_ioctl(sdev, cmd, argp);
-
-put:
-	scsi_autopm_put_device(sdev);
-
-out:
-	mutex_unlock(&cd->lock);
-	return ret;
-}
-
-#ifdef CONFIG_COMPAT
-static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
-			  unsigned long arg)
-{
-	struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
-	struct scsi_device *sdev = cd->device;
-	void __user *argp = compat_ptr(arg);
-	int ret;
-
-	mutex_lock(&cd->lock);
-
-	ret = scsi_ioctl_block_when_processing_errors(sdev, cmd,
-			(mode & FMODE_NDELAY) != 0);
-	if (ret)
-		goto out;
-
-	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:
+	if (in_compat_syscall())
 		ret = scsi_compat_ioctl(sdev, cmd, argp);
-		goto put;
-	}
-
-	ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, (unsigned long)argp);
-	if (ret != -ENOSYS)
-		goto put;
-
-	ret = scsi_compat_ioctl(sdev, cmd, argp);
+	else
+		ret = scsi_ioctl(sdev, cmd, argp);
 
 put:
 	scsi_autopm_put_device(sdev);
-
 out:
 	mutex_unlock(&cd->lock);
 	return ret;
-
 }
-#endif
 
 static unsigned int sr_block_check_events(struct gendisk *disk,
 					  unsigned int clearing)
@@ -663,9 +619,7 @@ static const struct block_device_operations sr_bdops =
 	.open		= sr_block_open,
 	.release	= sr_block_release,
 	.ioctl		= sr_block_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= sr_block_compat_ioctl,
-#endif
+	.compat_ioctl	= blkdev_compat_ptr_ioctl,
 	.check_events	= sr_block_check_events,
 };
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 03/24] sd: consolidate compat ioctl handling
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 01/24] bsg: remove support for SCSI_IOCTL_SEND_COMMAND Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 02/24] sr: consolidate compat ioctl handling Christoph Hellwig
@ 2021-07-12  5:47 ` Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 04/24] ch: " Christoph Hellwig
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:47 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Merge the native and compat ioctl handlers into a single one using
in_compat_syscall(), and also simplify the calling conventions
by mergin sd_ioctl_common into sd_ioctl.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/sd.c | 63 ++++++++++++++---------------------------------
 1 file changed, 18 insertions(+), 45 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 6d2d63629a90..f470daf76155 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1533,11 +1533,11 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 }
 
 /**
- *	sd_ioctl_common - process an ioctl
+ *	sd_ioctl - process an ioctl
  *	@bdev: target block device
  *	@mode: FMODE_* mask
  *	@cmd: ioctl command number
- *	@p: this is third argument given to ioctl(2) system call.
+ *	@arg: this is third argument given to ioctl(2) system call.
  *	Often contains a pointer.
  *
  *	Returns 0 if successful (some ioctls return positive numbers on
@@ -1546,12 +1546,13 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
  *	Note: most ioctls are forward onto the block subsystem or further
  *	down in the scsi subsystem.
  **/
-static int sd_ioctl_common(struct block_device *bdev, fmode_t mode,
-			   unsigned int cmd, void __user *p)
+static int sd_ioctl(struct block_device *bdev, fmode_t mode,
+		    unsigned int cmd, unsigned long arg)
 {
 	struct gendisk *disk = bdev->bd_disk;
 	struct scsi_disk *sdkp = scsi_disk(disk);
 	struct scsi_device *sdp = sdkp->device;
+	void __user *p = (void __user *)arg;
 	int error;
     
 	SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
@@ -1570,7 +1571,7 @@ static int sd_ioctl_common(struct block_device *bdev, fmode_t mode,
 	error = scsi_ioctl_block_when_processing_errors(sdp, cmd,
 			(mode & FMODE_NDELAY) != 0);
 	if (error)
-		goto out;
+		return error;
 
 	if (is_sed_ioctl(cmd))
 		return sed_ioctl(sdkp->opal_dev, cmd, p);
@@ -1581,16 +1582,18 @@ static int sd_ioctl_common(struct block_device *bdev, fmode_t mode,
 	 * resolved.
 	 */
 	switch (cmd) {
-		case SCSI_IOCTL_GET_IDLUN:
-		case SCSI_IOCTL_GET_BUS_NUMBER:
-			error = scsi_ioctl(sdp, cmd, p);
-			break;
-		default:
-			error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
-			break;
+	case SCSI_IOCTL_GET_IDLUN:
+	case SCSI_IOCTL_GET_BUS_NUMBER:
+		break;
+	default:
+		error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
+		if (error != -ENOTTY)
+			return error;
 	}
-out:
-	return error;
+
+	if (in_compat_syscall())
+		return scsi_compat_ioctl(sdp, cmd, p);
+	return scsi_ioctl(sdp, cmd, p);
 }
 
 static void set_media_not_present(struct scsi_disk *sdkp)
@@ -1773,34 +1776,6 @@ static void sd_rescan(struct device *dev)
 	sd_revalidate_disk(sdkp->disk);
 }
 
-static int sd_ioctl(struct block_device *bdev, fmode_t mode,
-		    unsigned int cmd, unsigned long arg)
-{
-	void __user *p = (void __user *)arg;
-	int ret;
-
-	ret = sd_ioctl_common(bdev, mode, cmd, p);
-	if (ret != -ENOTTY)
-		return ret;
-
-	return scsi_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p);
-}
-
-#ifdef CONFIG_COMPAT
-static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
-			   unsigned int cmd, unsigned long arg)
-{
-	void __user *p = compat_ptr(arg);
-	int ret;
-
-	ret = sd_ioctl_common(bdev, mode, cmd, p);
-	if (ret != -ENOTTY)
-		return ret;
-
-	return scsi_compat_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p);
-}
-#endif
-
 static char sd_pr_type(enum pr_type type)
 {
 	switch (type) {
@@ -1901,9 +1876,7 @@ static const struct block_device_operations sd_fops = {
 	.release		= sd_release,
 	.ioctl			= sd_ioctl,
 	.getgeo			= sd_getgeo,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl		= sd_compat_ioctl,
-#endif
+	.compat_ioctl		= blkdev_compat_ptr_ioctl,
 	.check_events		= sd_check_events,
 	.unlock_native_capacity	= sd_unlock_native_capacity,
 	.report_zones		= sd_zbc_report_zones,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 04/24] ch: consolidate compat ioctl handling
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (2 preceding siblings ...)
  2021-07-12  5:47 ` [PATCH 03/24] sd: " Christoph Hellwig
@ 2021-07-12  5:47 ` Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 05/24] cg: " Christoph Hellwig
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:47 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Merge the native and compat ioctl handlers into a single one using
in_compat_syscall().

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/ch.c | 73 ++++++++++++++---------------------------------
 1 file changed, 22 insertions(+), 51 deletions(-)

diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index fc7197abfcdf..e89f226cae5c 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -618,6 +618,12 @@ ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
 	return 0;
 }
 
+struct changer_element_status32 {
+	int		ces_type;
+	compat_uptr_t	ces_data;
+};
+#define CHIOGSTATUS32  _IOW('c', 8,struct changer_element_status32)
+
 static long ch_ioctl(struct file *file,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -748,7 +754,20 @@ static long ch_ioctl(struct file *file,
 
 		return ch_gstatus(ch, ces.ces_type, ces.ces_data);
 	}
+#ifdef CONFIG_COMPAT
+	case CHIOGSTATUS32:
+	{
+		struct changer_element_status32 ces32;
+
+		if (copy_from_user(&ces32, argp, sizeof (ces32)))
+			return -EFAULT;
+		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
+			return -EINVAL;
 
+		return ch_gstatus(ch, ces32.ces_type,
+				  compat_ptr(ces32.ces_data));
+	}
+#endif
 	case CHIOGELEM:
 	{
 		struct changer_get_element cge;
@@ -858,59 +877,13 @@ static long ch_ioctl(struct file *file,
 	}
 
 	default:
+		if (in_compat_syscall())
+			return scsi_compat_ioctl(ch->device, cmd, argp);
 		return scsi_ioctl(ch->device, cmd, argp);
 
 	}
 }
 
-#ifdef CONFIG_COMPAT
-
-struct changer_element_status32 {
-	int		ces_type;
-	compat_uptr_t	ces_data;
-};
-#define CHIOGSTATUS32  _IOW('c', 8,struct changer_element_status32)
-
-static long ch_ioctl_compat(struct file * file,
-			    unsigned int cmd, unsigned long arg)
-{
-	scsi_changer *ch = file->private_data;
-	int retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
-							file->f_flags & O_NDELAY);
-	if (retval)
-		return retval;
-
-	switch (cmd) {
-	case CHIOGPARAMS:
-	case CHIOGVPARAMS:
-	case CHIOPOSITION:
-	case CHIOMOVE:
-	case CHIOEXCHANGE:
-	case CHIOGELEM:
-	case CHIOINITELEM:
-	case CHIOSVOLTAG:
-		/* compatible */
-		return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
-	case CHIOGSTATUS32:
-	{
-		struct changer_element_status32 ces32;
-		unsigned char __user *data;
-
-		if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
-			return -EFAULT;
-		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
-			return -EINVAL;
-
-		data = compat_ptr(ces32.ces_data);
-		return ch_gstatus(ch, ces32.ces_type, data);
-	}
-	default:
-		return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg));
-
-	}
-}
-#endif
-
 /* ------------------------------------------------------------------------ */
 
 static int ch_probe(struct device *dev)
@@ -1015,9 +988,7 @@ static const struct file_operations changer_fops = {
 	.open		= ch_open,
 	.release	= ch_release,
 	.unlocked_ioctl	= ch_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= ch_ioctl_compat,
-#endif
+	.compat_ioctl	= compat_ptr_ioctl,
 	.llseek		= noop_llseek,
 };
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 05/24] cg: consolidate compat ioctl handling
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (3 preceding siblings ...)
  2021-07-12  5:47 ` [PATCH 04/24] ch: " Christoph Hellwig
@ 2021-07-12  5:47 ` Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 06/24] scsi: remove scsi_compat_ioctl Christoph Hellwig
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:47 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Merge the native and compat ioctl handlers into a single one using
in_compat_syscall().

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/sg.c | 25 +++----------------------
 1 file changed, 3 insertions(+), 22 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 91e2221bbb0d..0a6655bad5a4 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1166,28 +1166,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 	if (ret != -ENOIOCTLCMD)
 		return ret;
 
+	if (in_compat_syscall())
+		return scsi_compat_ioctl(sdp->device, cmd_in, p);
 	return scsi_ioctl(sdp->device, cmd_in, p);
 }
 
-#ifdef CONFIG_COMPAT
-static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
-{
-	void __user *p = compat_ptr(arg);
-	Sg_device *sdp;
-	Sg_fd *sfp;
-	int ret;
-
-	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
-		return -ENXIO;
-
-	ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
-	if (ret != -ENOIOCTLCMD)
-		return ret;
-
-	return scsi_compat_ioctl(sdp->device, cmd_in, p);
-}
-#endif
-
 static __poll_t
 sg_poll(struct file *filp, poll_table * wait)
 {
@@ -1441,9 +1424,7 @@ static const struct file_operations sg_fops = {
 	.write = sg_write,
 	.poll = sg_poll,
 	.unlocked_ioctl = sg_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl = sg_compat_ioctl,
-#endif
+	.compat_ioctl = compat_ptr_ioctl,
 	.open = sg_open,
 	.mmap = sg_mmap,
 	.release = sg_release,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 06/24] scsi: remove scsi_compat_ioctl
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (4 preceding siblings ...)
  2021-07-12  5:47 ` [PATCH 05/24] cg: " Christoph Hellwig
@ 2021-07-12  5:47 ` Christoph Hellwig
  2021-07-12  5:47 ` [PATCH 07/24] st: simplify ioctl handling Christoph Hellwig
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:47 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Just handle the compat case in scsi_ioctl using in_compat_syscall().

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/ch.c         |  2 --
 drivers/scsi/scsi_ioctl.c | 60 +++++++++++++--------------------------
 drivers/scsi/sd.c         |  2 --
 drivers/scsi/sg.c         |  3 --
 drivers/scsi/sr.c         |  5 +---
 drivers/scsi/st.c         |  2 +-
 include/scsi/scsi_ioctl.h |  1 -
 7 files changed, 22 insertions(+), 53 deletions(-)

diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index e89f226cae5c..87df8cd880e0 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -877,8 +877,6 @@ static long ch_ioctl(struct file *file,
 	}
 
 	default:
-		if (in_compat_syscall())
-			return scsi_compat_ioctl(ch->device, cmd, argp);
 		return scsi_ioctl(ch->device, cmd, argp);
 
 	}
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 0d13610cd6bf..7b2e3cc85e66 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -189,8 +189,17 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg)
 		? -EFAULT: 0;
 }
 
-
-static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg)
+/**
+ * scsi_ioctl - Dispatch ioctl to scsi device
+ * @sdev: scsi device receiving ioctl
+ * @cmd: which ioctl is it
+ * @arg: data associated with ioctl
+ *
+ * Description: The scsi_ioctl() function differs from most ioctls in that it
+ * 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)
 {
 	char scsi_cmd[MAX_COMMAND_SIZE];
 	struct scsi_sense_hdr sense_hdr;
@@ -258,48 +267,19 @@ static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg
 	case SG_SCSI_RESET:
 		return scsi_ioctl_reset(sdev, arg);
 	}
-	return -ENOIOCTLCMD;
-}
-
-/**
- * scsi_ioctl - Dispatch ioctl to scsi device
- * @sdev: scsi device receiving ioctl
- * @cmd: which ioctl is it
- * @arg: data associated with ioctl
- *
- * Description: The scsi_ioctl() function differs from most ioctls in that it
- * 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 ret = scsi_ioctl_common(sdev, cmd, arg);
-
-	if (ret != -ENOIOCTLCMD)
-		return ret;
-
-	if (sdev->host->hostt->ioctl)
-		return sdev->host->hostt->ioctl(sdev, cmd, arg);
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(scsi_ioctl);
 
 #ifdef CONFIG_COMPAT
-int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
-{
-	int ret = scsi_ioctl_common(sdev, cmd, arg);
-
-	if (ret != -ENOIOCTLCMD)
-		return ret;
-
-	if (sdev->host->hostt->compat_ioctl)
+	if (in_compat_syscall()) {
+		if (!sdev->host->hostt->compat_ioctl)
+			return -EINVAL;
 		return sdev->host->hostt->compat_ioctl(sdev, cmd, arg);
-
-	return ret;
-}
-EXPORT_SYMBOL(scsi_compat_ioctl);
+	}
 #endif
+	if (!sdev->host->hostt->ioctl)
+		return -EINVAL;
+	return sdev->host->hostt->ioctl(sdev, cmd, arg);
+}
+EXPORT_SYMBOL(scsi_ioctl);
 
 /*
  * We can process a reset even when a device isn't fully operable.
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f470daf76155..1c9dbdaaef22 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1591,8 +1591,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
 			return error;
 	}
 
-	if (in_compat_syscall())
-		return scsi_compat_ioctl(sdp, cmd, p);
 	return scsi_ioctl(sdp, cmd, p);
 }
 
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 0a6655bad5a4..c3562c2d0dca 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1165,9 +1165,6 @@ 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;
-
-	if (in_compat_syscall())
-		return scsi_compat_ioctl(sdp->device, cmd_in, p);
 	return scsi_ioctl(sdp->device, cmd_in, p);
 }
 
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index b34f06924659..c5e163a659d2 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -584,10 +584,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 			goto put;
 	}
 
-	if (in_compat_syscall())
-		ret = scsi_compat_ioctl(sdev, cmd, argp);
-	else
-		ret = scsi_ioctl(sdev, cmd, argp);
+	ret = scsi_ioctl(sdev, cmd, argp);
 
 put:
 	scsi_autopm_put_device(sdev);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index c6f14540ae03..c3fee73e018e 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3886,7 +3886,7 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd_in, unsigned lon
 	if (ret != -ENOTTY)
 		return ret;
 
-	return scsi_compat_ioctl(STp->device, cmd_in, p);
+	return scsi_ioctl(STp->device, cmd_in, p);
 }
 #endif
 
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index b465799f4d2d..cdb3ba3451e7 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -44,7 +44,6 @@ 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 *);
-extern int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg);
 
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 07/24] st: simplify ioctl handling
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (5 preceding siblings ...)
  2021-07-12  5:47 ` [PATCH 06/24] scsi: remove scsi_compat_ioctl Christoph Hellwig
@ 2021-07-12  5:47 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 08/24] cdrom: remove the call to scsi_cmd_blk_ioctl from cdrom_ioctl Christoph Hellwig
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:47 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Merge st_ioctl_common into st_ioctl and streamline the invocation
of the common ioctl helpers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/st.c | 78 ++++++++++++++++++-----------------------------
 1 file changed, 29 insertions(+), 49 deletions(-)

diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index c3fee73e018e..9274f665bc0f 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3499,8 +3499,9 @@ static int partition_tape(struct scsi_tape *STp, int size)
 
 
 /* The ioctl command */
-static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user *p)
+static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 {
+	void __user *p = (void __user *)arg;
 	int i, cmd_nr, cmd_type, bt;
 	int retval = 0;
 	unsigned int blk;
@@ -3820,73 +3821,52 @@ static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user
 		goto out;
 	}
 	mutex_unlock(&STp->lock);
+
 	switch (cmd_in) {
-		case SCSI_IOCTL_STOP_UNIT:
-			/* unload */
-			retval = scsi_ioctl(STp->device, cmd_in, p);
-			if (!retval) {
-				STp->rew_at_close = 0;
-				STp->ready = ST_NO_TAPE;
-			}
+	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;
+	}
 
-		case SCSI_IOCTL_GET_IDLUN:
-		case SCSI_IOCTL_GET_BUS_NUMBER:
-			break;
-
-		default:
-			if ((cmd_in == SG_IO ||
-			     cmd_in == SCSI_IOCTL_SEND_COMMAND ||
-			     cmd_in == CDROM_SEND_PACKET) &&
-			    !capable(CAP_SYS_RAWIO))
-				i = -EPERM;
-			else
-				i = scsi_cmd_ioctl(STp->disk->queue, STp->disk,
-						   file->f_mode, cmd_in, p);
-			if (i != -ENOTTY)
-				return i;
-			break;
+	retval = scsi_ioctl(STp->device, cmd_in, p);
+	if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) {
+		/* unload */
+		STp->rew_at_close = 0;
+		STp->ready = ST_NO_TAPE;
 	}
-	return -ENOTTY;
+	return retval;
 
  out:
 	mutex_unlock(&STp->lock);
 	return retval;
 }
 
-static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
-{
-	void __user *p = (void __user *)arg;
-	struct scsi_tape *STp = file->private_data;
-	int ret;
-
-	ret = st_ioctl_common(file, cmd_in, p);
-	if (ret != -ENOTTY)
-		return ret;
-
-	return scsi_ioctl(STp->device, cmd_in, p);
-}
-
 #ifdef CONFIG_COMPAT
 static long st_compat_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
 {
-	void __user *p = compat_ptr(arg);
-	struct scsi_tape *STp = file->private_data;
-	int ret;
-
 	/* argument conversion is handled using put_user_mtpos/put_user_mtget */
 	switch (cmd_in) {
 	case MTIOCPOS32:
-		return st_ioctl_common(file, MTIOCPOS, p);
+		cmd_in = MTIOCPOS;
+		break;
 	case MTIOCGET32:
-		return st_ioctl_common(file, MTIOCGET, p);
+		cmd_in = MTIOCGET;
+		break;
 	}
 
-	ret = st_ioctl_common(file, cmd_in, p);
-	if (ret != -ENOTTY)
-		return ret;
-
-	return scsi_ioctl(STp->device, cmd_in, p);
+	return st_ioctl(file, cmd_in, arg);
 }
 #endif
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 08/24] cdrom: remove the call to scsi_cmd_blk_ioctl from cdrom_ioctl
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (6 preceding siblings ...)
  2021-07-12  5:47 ` [PATCH 07/24] st: simplify ioctl handling Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 09/24] scsi_ioctl: remove scsi_cmd_blk_ioctl Christoph Hellwig
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Only the sr driver can handle SCSI passthrough requests, so move the
call to scsi_cmd_blk_ioctl there.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/block/Kconfig        | 1 -
 drivers/block/paride/Kconfig | 1 -
 drivers/cdrom/cdrom.c        | 7 -------
 drivers/scsi/sr.c            | 3 +++
 4 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 63056cfd4b62..4652bcdb9efb 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -74,7 +74,6 @@ config N64CART
 
 config CDROM
 	tristate
-	select BLK_SCSI_REQUEST
 
 config GDROM
 	tristate "SEGA Dreamcast GD-ROM drive"
diff --git a/drivers/block/paride/Kconfig b/drivers/block/paride/Kconfig
index 7c6ae1036927..a295634597ba 100644
--- a/drivers/block/paride/Kconfig
+++ b/drivers/block/paride/Kconfig
@@ -27,7 +27,6 @@ config PARIDE_PCD
 	tristate "Parallel port ATAPI CD-ROMs"
 	depends on PARIDE
 	select CDROM
-	select BLK_SCSI_REQUEST # only for the generic cdrom code
 	help
 	  This option enables the high-level driver for ATAPI CD-ROM devices
 	  connected through a parallel port. If you chose to build PARIDE
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index feb827eefd1a..8882b311bafd 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3357,13 +3357,6 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
 	void __user *argp = (void __user *)arg;
 	int ret;
 
-	/*
-	 * Try the generic SCSI command ioctl's first.
-	 */
-	ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
-	if (ret != -ENOTTY)
-		return ret;
-
 	switch (cmd) {
 	case CDROMMULTISESSION:
 		return cdrom_ioctl_multisession(cdi, argp);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index c5e163a659d2..7948416f40d5 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -579,6 +579,9 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 		break;
 	default:
+		ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
+		if (ret != -ENOTTY)
+			goto put;
 		ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
 		if (ret != -ENOSYS)
 			goto put;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 09/24] scsi_ioctl: remove scsi_cmd_blk_ioctl
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (7 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 08/24] cdrom: remove the call to scsi_cmd_blk_ioctl from cdrom_ioctl Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 10/24] scsi_ioctl: remove scsi_verify_blk_ioctl Christoph Hellwig
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Open code scsi_cmd_blk_ioctl in its two callers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/scsi_ioctl.c     | 13 -------------
 drivers/scsi/sd.c      |  5 ++++-
 drivers/scsi/sr.c      |  8 ++++++--
 include/linux/blkdev.h |  2 --
 4 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index d247431a6853..f8138438c56f 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -854,19 +854,6 @@ int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd)
 }
 EXPORT_SYMBOL(scsi_verify_blk_ioctl);
 
-int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode,
-		       unsigned int cmd, void __user *arg)
-{
-	int ret;
-
-	ret = scsi_verify_blk_ioctl(bd, cmd);
-	if (ret < 0)
-		return ret;
-
-	return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg);
-}
-EXPORT_SYMBOL(scsi_cmd_blk_ioctl);
-
 /**
  * scsi_req_init - initialize certain fields of a scsi_request structure
  * @req: Pointer to a scsi_request structure.
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 1c9dbdaaef22..ca918b0047fa 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1586,7 +1586,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 		break;
 	default:
-		error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
+		error = scsi_verify_blk_ioctl(bdev, cmd);
+		if (error < 0)
+			return error;
+		error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
 		if (error != -ENOTTY)
 			return error;
 	}
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 7948416f40d5..b903e54c57fd 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -556,7 +556,8 @@ static void sr_block_release(struct gendisk *disk, fmode_t mode)
 static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 			  unsigned long arg)
 {
-	struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
+	struct gendisk *disk = bdev->bd_disk;
+	struct scsi_cd *cd = scsi_cd(disk);
 	struct scsi_device *sdev = cd->device;
 	void __user *argp = (void __user *)arg;
 	int ret;
@@ -579,7 +580,10 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 		break;
 	default:
-		ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
+		ret = scsi_verify_blk_ioctl(bdev, cmd);
+		if (ret < 0)
+			goto put;
+		ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
 		if (ret != -ENOTTY)
 			goto put;
 		ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 3177181c4326..19aa3d5429c0 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -889,8 +889,6 @@ extern blk_status_t blk_insert_cloned_request(struct request_queue *q,
 int blk_rq_append_bio(struct request *rq, struct bio *bio);
 extern void blk_queue_split(struct bio **);
 extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int);
-extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t,
-			      unsigned int, void __user *);
 extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
 			  unsigned int, void __user *);
 extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 10/24] scsi_ioctl: remove scsi_verify_blk_ioctl
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (8 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 09/24] scsi_ioctl: remove scsi_cmd_blk_ioctl Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 11/24] scsi: call scsi_cmd_ioctl from scsi_ioctl Christoph Hellwig
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Just verify that the device is no a partition or the caller has admin
privіleges at the beginning of the sr ioctl method manually and open
code the trivial check for sd as well.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/scsi_ioctl.c     | 12 ------------
 drivers/scsi/sd.c      |  8 ++------
 drivers/scsi/sr.c      |  6 +++---
 include/linux/blkdev.h |  1 -
 4 files changed, 5 insertions(+), 22 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index f8138438c56f..ca7b84452d9d 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -842,18 +842,6 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
 }
 EXPORT_SYMBOL(scsi_cmd_ioctl);
 
-int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd)
-{
-	if (bd && !bdev_is_partition(bd))
-		return 0;
-
-	if (capable(CAP_SYS_RAWIO))
-		return 0;
-
-	return -ENOIOCTLCMD;
-}
-EXPORT_SYMBOL(scsi_verify_blk_ioctl);
-
 /**
  * scsi_req_init - initialize certain fields of a scsi_request structure
  * @req: Pointer to a scsi_request structure.
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index ca918b0047fa..7c0b15cd8a0f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1558,9 +1558,8 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
 	SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
 				    "cmd=0x%x\n", disk->disk_name, cmd));
 
-	error = scsi_verify_blk_ioctl(bdev, cmd);
-	if (error < 0)
-		return error;
+	if (bdev_is_partition(bdev) && !capable(CAP_SYS_RAWIO))
+		return -ENOIOCTLCMD;
 
 	/*
 	 * If we are in the middle of error recovery, don't let anyone
@@ -1586,9 +1585,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 		break;
 	default:
-		error = scsi_verify_blk_ioctl(bdev, cmd);
-		if (error < 0)
-			return error;
 		error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
 		if (error != -ENOTTY)
 			return error;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index b903e54c57fd..e6eadba4d638 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -562,6 +562,9 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 	void __user *argp = (void __user *)arg;
 	int ret;
 
+	if (bdev_is_partition(bdev) && !capable(CAP_SYS_RAWIO))
+		return -ENOIOCTLCMD;
+
 	mutex_lock(&cd->lock);
 
 	ret = scsi_ioctl_block_when_processing_errors(sdev, cmd,
@@ -580,9 +583,6 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 		break;
 	default:
-		ret = scsi_verify_blk_ioctl(bdev, cmd);
-		if (ret < 0)
-			goto put;
 		ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
 		if (ret != -ENOTTY)
 			goto put;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 19aa3d5429c0..e2b972a85012 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -888,7 +888,6 @@ extern blk_status_t blk_insert_cloned_request(struct request_queue *q,
 				     struct request *rq);
 int blk_rq_append_bio(struct request *rq, struct bio *bio);
 extern void blk_queue_split(struct bio **);
-extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int);
 extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
 			  unsigned int, void __user *);
 extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 11/24] scsi: call scsi_cmd_ioctl from scsi_ioctl
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (9 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 10/24] scsi_ioctl: remove scsi_verify_blk_ioctl Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 12/24] block: add a queue_max_sectors_bytes helper Christoph Hellwig
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Ensure SCSI ULD only have 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.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/ch.c         |  2 +-
 drivers/scsi/scsi_ioctl.c | 17 ++++++++++++-----
 drivers/scsi/sd.c         | 18 +-----------------
 drivers/scsi/sg.c         |  2 +-
 drivers/scsi/sr.c         | 16 ++--------------
 drivers/scsi/st.c         | 10 +---------
 include/scsi/scsi_ioctl.h |  4 +++-
 7 files changed, 21 insertions(+), 48 deletions(-)

diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 87df8cd880e0..159ab7ccaf7b 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 7c0b15cd8a0f..73388113559e 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1574,23 +1574,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 */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 12/24] block: add a queue_max_sectors_bytes helper
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (10 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 11/24] scsi: call scsi_cmd_ioctl from scsi_ioctl Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-22 17:37   ` Bart Van Assche
  2021-07-22 18:00   ` Martin K. Petersen
  2021-07-12  5:48 ` [PATCH 13/24] bsg: decouple from scsi_cmd_ioctl Christoph Hellwig
                   ` (12 subsequent siblings)
  24 siblings, 2 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Return the max_sectors value in bytes.  Lifted from scsi_ioctl.c.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/scsi_ioctl.c     | 13 ++-----------
 include/linux/blkdev.h |  5 +++++
 2 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index ca7b84452d9d..b46a04a40db4 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -68,18 +68,9 @@ static int sg_set_timeout(struct request_queue *q, int __user *p)
 	return err;
 }
 
-static int max_sectors_bytes(struct request_queue *q)
-{
-	unsigned int max_sectors = queue_max_sectors(q);
-
-	max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9);
-
-	return max_sectors << 9;
-}
-
 static int sg_get_reserved_size(struct request_queue *q, int __user *p)
 {
-	int val = min_t(int, q->sg_reserved_size, max_sectors_bytes(q));
+	int val = min_t(int, q->sg_reserved_size, queue_max_sectors_bytes(q));
 
 	return put_user(val, p);
 }
@@ -94,7 +85,7 @@ static int sg_set_reserved_size(struct request_queue *q, int __user *p)
 	if (size < 0)
 		return -EINVAL;
 
-	q->sg_reserved_size = min(size, max_sectors_bytes(q));
+	q->sg_reserved_size = min(size, queue_max_sectors_bytes(q));
 	return 0;
 }
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index e2b972a85012..c983cd8ecf98 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1373,6 +1373,11 @@ static inline unsigned int queue_max_sectors(const struct request_queue *q)
 	return q->limits.max_sectors;
 }
 
+static inline int queue_max_sectors_bytes(struct request_queue *q)
+{
+	return min_t(unsigned int, queue_max_sectors(q), INT_MAX >> 9) << 9;
+}
+
 static inline unsigned int queue_max_hw_sectors(const struct request_queue *q)
 {
 	return q->limits.max_hw_sectors;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 13/24] bsg: decouple from scsi_cmd_ioctl
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (11 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 12/24] block: add a queue_max_sectors_bytes helper Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 14/24] bsg: move bsg_scsi_ops to drivers/scsi/ Christoph Hellwig
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Decouple bsg from scsi_cmd_ioctl.  This requires a small amount of
code duplication, but will allow moving ll SCSI ioctl handling into
SCSI midlayer.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bsg.c        | 23 +++++++++++++++++++++--
 block/scsi_ioctl.c | 16 ----------------
 2 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/block/bsg.c b/block/bsg.c
index 79b42c5cafeb..e51459011467 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -351,7 +351,10 @@ static int bsg_set_command_q(struct bsg_device *bd, int __user *uarg)
 static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct bsg_device *bd = file->private_data;
+	struct request_queue *q = bd->queue;
 	void __user *uarg = (void __user *) arg;
+	int __user *intp = uarg;
+	int val;
 
 	switch (cmd) {
 	/*
@@ -366,16 +369,32 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	 * SCSI/sg ioctls
 	 */
 	case SG_GET_VERSION_NUM:
+		return put_user(30527, intp);
 	case SCSI_IOCTL_GET_IDLUN:
+		return put_user(0, intp);
 	case SCSI_IOCTL_GET_BUS_NUMBER:
+		return put_user(0, intp);
 	case SG_SET_TIMEOUT:
+		if (get_user(val, intp))
+			return -EFAULT;
+		q->sg_timeout = clock_t_to_jiffies(val);
+		return 0;
 	case SG_GET_TIMEOUT:
+		return jiffies_to_clock_t(q->sg_timeout);
 	case SG_GET_RESERVED_SIZE:
+		return put_user(min_t(int, q->sg_reserved_size,
+				queue_max_sectors_bytes(q)), intp);
 	case SG_SET_RESERVED_SIZE:
+		if (get_user(val, intp))
+			return -EFAULT;
+		if (val < 0)
+			return -EINVAL;
+		q->sg_reserved_size = min(val, queue_max_sectors_bytes(q));
+		return 0;
 	case SG_EMULATED_HOST:
-		return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg);
+		return put_user(1, intp);
 	case SG_IO:
-		return bsg_sg_io(bd->queue, file->f_mode, uarg);
+		return bsg_sg_io(q, file->f_mode, uarg);
 	case SCSI_IOCTL_SEND_COMMAND:
 		pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND\n",
 				current->comm);
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index b46a04a40db4..006da3e829a2 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -43,16 +43,6 @@ static int sg_get_version(int __user *p)
 	return put_user(sg_version_num, p);
 }
 
-static int scsi_get_idlun(struct request_queue *q, int __user *p)
-{
-	return put_user(0, p);
-}
-
-static int scsi_get_bus(struct request_queue *q, int __user *p)
-{
-	return put_user(0, p);
-}
-
 static int sg_get_timeout(struct request_queue *q)
 {
 	return jiffies_to_clock_t(q->sg_timeout);
@@ -769,12 +759,6 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
 		case SG_GET_VERSION_NUM:
 			err = sg_get_version(arg);
 			break;
-		case SCSI_IOCTL_GET_IDLUN:
-			err = scsi_get_idlun(q, arg);
-			break;
-		case SCSI_IOCTL_GET_BUS_NUMBER:
-			err = scsi_get_bus(q, arg);
-			break;
 		case SG_SET_TIMEOUT:
 			err = sg_set_timeout(q, arg);
 			break;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 14/24] bsg: move bsg_scsi_ops to drivers/scsi/
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (12 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 13/24] bsg: decouple from scsi_cmd_ioctl Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-22 18:03   ` Martin K. Petersen
  2021-07-12  5:48 ` [PATCH 15/24] scsi_ioctl: remove scsi_req_init Christoph Hellwig
                   ` (10 subsequent siblings)
  24 siblings, 1 reply; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Move the SCSI-specific bsg code in the SCSI midlayer instead of in the
common bsg code.  This just keeps the common bsg code block/ and also
allows building it as a module.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/Kconfig            | 23 ++--------
 block/Makefile           |  2 +-
 block/bsg.c              | 95 +---------------------------------------
 drivers/scsi/Kconfig     | 13 ++++++
 drivers/scsi/Makefile    |  1 +
 drivers/scsi/scsi_bsg.c  | 95 ++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/scsi_priv.h | 10 +++++
 include/linux/blkdev.h   |  2 +-
 include/linux/bsg.h      | 11 ++---
 9 files changed, 128 insertions(+), 124 deletions(-)
 create mode 100644 drivers/scsi/scsi_bsg.c

diff --git a/block/Kconfig b/block/Kconfig
index fd732aede922..88aa88241795 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -35,29 +35,12 @@ config BLK_SCSI_REQUEST
 config BLK_CGROUP_RWSTAT
 	bool
 
-config BLK_DEV_BSG
-	bool "Block layer SG support v4"
-	default y
-	select BLK_SCSI_REQUEST
-	help
-	  Saying Y here will enable generic SG (SCSI generic) v4 support
-	  for any block device.
-
-	  Unlike SG v3 (aka block/scsi_ioctl.c drivers/scsi/sg.c), SG v4
-	  can handle complicated SCSI commands: tagged variable length cdbs
-	  with bidirectional data transfers and generic request/response
-	  protocols (e.g. Task Management Functions and SMP in Serial
-	  Attached SCSI).
-
-	  This option is required by recent UDEV versions to properly
-	  access device serial numbers, etc.
-
-	  If unsure, say Y.
+config BLK_DEV_BSG_COMMON
+	tristate
 
 config BLK_DEV_BSGLIB
 	bool "Block layer SG support v4 helper lib"
-	select BLK_DEV_BSG
-	select BLK_SCSI_REQUEST
+	select BLK_DEV_BSG_COMMON
 	help
 	  Subsystems will normally enable this if needed. Users will not
 	  normally need to manually enable this.
diff --git a/block/Makefile b/block/Makefile
index bfbe4e13ca1e..f37d532c8da5 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-sysfs.o \
 
 obj-$(CONFIG_BOUNCE)		+= bounce.o
 obj-$(CONFIG_BLK_SCSI_REQUEST)	+= scsi_ioctl.o
-obj-$(CONFIG_BLK_DEV_BSG)	+= bsg.o
+obj-$(CONFIG_BLK_DEV_BSG_COMMON) += bsg.o
 obj-$(CONFIG_BLK_DEV_BSGLIB)	+= bsg-lib.o
 obj-$(CONFIG_BLK_CGROUP)	+= blk-cgroup.o
 obj-$(CONFIG_BLK_CGROUP_RWSTAT)	+= blk-cgroup-rwstat.o
diff --git a/block/bsg.c b/block/bsg.c
index e51459011467..6062c0931530 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -15,9 +15,6 @@
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_driver.h>
 #include <scsi/sg.h>
 
 #define BSG_DESCRIPTION	"Block layer SCSI generic (bsg) driver"
@@ -54,86 +51,6 @@ static inline struct hlist_head *bsg_dev_idx_hash(int index)
 
 #define uptr64(val) ((void __user *)(uintptr_t)(val))
 
-static int bsg_scsi_check_proto(struct sg_io_v4 *hdr)
-{
-	if (hdr->protocol != BSG_PROTOCOL_SCSI  ||
-	    hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_CMD)
-		return -EINVAL;
-	return 0;
-}
-
-static int bsg_scsi_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
-		fmode_t mode)
-{
-	struct scsi_request *sreq = scsi_req(rq);
-
-	if (hdr->dout_xfer_len && hdr->din_xfer_len) {
-		pr_warn_once("BIDI support in bsg has been removed.\n");
-		return -EOPNOTSUPP;
-	}
-
-	sreq->cmd_len = hdr->request_len;
-	if (sreq->cmd_len > BLK_MAX_CDB) {
-		sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL);
-		if (!sreq->cmd)
-			return -ENOMEM;
-	}
-
-	if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len))
-		return -EFAULT;
-	if (blk_verify_command(sreq->cmd, mode))
-		return -EPERM;
-	return 0;
-}
-
-static int bsg_scsi_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
-{
-	struct scsi_request *sreq = scsi_req(rq);
-	int ret = 0;
-
-	/*
-	 * fill in all the output members
-	 */
-	hdr->device_status = sreq->result & 0xff;
-	hdr->transport_status = host_byte(sreq->result);
-	hdr->driver_status = 0;
-	if (scsi_status_is_check_condition(sreq->result))
-		hdr->driver_status = DRIVER_SENSE;
-	hdr->info = 0;
-	if (hdr->device_status || hdr->transport_status || hdr->driver_status)
-		hdr->info |= SG_INFO_CHECK;
-	hdr->response_len = 0;
-
-	if (sreq->sense_len && hdr->response) {
-		int len = min_t(unsigned int, hdr->max_response_len,
-					sreq->sense_len);
-
-		if (copy_to_user(uptr64(hdr->response), sreq->sense, len))
-			ret = -EFAULT;
-		else
-			hdr->response_len = len;
-	}
-
-	if (rq_data_dir(rq) == READ)
-		hdr->din_resid = sreq->resid_len;
-	else
-		hdr->dout_resid = sreq->resid_len;
-
-	return ret;
-}
-
-static void bsg_scsi_free_rq(struct request *rq)
-{
-	scsi_req_free_cmd(scsi_req(rq));
-}
-
-static const struct bsg_ops bsg_scsi_ops = {
-	.check_proto		= bsg_scsi_check_proto,
-	.fill_hdr		= bsg_scsi_fill_hdr,
-	.complete_rq		= bsg_scsi_complete_rq,
-	.free_rq		= bsg_scsi_free_rq,
-};
-
 static int bsg_sg_io(struct request_queue *q, fmode_t mode, void __user *uarg)
 {
 	struct request *rq;
@@ -486,17 +403,7 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
 	mutex_unlock(&bsg_mutex);
 	return ret;
 }
-
-int bsg_scsi_register_queue(struct request_queue *q, struct device *parent)
-{
-	if (!blk_queue_scsi_passthrough(q)) {
-		WARN_ONCE(true, "Attempt to register a non-SCSI queue\n");
-		return -EINVAL;
-	}
-
-	return bsg_register_queue(q, parent, dev_name(parent), &bsg_scsi_ops);
-}
-EXPORT_SYMBOL_GPL(bsg_scsi_register_queue);
+EXPORT_SYMBOL_GPL(bsg_register_queue);
 
 static struct cdev bsg_cdev;
 
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 8f44d433e06e..86ecab196dfd 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -20,6 +20,7 @@ config SCSI
 	select SCSI_DMA if HAS_DMA
 	select SG_POOL
 	select BLK_SCSI_REQUEST
+	select BLK_DEV_BSG_COMMON if BLK_DEV_BSG
 	help
 	  If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
 	  any other SCSI device under Linux, say Y and make sure that you know
@@ -140,6 +141,18 @@ config CHR_DEV_SG
 
 	  If unsure, say N.
 
+config BLK_DEV_BSG
+	bool "/dev/bsg support (SG v4)"
+	depends on SCSI
+	default y
+	help
+	  Saying Y here will enable generic SG (SCSI generic) v4 support
+	  for any SCSI device.
+
+	  This option is required by UDEV to access device serial numbers, etc.
+
+	  If unsure, say Y.
+
 config CHR_DEV_SCH
 	tristate "SCSI media changer support"
 	depends on SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1748d1ec1338..240b831b5a11 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -168,6 +168,7 @@ scsi_mod-$(CONFIG_BLK_DEBUG_FS)	+= scsi_debugfs.o
 scsi_mod-y			+= scsi_trace.o scsi_logging.o
 scsi_mod-$(CONFIG_PM)		+= scsi_pm.o
 scsi_mod-$(CONFIG_SCSI_DH)	+= scsi_dh.o
+scsi_mod-$(CONFIG_BLK_DEV_BSG)	+= scsi_bsg.o
 
 hv_storvsc-y			:= storvsc_drv.o
 
diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
new file mode 100644
index 000000000000..ac5be941f5e8
--- /dev/null
+++ b/drivers/scsi/scsi_bsg.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bsg.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/sg.h>
+#include "scsi_priv.h"
+
+#define uptr64(val) ((void __user *)(uintptr_t)(val))
+
+static int bsg_scsi_check_proto(struct sg_io_v4 *hdr)
+{
+	if (hdr->protocol != BSG_PROTOCOL_SCSI  ||
+	    hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_CMD)
+		return -EINVAL;
+	return 0;
+}
+
+static int bsg_scsi_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
+		fmode_t mode)
+{
+	struct scsi_request *sreq = scsi_req(rq);
+
+	if (hdr->dout_xfer_len && hdr->din_xfer_len) {
+		pr_warn_once("BIDI support in bsg has been removed.\n");
+		return -EOPNOTSUPP;
+	}
+
+	sreq->cmd_len = hdr->request_len;
+	if (sreq->cmd_len > BLK_MAX_CDB) {
+		sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL);
+		if (!sreq->cmd)
+			return -ENOMEM;
+	}
+
+	if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len))
+		return -EFAULT;
+	if (blk_verify_command(sreq->cmd, mode))
+		return -EPERM;
+	return 0;
+}
+
+static int bsg_scsi_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
+{
+	struct scsi_request *sreq = scsi_req(rq);
+	int ret = 0;
+
+	/*
+	 * fill in all the output members
+	 */
+	hdr->device_status = sreq->result & 0xff;
+	hdr->transport_status = host_byte(sreq->result);
+	hdr->driver_status = 0;
+	if (scsi_status_is_check_condition(sreq->result))
+		hdr->driver_status = DRIVER_SENSE;
+	hdr->info = 0;
+	if (hdr->device_status || hdr->transport_status || hdr->driver_status)
+		hdr->info |= SG_INFO_CHECK;
+	hdr->response_len = 0;
+
+	if (sreq->sense_len && hdr->response) {
+		int len = min_t(unsigned int, hdr->max_response_len,
+					sreq->sense_len);
+
+		if (copy_to_user(uptr64(hdr->response), sreq->sense, len))
+			ret = -EFAULT;
+		else
+			hdr->response_len = len;
+	}
+
+	if (rq_data_dir(rq) == READ)
+		hdr->din_resid = sreq->resid_len;
+	else
+		hdr->dout_resid = sreq->resid_len;
+
+	return ret;
+}
+
+static void bsg_scsi_free_rq(struct request *rq)
+{
+	scsi_req_free_cmd(scsi_req(rq));
+}
+
+static const struct bsg_ops bsg_scsi_ops = {
+	.check_proto		= bsg_scsi_check_proto,
+	.fill_hdr		= bsg_scsi_fill_hdr,
+	.complete_rq		= bsg_scsi_complete_rq,
+	.free_rq		= bsg_scsi_free_rq,
+};
+
+int bsg_scsi_register_queue(struct request_queue *q, struct device *parent)
+{
+	return bsg_register_queue(q, parent, dev_name(parent), &bsg_scsi_ops);
+}
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 75d6f23e4fff..cb3cc7d41037 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -181,6 +181,16 @@ static inline void scsi_dh_add_device(struct scsi_device *sdev) { }
 static inline void scsi_dh_release_device(struct scsi_device *sdev) { }
 #endif
 
+#ifdef CONFIG_BLK_DEV_BSG
+int bsg_scsi_register_queue(struct request_queue *q, struct device *parent);
+#else
+static inline int bsg_scsi_register_queue(struct request_queue *q,
+		struct device *parent)
+{
+	return 0;
+}
+#endif
+
 extern int scsi_device_max_queue_depth(struct scsi_device *sdev);
 
 /* 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index c983cd8ecf98..b525481abfed 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -537,7 +537,7 @@ struct request_queue {
 
 	int			mq_freeze_depth;
 
-#if defined(CONFIG_BLK_DEV_BSG)
+#if defined(CONFIG_BLK_DEV_BSG_COMMON)
 	struct bsg_class_device bsg_dev;
 #endif
 
diff --git a/include/linux/bsg.h b/include/linux/bsg.h
index dac37b6e00ec..b887da20bd41 100644
--- a/include/linux/bsg.h
+++ b/include/linux/bsg.h
@@ -5,8 +5,9 @@
 #include <uapi/linux/bsg.h>
 
 struct request;
+struct request_queue;
 
-#ifdef CONFIG_BLK_DEV_BSG
+#ifdef CONFIG_BLK_DEV_BSG_COMMON
 struct bsg_ops {
 	int	(*check_proto)(struct sg_io_v4 *hdr);
 	int	(*fill_hdr)(struct request *rq, struct sg_io_v4 *hdr,
@@ -24,16 +25,10 @@ struct bsg_class_device {
 
 int bsg_register_queue(struct request_queue *q, struct device *parent,
 		const char *name, const struct bsg_ops *ops);
-int bsg_scsi_register_queue(struct request_queue *q, struct device *parent);
 void bsg_unregister_queue(struct request_queue *q);
 #else
-static inline int bsg_scsi_register_queue(struct request_queue *q,
-		struct device *parent)
-{
-	return 0;
-}
 static inline void bsg_unregister_queue(struct request_queue *q)
 {
 }
-#endif /* CONFIG_BLK_DEV_BSG */
+#endif /* CONFIG_BLK_DEV_BSG_COMMON */
 #endif /* _LINUX_BSG_H */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 15/24] scsi_ioctl: remove scsi_req_init
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (13 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 14/24] bsg: move bsg_scsi_ops to drivers/scsi/ Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 16/24] scsi_ioctl: move scsi_command_size_tbl to scsi_common.c Christoph Hellwig
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Merge scsi_req_init into its only caller.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/scsi_ioctl.c          | 15 ---------------
 drivers/scsi/scsi_lib.c     |  7 ++++++-
 include/scsi/scsi_request.h |  2 --
 3 files changed, 6 insertions(+), 18 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 006da3e829a2..76fbe5287876 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -817,21 +817,6 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
 }
 EXPORT_SYMBOL(scsi_cmd_ioctl);
 
-/**
- * scsi_req_init - initialize certain fields of a scsi_request structure
- * @req: Pointer to a scsi_request structure.
- * Initializes .__cmd[], .cmd, .cmd_len and .sense_len but no other members
- * of struct scsi_request.
- */
-void scsi_req_init(struct scsi_request *req)
-{
-	memset(req->__cmd, 0, sizeof(req->__cmd));
-	req->cmd = req->__cmd;
-	req->cmd_len = BLK_MAX_CDB;
-	req->sense_len = 0;
-}
-EXPORT_SYMBOL(scsi_req_init);
-
 static int __init blk_scsi_ioctl_init(void)
 {
 	blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index c9a91a52e637..4914b01e8e59 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1082,8 +1082,13 @@ EXPORT_SYMBOL(scsi_alloc_sgtables);
 static void scsi_initialize_rq(struct request *rq)
 {
 	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+	struct scsi_request *req = &cmd->req;
+
+	memset(req->__cmd, 0, sizeof(req->__cmd));
+	req->cmd = req->__cmd;
+	req->cmd_len = BLK_MAX_CDB;
+	req->sense_len = 0;
 
-	scsi_req_init(&cmd->req);
 	init_rcu_head(&cmd->rcu);
 	cmd->jiffies_at_alloc = jiffies;
 	cmd->retries = 0;
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
index b06f28c74908..9129b23e12bc 100644
--- a/include/scsi/scsi_request.h
+++ b/include/scsi/scsi_request.h
@@ -28,6 +28,4 @@ static inline void scsi_req_free_cmd(struct scsi_request *req)
 		kfree(req->cmd);
 }
 
-void scsi_req_init(struct scsi_request *req);
-
 #endif /* _SCSI_SCSI_REQUEST_H */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 16/24] scsi_ioctl: move scsi_command_size_tbl to scsi_common.c
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (14 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 15/24] scsi_ioctl: remove scsi_req_init Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 17/24] scsi_ioctl: simplify SCSI passthrough permission checking Christoph Hellwig
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Move the SCSI command size table towards the rest of the common SCSI
code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/scsi_ioctl.c         | 8 --------
 drivers/scsi/scsi_common.c | 6 ++++++
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 76fbe5287876..ccc06b8e88c6 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -29,14 +29,6 @@ struct blk_cmd_filter {
 
 static struct blk_cmd_filter blk_default_cmd_filter;
 
-/* Command group 3 is reserved and should never be used.  */
-const unsigned char scsi_command_size_tbl[8] =
-{
-	6, 10, 10, 12,
-	16, 12, 10, 10
-};
-EXPORT_SYMBOL(scsi_command_size_tbl);
-
 static int sg_get_version(int __user *p)
 {
 	static const int sg_version_num = 30527;
diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c
index 90349498f686..8aac4e5e8c4c 100644
--- a/drivers/scsi/scsi_common.c
+++ b/drivers/scsi/scsi_common.c
@@ -10,6 +10,12 @@
 #include <asm/unaligned.h>
 #include <scsi/scsi_common.h>
 
+/* Command group 3 is reserved and should never be used.  */
+const unsigned char scsi_command_size_tbl[8] = {
+	6, 10, 10, 12, 16, 12, 10, 10
+};
+EXPORT_SYMBOL(scsi_command_size_tbl);
+
 /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI.
  * You may not alter any existing entry (although adding new ones is
  * encouraged once assigned by ANSI/INCITS T10).
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 17/24] scsi_ioctl: simplify SCSI passthrough permission checking
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (15 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 16/24] scsi_ioctl: move scsi_command_size_tbl to scsi_common.c Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-22 17:47   ` Bart Van Assche
  2021-07-12  5:48 ` [PATCH 18/24] scsi_ioctl: move all "block layer" SCSI ioctl handling to drivers/scsi Christoph Hellwig
                   ` (7 subsequent siblings)
  24 siblings, 1 reply; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Remove the separate command filter structure and just use a switch
statement (which also cought two duplicate commands), return a bool
and give the function a sensible name.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/scsi_ioctl.c      | 213 ++++++++++++++++++----------------------
 drivers/scsi/scsi_bsg.c |   2 +-
 drivers/scsi/sg.c       |   5 +-
 include/linux/blkdev.h  |   2 +-
 4 files changed, 98 insertions(+), 124 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index ccc06b8e88c6..f28570c8a4ed 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -22,13 +22,6 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/sg.h>
 
-struct blk_cmd_filter {
-	unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
-	unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
-};
-
-static struct blk_cmd_filter blk_default_cmd_filter;
-
 static int sg_get_version(int __user *p)
 {
 	static const int sg_version_num = 30527;
@@ -80,115 +73,102 @@ static int sg_emulated_host(struct request_queue *q, int __user *p)
 	return put_user(1, p);
 }
 
-static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
-{
-	/* Basic read-only commands */
-	__set_bit(TEST_UNIT_READY, filter->read_ok);
-	__set_bit(REQUEST_SENSE, filter->read_ok);
-	__set_bit(READ_6, filter->read_ok);
-	__set_bit(READ_10, filter->read_ok);
-	__set_bit(READ_12, filter->read_ok);
-	__set_bit(READ_16, filter->read_ok);
-	__set_bit(READ_BUFFER, filter->read_ok);
-	__set_bit(READ_DEFECT_DATA, filter->read_ok);
-	__set_bit(READ_CAPACITY, filter->read_ok);
-	__set_bit(READ_LONG, filter->read_ok);
-	__set_bit(INQUIRY, filter->read_ok);
-	__set_bit(MODE_SENSE, filter->read_ok);
-	__set_bit(MODE_SENSE_10, filter->read_ok);
-	__set_bit(LOG_SENSE, filter->read_ok);
-	__set_bit(START_STOP, filter->read_ok);
-	__set_bit(GPCMD_VERIFY_10, filter->read_ok);
-	__set_bit(VERIFY_16, filter->read_ok);
-	__set_bit(REPORT_LUNS, filter->read_ok);
-	__set_bit(SERVICE_ACTION_IN_16, filter->read_ok);
-	__set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok);
-	__set_bit(MAINTENANCE_IN, filter->read_ok);
-	__set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok);
-
-	/* Audio CD commands */
-	__set_bit(GPCMD_PLAY_CD, filter->read_ok);
-	__set_bit(GPCMD_PLAY_AUDIO_10, filter->read_ok);
-	__set_bit(GPCMD_PLAY_AUDIO_MSF, filter->read_ok);
-	__set_bit(GPCMD_PLAY_AUDIO_TI, filter->read_ok);
-	__set_bit(GPCMD_PAUSE_RESUME, filter->read_ok);
-
-	/* CD/DVD data reading */
-	__set_bit(GPCMD_READ_CD, filter->read_ok);
-	__set_bit(GPCMD_READ_CD_MSF, filter->read_ok);
-	__set_bit(GPCMD_READ_DISC_INFO, filter->read_ok);
-	__set_bit(GPCMD_READ_CDVD_CAPACITY, filter->read_ok);
-	__set_bit(GPCMD_READ_DVD_STRUCTURE, filter->read_ok);
-	__set_bit(GPCMD_READ_HEADER, filter->read_ok);
-	__set_bit(GPCMD_READ_TRACK_RZONE_INFO, filter->read_ok);
-	__set_bit(GPCMD_READ_SUBCHANNEL, filter->read_ok);
-	__set_bit(GPCMD_READ_TOC_PMA_ATIP, filter->read_ok);
-	__set_bit(GPCMD_REPORT_KEY, filter->read_ok);
-	__set_bit(GPCMD_SCAN, filter->read_ok);
-	__set_bit(GPCMD_GET_CONFIGURATION, filter->read_ok);
-	__set_bit(GPCMD_READ_FORMAT_CAPACITIES, filter->read_ok);
-	__set_bit(GPCMD_GET_EVENT_STATUS_NOTIFICATION, filter->read_ok);
-	__set_bit(GPCMD_GET_PERFORMANCE, filter->read_ok);
-	__set_bit(GPCMD_SEEK, filter->read_ok);
-	__set_bit(GPCMD_STOP_PLAY_SCAN, filter->read_ok);
-
-	/* Basic writing commands */
-	__set_bit(WRITE_6, filter->write_ok);
-	__set_bit(WRITE_10, filter->write_ok);
-	__set_bit(WRITE_VERIFY, filter->write_ok);
-	__set_bit(WRITE_12, filter->write_ok);
-	__set_bit(WRITE_VERIFY_12, filter->write_ok);
-	__set_bit(WRITE_16, filter->write_ok);
-	__set_bit(WRITE_LONG, filter->write_ok);
-	__set_bit(WRITE_LONG_2, filter->write_ok);
-	__set_bit(WRITE_SAME, filter->write_ok);
-	__set_bit(WRITE_SAME_16, filter->write_ok);
-	__set_bit(WRITE_SAME_32, filter->write_ok);
-	__set_bit(ERASE, filter->write_ok);
-	__set_bit(GPCMD_MODE_SELECT_10, filter->write_ok);
-	__set_bit(MODE_SELECT, filter->write_ok);
-	__set_bit(LOG_SELECT, filter->write_ok);
-	__set_bit(GPCMD_BLANK, filter->write_ok);
-	__set_bit(GPCMD_CLOSE_TRACK, filter->write_ok);
-	__set_bit(GPCMD_FLUSH_CACHE, filter->write_ok);
-	__set_bit(GPCMD_FORMAT_UNIT, filter->write_ok);
-	__set_bit(GPCMD_REPAIR_RZONE_TRACK, filter->write_ok);
-	__set_bit(GPCMD_RESERVE_RZONE_TRACK, filter->write_ok);
-	__set_bit(GPCMD_SEND_DVD_STRUCTURE, filter->write_ok);
-	__set_bit(GPCMD_SEND_EVENT, filter->write_ok);
-	__set_bit(GPCMD_SEND_KEY, filter->write_ok);
-	__set_bit(GPCMD_SEND_OPC, filter->write_ok);
-	__set_bit(GPCMD_SEND_CUE_SHEET, filter->write_ok);
-	__set_bit(GPCMD_SET_SPEED, filter->write_ok);
-	__set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok);
-	__set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok);
-	__set_bit(GPCMD_SET_STREAMING, filter->write_ok);
-	__set_bit(GPCMD_SET_READ_AHEAD, filter->write_ok);
-
-	/* ZBC Commands */
-	__set_bit(ZBC_OUT, filter->write_ok);
-	__set_bit(ZBC_IN, filter->read_ok);
-}
-
-int blk_verify_command(unsigned char *cmd, fmode_t mode)
+bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
 {
-	struct blk_cmd_filter *filter = &blk_default_cmd_filter;
-
 	/* root can do any command. */
 	if (capable(CAP_SYS_RAWIO))
-		return 0;
+		return true;
 
 	/* Anybody who can open the device can do a read-safe command */
-	if (test_bit(cmd[0], filter->read_ok))
-		return 0;
-
-	/* Write-safe commands require a writable open */
-	if (test_bit(cmd[0], filter->write_ok) && (mode & FMODE_WRITE))
-		return 0;
-
-	return -EPERM;
+	switch (cmd[0]) {
+	/* Basic read-only commands */
+	case TEST_UNIT_READY:
+	case REQUEST_SENSE:
+	case READ_6:
+	case READ_10:
+	case READ_12:
+	case READ_16:
+	case READ_BUFFER:
+	case READ_DEFECT_DATA:
+	case READ_CAPACITY: /* also GPCMD_READ_CDVD_CAPACITY */
+	case READ_LONG:
+	case INQUIRY:
+	case MODE_SENSE:
+	case MODE_SENSE_10:
+	case LOG_SENSE:
+	case START_STOP:
+	case GPCMD_VERIFY_10:
+	case VERIFY_16:
+	case REPORT_LUNS:
+	case SERVICE_ACTION_IN_16:
+	case RECEIVE_DIAGNOSTIC:
+	case MAINTENANCE_IN: /* also GPCMD_SEND_KEY, which is a write command */
+	case GPCMD_READ_BUFFER_CAPACITY:
+	/* Audio CD commands */
+	case GPCMD_PLAY_CD:
+	case GPCMD_PLAY_AUDIO_10:
+	case GPCMD_PLAY_AUDIO_MSF:
+	case GPCMD_PLAY_AUDIO_TI:
+	case GPCMD_PAUSE_RESUME:
+	/* CD/DVD data reading */
+	case GPCMD_READ_CD:
+	case GPCMD_READ_CD_MSF:
+	case GPCMD_READ_DISC_INFO:
+	case GPCMD_READ_DVD_STRUCTURE:
+	case GPCMD_READ_HEADER:
+	case GPCMD_READ_TRACK_RZONE_INFO:
+	case GPCMD_READ_SUBCHANNEL:
+	case GPCMD_READ_TOC_PMA_ATIP:
+	case GPCMD_REPORT_KEY:
+	case GPCMD_SCAN:
+	case GPCMD_GET_CONFIGURATION:
+	case GPCMD_READ_FORMAT_CAPACITIES:
+	case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
+	case GPCMD_GET_PERFORMANCE:
+	case GPCMD_SEEK:
+	case GPCMD_STOP_PLAY_SCAN:
+	/* ZBC */
+	case ZBC_IN:
+		return true;
+	/* Basic writing commands */
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_VERIFY:
+	case WRITE_12:
+	case WRITE_VERIFY_12:
+	case WRITE_16:
+	case WRITE_LONG:
+	case WRITE_LONG_2:
+	case WRITE_SAME:
+	case WRITE_SAME_16:
+	case WRITE_SAME_32:
+	case ERASE:
+	case GPCMD_MODE_SELECT_10:
+	case MODE_SELECT:
+	case LOG_SELECT:
+	case GPCMD_BLANK:
+	case GPCMD_CLOSE_TRACK:
+	case GPCMD_FLUSH_CACHE:
+	case GPCMD_FORMAT_UNIT:
+	case GPCMD_REPAIR_RZONE_TRACK:
+	case GPCMD_RESERVE_RZONE_TRACK:
+	case GPCMD_SEND_DVD_STRUCTURE:
+	case GPCMD_SEND_EVENT:
+	case GPCMD_SEND_OPC:
+	case GPCMD_SEND_CUE_SHEET:
+	case GPCMD_SET_SPEED:
+	case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+	case GPCMD_LOAD_UNLOAD:
+	case GPCMD_SET_STREAMING:
+	case GPCMD_SET_READ_AHEAD:
+	/* ZBC */
+	case ZBC_OUT:
+		return (mode & FMODE_WRITE);
+	default:
+		return false;
+	}
 }
-EXPORT_SYMBOL(blk_verify_command);
+EXPORT_SYMBOL(scsi_cmd_allowed);
 
 static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
 			     struct sg_io_hdr *hdr, fmode_t mode)
@@ -197,7 +177,7 @@ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
 
 	if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len))
 		return -EFAULT;
-	if (blk_verify_command(req->cmd, mode))
+	if (!scsi_cmd_allowed(req->cmd, mode))
 		return -EPERM;
 
 	/*
@@ -428,8 +408,8 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
 	if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
 		goto error;
 
-	err = blk_verify_command(req->cmd, mode);
-	if (err)
+	err = -EPERM;
+	if (!scsi_cmd_allowed(req->cmd, mode))
 		goto error;
 
 	/* default.  possible overriden later */
@@ -808,10 +788,3 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
 	return err;
 }
 EXPORT_SYMBOL(scsi_cmd_ioctl);
-
-static int __init blk_scsi_ioctl_init(void)
-{
-	blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
-	return 0;
-}
-fs_initcall(blk_scsi_ioctl_init);
diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
index ac5be941f5e8..e1e1672c9762 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -36,7 +36,7 @@ static int bsg_scsi_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
 
 	if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len))
 		return -EFAULT;
-	if (blk_verify_command(sreq->cmd, mode))
+	if (!scsi_cmd_allowed(sreq->cmd, mode))
 		return -EPERM;
 	return 0;
 }
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 6cb1e4b6eac2..c86fa4476334 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -238,8 +238,9 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd)
 
 	if (sfp->parentdp->device->type == TYPE_SCANNER)
 		return 0;
-
-	return blk_verify_command(cmd, filp->f_mode);
+	if (!scsi_cmd_allowed(cmd, filp->f_mode))
+		return -EPERM;
+	return 0;
 }
 
 static int
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b525481abfed..3522e8cbee26 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1343,7 +1343,7 @@ static inline int sb_issue_zeroout(struct super_block *sb, sector_t block,
 				    gfp_mask, 0);
 }
 
-extern int blk_verify_command(unsigned char *cmd, fmode_t mode);
+bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode);
 
 static inline bool bdev_is_partition(struct block_device *bdev)
 {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 18/24] scsi_ioctl: move all "block layer" SCSI ioctl handling to drivers/scsi
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (16 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 17/24] scsi_ioctl: simplify SCSI passthrough permission checking Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-22 18:06   ` Martin K. Petersen
  2021-07-12  5:48 ` [PATCH 19/24] scsi: rename CONFIG_BLK_SCSI_REQUEST to CONFIG_SCSI_COMMON Christoph Hellwig
                   ` (6 subsequent siblings)
  24 siblings, 1 reply; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Merge the ioctl handling in block/scsi_ioctl.c into its only caller in
drivers/scsi/scsi_ioctl.c.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/Makefile            |   1 -
 block/scsi_ioctl.c        | 790 --------------------------------------
 drivers/scsi/scsi_ioctl.c | 734 ++++++++++++++++++++++++++++++++++-
 include/linux/blkdev.h    |  11 -
 include/scsi/scsi_ioctl.h |   6 +
 5 files changed, 735 insertions(+), 807 deletions(-)
 delete mode 100644 block/scsi_ioctl.c

diff --git a/block/Makefile b/block/Makefile
index f37d532c8da5..640afba070fd 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-sysfs.o \
 			disk-events.o
 
 obj-$(CONFIG_BOUNCE)		+= bounce.o
-obj-$(CONFIG_BLK_SCSI_REQUEST)	+= scsi_ioctl.o
 obj-$(CONFIG_BLK_DEV_BSG_COMMON) += bsg.o
 obj-$(CONFIG_BLK_DEV_BSGLIB)	+= bsg-lib.o
 obj-$(CONFIG_BLK_CGROUP)	+= blk-cgroup.o
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
deleted file mode 100644
index f28570c8a4ed..000000000000
--- a/block/scsi_ioctl.c
+++ /dev/null
@@ -1,790 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
- */
-#include <linux/compat.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/blkdev.h>
-#include <linux/capability.h>
-#include <linux/completion.h>
-#include <linux/cdrom.h>
-#include <linux/ratelimit.h>
-#include <linux/slab.h>
-#include <linux/times.h>
-#include <linux/uio.h>
-#include <linux/uaccess.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/sg.h>
-
-static int sg_get_version(int __user *p)
-{
-	static const int sg_version_num = 30527;
-	return put_user(sg_version_num, p);
-}
-
-static int sg_get_timeout(struct request_queue *q)
-{
-	return jiffies_to_clock_t(q->sg_timeout);
-}
-
-static int sg_set_timeout(struct request_queue *q, int __user *p)
-{
-	int timeout, err = get_user(timeout, p);
-
-	if (!err)
-		q->sg_timeout = clock_t_to_jiffies(timeout);
-
-	return err;
-}
-
-static int sg_get_reserved_size(struct request_queue *q, int __user *p)
-{
-	int val = min_t(int, q->sg_reserved_size, queue_max_sectors_bytes(q));
-
-	return put_user(val, p);
-}
-
-static int sg_set_reserved_size(struct request_queue *q, int __user *p)
-{
-	int size, err = get_user(size, p);
-
-	if (err)
-		return err;
-
-	if (size < 0)
-		return -EINVAL;
-
-	q->sg_reserved_size = min(size, queue_max_sectors_bytes(q));
-	return 0;
-}
-
-/*
- * will always return that we are ATAPI even for a real SCSI drive, I'm not
- * so sure this is worth doing anything about (why would you care??)
- */
-static int sg_emulated_host(struct request_queue *q, int __user *p)
-{
-	return put_user(1, p);
-}
-
-bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
-{
-	/* root can do any command. */
-	if (capable(CAP_SYS_RAWIO))
-		return true;
-
-	/* Anybody who can open the device can do a read-safe command */
-	switch (cmd[0]) {
-	/* Basic read-only commands */
-	case TEST_UNIT_READY:
-	case REQUEST_SENSE:
-	case READ_6:
-	case READ_10:
-	case READ_12:
-	case READ_16:
-	case READ_BUFFER:
-	case READ_DEFECT_DATA:
-	case READ_CAPACITY: /* also GPCMD_READ_CDVD_CAPACITY */
-	case READ_LONG:
-	case INQUIRY:
-	case MODE_SENSE:
-	case MODE_SENSE_10:
-	case LOG_SENSE:
-	case START_STOP:
-	case GPCMD_VERIFY_10:
-	case VERIFY_16:
-	case REPORT_LUNS:
-	case SERVICE_ACTION_IN_16:
-	case RECEIVE_DIAGNOSTIC:
-	case MAINTENANCE_IN: /* also GPCMD_SEND_KEY, which is a write command */
-	case GPCMD_READ_BUFFER_CAPACITY:
-	/* Audio CD commands */
-	case GPCMD_PLAY_CD:
-	case GPCMD_PLAY_AUDIO_10:
-	case GPCMD_PLAY_AUDIO_MSF:
-	case GPCMD_PLAY_AUDIO_TI:
-	case GPCMD_PAUSE_RESUME:
-	/* CD/DVD data reading */
-	case GPCMD_READ_CD:
-	case GPCMD_READ_CD_MSF:
-	case GPCMD_READ_DISC_INFO:
-	case GPCMD_READ_DVD_STRUCTURE:
-	case GPCMD_READ_HEADER:
-	case GPCMD_READ_TRACK_RZONE_INFO:
-	case GPCMD_READ_SUBCHANNEL:
-	case GPCMD_READ_TOC_PMA_ATIP:
-	case GPCMD_REPORT_KEY:
-	case GPCMD_SCAN:
-	case GPCMD_GET_CONFIGURATION:
-	case GPCMD_READ_FORMAT_CAPACITIES:
-	case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
-	case GPCMD_GET_PERFORMANCE:
-	case GPCMD_SEEK:
-	case GPCMD_STOP_PLAY_SCAN:
-	/* ZBC */
-	case ZBC_IN:
-		return true;
-	/* Basic writing commands */
-	case WRITE_6:
-	case WRITE_10:
-	case WRITE_VERIFY:
-	case WRITE_12:
-	case WRITE_VERIFY_12:
-	case WRITE_16:
-	case WRITE_LONG:
-	case WRITE_LONG_2:
-	case WRITE_SAME:
-	case WRITE_SAME_16:
-	case WRITE_SAME_32:
-	case ERASE:
-	case GPCMD_MODE_SELECT_10:
-	case MODE_SELECT:
-	case LOG_SELECT:
-	case GPCMD_BLANK:
-	case GPCMD_CLOSE_TRACK:
-	case GPCMD_FLUSH_CACHE:
-	case GPCMD_FORMAT_UNIT:
-	case GPCMD_REPAIR_RZONE_TRACK:
-	case GPCMD_RESERVE_RZONE_TRACK:
-	case GPCMD_SEND_DVD_STRUCTURE:
-	case GPCMD_SEND_EVENT:
-	case GPCMD_SEND_OPC:
-	case GPCMD_SEND_CUE_SHEET:
-	case GPCMD_SET_SPEED:
-	case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
-	case GPCMD_LOAD_UNLOAD:
-	case GPCMD_SET_STREAMING:
-	case GPCMD_SET_READ_AHEAD:
-	/* ZBC */
-	case ZBC_OUT:
-		return (mode & FMODE_WRITE);
-	default:
-		return false;
-	}
-}
-EXPORT_SYMBOL(scsi_cmd_allowed);
-
-static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
-			     struct sg_io_hdr *hdr, fmode_t mode)
-{
-	struct scsi_request *req = scsi_req(rq);
-
-	if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len))
-		return -EFAULT;
-	if (!scsi_cmd_allowed(req->cmd, mode))
-		return -EPERM;
-
-	/*
-	 * fill in request structure
-	 */
-	req->cmd_len = hdr->cmd_len;
-
-	rq->timeout = msecs_to_jiffies(hdr->timeout);
-	if (!rq->timeout)
-		rq->timeout = q->sg_timeout;
-	if (!rq->timeout)
-		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
-	if (rq->timeout < BLK_MIN_SG_TIMEOUT)
-		rq->timeout = BLK_MIN_SG_TIMEOUT;
-
-	return 0;
-}
-
-static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
-				 struct bio *bio)
-{
-	struct scsi_request *req = scsi_req(rq);
-	int r, ret = 0;
-
-	/*
-	 * fill in all the output members
-	 */
-	hdr->status = req->result & 0xff;
-	hdr->masked_status = status_byte(req->result);
-	hdr->msg_status = COMMAND_COMPLETE;
-	hdr->host_status = host_byte(req->result);
-	hdr->driver_status = 0;
-	if (scsi_status_is_check_condition(hdr->status))
-		hdr->driver_status = DRIVER_SENSE;
-	hdr->info = 0;
-	if (hdr->masked_status || hdr->host_status || hdr->driver_status)
-		hdr->info |= SG_INFO_CHECK;
-	hdr->resid = req->resid_len;
-	hdr->sb_len_wr = 0;
-
-	if (req->sense_len && hdr->sbp) {
-		int len = min((unsigned int) hdr->mx_sb_len, req->sense_len);
-
-		if (!copy_to_user(hdr->sbp, req->sense, len))
-			hdr->sb_len_wr = len;
-		else
-			ret = -EFAULT;
-	}
-
-	r = blk_rq_unmap_user(bio);
-	if (!ret)
-		ret = r;
-
-	return ret;
-}
-
-static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
-		struct sg_io_hdr *hdr, fmode_t mode)
-{
-	unsigned long start_time;
-	ssize_t ret = 0;
-	int writing = 0;
-	int at_head = 0;
-	struct request *rq;
-	struct scsi_request *req;
-	struct bio *bio;
-
-	if (hdr->interface_id != 'S')
-		return -EINVAL;
-
-	if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
-		return -EIO;
-
-	if (hdr->dxfer_len)
-		switch (hdr->dxfer_direction) {
-		default:
-			return -EINVAL;
-		case SG_DXFER_TO_DEV:
-			writing = 1;
-			break;
-		case SG_DXFER_TO_FROM_DEV:
-		case SG_DXFER_FROM_DEV:
-			break;
-		}
-	if (hdr->flags & SG_FLAG_Q_AT_HEAD)
-		at_head = 1;
-
-	ret = -ENOMEM;
-	rq = blk_get_request(q, writing ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
-	if (IS_ERR(rq))
-		return PTR_ERR(rq);
-	req = scsi_req(rq);
-
-	if (hdr->cmd_len > BLK_MAX_CDB) {
-		req->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
-		if (!req->cmd)
-			goto out_put_request;
-	}
-
-	ret = blk_fill_sghdr_rq(q, rq, hdr, mode);
-	if (ret < 0)
-		goto out_free_cdb;
-
-	ret = 0;
-	if (hdr->iovec_count) {
-		struct iov_iter i;
-		struct iovec *iov = NULL;
-
-		ret = import_iovec(rq_data_dir(rq), hdr->dxferp,
-				   hdr->iovec_count, 0, &iov, &i);
-		if (ret < 0)
-			goto out_free_cdb;
-
-		/* SG_IO howto says that the shorter of the two wins */
-		iov_iter_truncate(&i, hdr->dxfer_len);
-
-		ret = blk_rq_map_user_iov(q, rq, NULL, &i, GFP_KERNEL);
-		kfree(iov);
-	} else if (hdr->dxfer_len)
-		ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
-				      GFP_KERNEL);
-
-	if (ret)
-		goto out_free_cdb;
-
-	bio = rq->bio;
-	req->retries = 0;
-
-	start_time = jiffies;
-
-	blk_execute_rq(bd_disk, rq, at_head);
-
-	hdr->duration = jiffies_to_msecs(jiffies - start_time);
-
-	ret = blk_complete_sghdr_rq(rq, hdr, bio);
-
-out_free_cdb:
-	scsi_req_free_cmd(req);
-out_put_request:
-	blk_put_request(rq);
-	return ret;
-}
-
-/**
- * sg_scsi_ioctl  --  handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
- * @q:		request queue to send scsi commands down
- * @disk:	gendisk to operate on (option)
- * @mode:	mode used to open the file through which the ioctl has been
- *		submitted
- * @sic:	userspace structure describing the command to perform
- *
- * Send down the scsi command described by @sic to the device below
- * the request queue @q.  If @file is non-NULL it's used to perform
- * fine-grained permission checks that allow users to send down
- * non-destructive SCSI commands.  If the caller has a struct gendisk
- * available it should be passed in as @disk to allow the low level
- * driver to use the information contained in it.  A non-NULL @disk
- * is only allowed if the caller knows that the low level driver doesn't
- * need it (e.g. in the scsi subsystem).
- *
- * Notes:
- *   -  This interface is deprecated - users should use the SG_IO
- *      interface instead, as this is a more flexible approach to
- *      performing SCSI commands on a device.
- *   -  The SCSI command length is determined by examining the 1st byte
- *      of the given command. There is no way to override this.
- *   -  Data transfers are limited to PAGE_SIZE
- *   -  The length (x + y) must be at least OMAX_SB_LEN bytes long to
- *      accommodate the sense buffer when an error occurs.
- *      The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
- *      old code will not be surprised.
- *   -  If a Unix error occurs (e.g. ENOMEM) then the user will receive
- *      a negative return and the Unix error code in 'errno'.
- *      If the SCSI command succeeds then 0 is returned.
- *      Positive numbers returned are the compacted SCSI error codes (4
- *      bytes in one int) where the lowest byte is the SCSI status.
- */
-int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
-		struct scsi_ioctl_command __user *sic)
-{
-	enum { OMAX_SB_LEN = 16 };	/* For backward compatibility */
-	struct request *rq;
-	struct scsi_request *req;
-	int err;
-	unsigned int in_len, out_len, bytes, opcode, cmdlen;
-	char *buffer = NULL;
-
-	if (!sic)
-		return -EINVAL;
-
-	/*
-	 * get in an out lengths, verify they don't exceed a page worth of data
-	 */
-	if (get_user(in_len, &sic->inlen))
-		return -EFAULT;
-	if (get_user(out_len, &sic->outlen))
-		return -EFAULT;
-	if (in_len > PAGE_SIZE || out_len > PAGE_SIZE)
-		return -EINVAL;
-	if (get_user(opcode, sic->data))
-		return -EFAULT;
-
-	bytes = max(in_len, out_len);
-	if (bytes) {
-		buffer = kzalloc(bytes, GFP_NOIO | GFP_USER | __GFP_NOWARN);
-		if (!buffer)
-			return -ENOMEM;
-
-	}
-
-	rq = blk_get_request(q, in_len ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
-	if (IS_ERR(rq)) {
-		err = PTR_ERR(rq);
-		goto error_free_buffer;
-	}
-	req = scsi_req(rq);
-
-	cmdlen = COMMAND_SIZE(opcode);
-
-	/*
-	 * get command and data to send to device, if any
-	 */
-	err = -EFAULT;
-	req->cmd_len = cmdlen;
-	if (copy_from_user(req->cmd, sic->data, cmdlen))
-		goto error;
-
-	if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
-		goto error;
-
-	err = -EPERM;
-	if (!scsi_cmd_allowed(req->cmd, mode))
-		goto error;
-
-	/* default.  possible overriden later */
-	req->retries = 5;
-
-	switch (opcode) {
-	case SEND_DIAGNOSTIC:
-	case FORMAT_UNIT:
-		rq->timeout = FORMAT_UNIT_TIMEOUT;
-		req->retries = 1;
-		break;
-	case START_STOP:
-		rq->timeout = START_STOP_TIMEOUT;
-		break;
-	case MOVE_MEDIUM:
-		rq->timeout = MOVE_MEDIUM_TIMEOUT;
-		break;
-	case READ_ELEMENT_STATUS:
-		rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
-		break;
-	case READ_DEFECT_DATA:
-		rq->timeout = READ_DEFECT_DATA_TIMEOUT;
-		req->retries = 1;
-		break;
-	default:
-		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
-		break;
-	}
-
-	if (bytes) {
-		err = blk_rq_map_kern(q, rq, buffer, bytes, GFP_NOIO);
-		if (err)
-			goto error;
-	}
-
-	blk_execute_rq(disk, rq, 0);
-
-	err = req->result & 0xff;	/* only 8 bit SCSI status */
-	if (err) {
-		if (req->sense_len && req->sense) {
-			bytes = (OMAX_SB_LEN > req->sense_len) ?
-				req->sense_len : OMAX_SB_LEN;
-			if (copy_to_user(sic->data, req->sense, bytes))
-				err = -EFAULT;
-		}
-	} else {
-		if (copy_to_user(sic->data, buffer, out_len))
-			err = -EFAULT;
-	}
-	
-error:
-	blk_put_request(rq);
-
-error_free_buffer:
-	kfree(buffer);
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
-
-/* Send basic block requests */
-static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
-			      int cmd, int data)
-{
-	struct request *rq;
-	int err;
-
-	rq = blk_get_request(q, REQ_OP_DRV_OUT, 0);
-	if (IS_ERR(rq))
-		return PTR_ERR(rq);
-	rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
-	scsi_req(rq)->cmd[0] = cmd;
-	scsi_req(rq)->cmd[4] = data;
-	scsi_req(rq)->cmd_len = 6;
-	blk_execute_rq(bd_disk, rq, 0);
-	err = scsi_req(rq)->result ? -EIO : 0;
-	blk_put_request(rq);
-
-	return err;
-}
-
-static inline int blk_send_start_stop(struct request_queue *q,
-				      struct gendisk *bd_disk, int data)
-{
-	return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
-}
-
-int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp)
-{
-#ifdef CONFIG_COMPAT
-	if (in_compat_syscall()) {
-		struct compat_sg_io_hdr hdr32 =  {
-			.interface_id	 = hdr->interface_id,
-			.dxfer_direction = hdr->dxfer_direction,
-			.cmd_len	 = hdr->cmd_len,
-			.mx_sb_len	 = hdr->mx_sb_len,
-			.iovec_count	 = hdr->iovec_count,
-			.dxfer_len	 = hdr->dxfer_len,
-			.dxferp		 = (uintptr_t)hdr->dxferp,
-			.cmdp		 = (uintptr_t)hdr->cmdp,
-			.sbp		 = (uintptr_t)hdr->sbp,
-			.timeout	 = hdr->timeout,
-			.flags		 = hdr->flags,
-			.pack_id	 = hdr->pack_id,
-			.usr_ptr	 = (uintptr_t)hdr->usr_ptr,
-			.status		 = hdr->status,
-			.masked_status	 = hdr->masked_status,
-			.msg_status	 = hdr->msg_status,
-			.sb_len_wr	 = hdr->sb_len_wr,
-			.host_status	 = hdr->host_status,
-			.driver_status	 = hdr->driver_status,
-			.resid		 = hdr->resid,
-			.duration	 = hdr->duration,
-			.info		 = hdr->info,
-		};
-
-		if (copy_to_user(argp, &hdr32, sizeof(hdr32)))
-			return -EFAULT;
-
-		return 0;
-	}
-#endif
-
-	if (copy_to_user(argp, hdr, sizeof(*hdr)))
-		return -EFAULT;
-
-	return 0;
-}
-EXPORT_SYMBOL(put_sg_io_hdr);
-
-int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp)
-{
-#ifdef CONFIG_COMPAT
-	struct compat_sg_io_hdr hdr32;
-
-	if (in_compat_syscall()) {
-		if (copy_from_user(&hdr32, argp, sizeof(hdr32)))
-			return -EFAULT;
-
-		*hdr = (struct sg_io_hdr) {
-			.interface_id	 = hdr32.interface_id,
-			.dxfer_direction = hdr32.dxfer_direction,
-			.cmd_len	 = hdr32.cmd_len,
-			.mx_sb_len	 = hdr32.mx_sb_len,
-			.iovec_count	 = hdr32.iovec_count,
-			.dxfer_len	 = hdr32.dxfer_len,
-			.dxferp		 = compat_ptr(hdr32.dxferp),
-			.cmdp		 = compat_ptr(hdr32.cmdp),
-			.sbp		 = compat_ptr(hdr32.sbp),
-			.timeout	 = hdr32.timeout,
-			.flags		 = hdr32.flags,
-			.pack_id	 = hdr32.pack_id,
-			.usr_ptr	 = compat_ptr(hdr32.usr_ptr),
-			.status		 = hdr32.status,
-			.masked_status	 = hdr32.masked_status,
-			.msg_status	 = hdr32.msg_status,
-			.sb_len_wr	 = hdr32.sb_len_wr,
-			.host_status	 = hdr32.host_status,
-			.driver_status	 = hdr32.driver_status,
-			.resid		 = hdr32.resid,
-			.duration	 = hdr32.duration,
-			.info		 = hdr32.info,
-		};
-
-		return 0;
-	}
-#endif
-
-	if (copy_from_user(hdr, argp, sizeof(*hdr)))
-		return -EFAULT;
-
-	return 0;
-}
-EXPORT_SYMBOL(get_sg_io_hdr);
-
-#ifdef CONFIG_COMPAT
-struct compat_cdrom_generic_command {
-	unsigned char	cmd[CDROM_PACKET_SIZE];
-	compat_caddr_t	buffer;
-	compat_uint_t	buflen;
-	compat_int_t	stat;
-	compat_caddr_t	sense;
-	unsigned char	data_direction;
-	unsigned char	pad[3];
-	compat_int_t	quiet;
-	compat_int_t	timeout;
-	compat_caddr_t	unused;
-};
-#endif
-
-static int scsi_get_cdrom_generic_arg(struct cdrom_generic_command *cgc,
-				      const void __user *arg)
-{
-#ifdef CONFIG_COMPAT
-	if (in_compat_syscall()) {
-		struct compat_cdrom_generic_command cgc32;
-
-		if (copy_from_user(&cgc32, arg, sizeof(cgc32)))
-			return -EFAULT;
-
-		*cgc = (struct cdrom_generic_command) {
-			.buffer		= compat_ptr(cgc32.buffer),
-			.buflen		= cgc32.buflen,
-			.stat		= cgc32.stat,
-			.sense		= compat_ptr(cgc32.sense),
-			.data_direction	= cgc32.data_direction,
-			.quiet		= cgc32.quiet,
-			.timeout	= cgc32.timeout,
-			.unused		= compat_ptr(cgc32.unused),
-		};
-		memcpy(&cgc->cmd, &cgc32.cmd, CDROM_PACKET_SIZE);
-		return 0;
-	}
-#endif
-	if (copy_from_user(cgc, arg, sizeof(*cgc)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc,
-				      void __user *arg)
-{
-#ifdef CONFIG_COMPAT
-	if (in_compat_syscall()) {
-		struct compat_cdrom_generic_command cgc32 = {
-			.buffer		= (uintptr_t)(cgc->buffer),
-			.buflen		= cgc->buflen,
-			.stat		= cgc->stat,
-			.sense		= (uintptr_t)(cgc->sense),
-			.data_direction	= cgc->data_direction,
-			.quiet		= cgc->quiet,
-			.timeout	= cgc->timeout,
-			.unused		= (uintptr_t)(cgc->unused),
-		};
-		memcpy(&cgc32.cmd, &cgc->cmd, CDROM_PACKET_SIZE);
-
-		if (copy_to_user(arg, &cgc32, sizeof(cgc32)))
-			return -EFAULT;
-
-		return 0;
-	}
-#endif
-	if (copy_to_user(arg, cgc, sizeof(*cgc)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int scsi_cdrom_send_packet(struct request_queue *q,
-				  struct gendisk *bd_disk,
-				  fmode_t mode, void __user *arg)
-{
-	struct cdrom_generic_command cgc;
-	struct sg_io_hdr hdr;
-	int err;
-
-	err = scsi_get_cdrom_generic_arg(&cgc, arg);
-	if (err)
-		return err;
-
-	cgc.timeout = clock_t_to_jiffies(cgc.timeout);
-	memset(&hdr, 0, sizeof(hdr));
-	hdr.interface_id = 'S';
-	hdr.cmd_len = sizeof(cgc.cmd);
-	hdr.dxfer_len = cgc.buflen;
-	switch (cgc.data_direction) {
-		case CGC_DATA_UNKNOWN:
-			hdr.dxfer_direction = SG_DXFER_UNKNOWN;
-			break;
-		case CGC_DATA_WRITE:
-			hdr.dxfer_direction = SG_DXFER_TO_DEV;
-			break;
-		case CGC_DATA_READ:
-			hdr.dxfer_direction = SG_DXFER_FROM_DEV;
-			break;
-		case CGC_DATA_NONE:
-			hdr.dxfer_direction = SG_DXFER_NONE;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	hdr.dxferp = cgc.buffer;
-	hdr.sbp = cgc.sense;
-	if (hdr.sbp)
-		hdr.mx_sb_len = sizeof(struct request_sense);
-	hdr.timeout = jiffies_to_msecs(cgc.timeout);
-	hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd;
-	hdr.cmd_len = sizeof(cgc.cmd);
-
-	err = sg_io(q, bd_disk, &hdr, mode);
-	if (err == -EFAULT)
-		return -EFAULT;
-
-	if (hdr.status)
-		return -EIO;
-
-	cgc.stat = err;
-	cgc.buflen = hdr.resid;
-	if (scsi_put_cdrom_generic_arg(&cgc, arg))
-		return -EFAULT;
-
-	return err;
-}
-
-int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode,
-		   unsigned int cmd, void __user *arg)
-{
-	int err;
-
-	if (!q)
-		return -ENXIO;
-
-	switch (cmd) {
-		/*
-		 * new sgv3 interface
-		 */
-		case SG_GET_VERSION_NUM:
-			err = sg_get_version(arg);
-			break;
-		case SG_SET_TIMEOUT:
-			err = sg_set_timeout(q, arg);
-			break;
-		case SG_GET_TIMEOUT:
-			err = sg_get_timeout(q);
-			break;
-		case SG_GET_RESERVED_SIZE:
-			err = sg_get_reserved_size(q, arg);
-			break;
-		case SG_SET_RESERVED_SIZE:
-			err = sg_set_reserved_size(q, arg);
-			break;
-		case SG_EMULATED_HOST:
-			err = sg_emulated_host(q, arg);
-			break;
-		case SG_IO: {
-			struct sg_io_hdr hdr;
-
-			err = get_sg_io_hdr(&hdr, arg);
-			if (err)
-				break;
-			err = sg_io(q, bd_disk, &hdr, mode);
-			if (err == -EFAULT)
-				break;
-
-			if (put_sg_io_hdr(&hdr, arg))
-				err = -EFAULT;
-			break;
-		}
-		case CDROM_SEND_PACKET:
-			err = scsi_cdrom_send_packet(q, bd_disk, mode, arg);
-			break;
-
-		/*
-		 * old junk scsi send command ioctl
-		 */
-		case SCSI_IOCTL_SEND_COMMAND:
-			printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
-			err = -EINVAL;
-			if (!arg)
-				break;
-
-			err = sg_scsi_ioctl(q, bd_disk, mode, arg);
-			break;
-		case CDROMCLOSETRAY:
-			err = blk_send_start_stop(q, bd_disk, 0x03);
-			break;
-		case CDROMEJECT:
-			err = blk_send_start_stop(q, bd_disk, 0x02);
-			break;
-		default:
-			err = -ENOTTY;
-	}
-
-	return err;
-}
-EXPORT_SYMBOL(scsi_cmd_ioctl);
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 7739575b5229..a70ddc1eb313 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/uaccess.h>
+#include <linux/cdrom.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -189,6 +190,700 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg)
 		? -EFAULT: 0;
 }
 
+static int sg_get_version(int __user *p)
+{
+	static const int sg_version_num = 30527;
+	return put_user(sg_version_num, p);
+}
+
+static int sg_get_timeout(struct request_queue *q)
+{
+	return jiffies_to_clock_t(q->sg_timeout);
+}
+
+static int sg_set_timeout(struct request_queue *q, int __user *p)
+{
+	int timeout, err = get_user(timeout, p);
+
+	if (!err)
+		q->sg_timeout = clock_t_to_jiffies(timeout);
+
+	return err;
+}
+
+static int sg_get_reserved_size(struct request_queue *q, int __user *p)
+{
+	int val = min_t(int, q->sg_reserved_size, queue_max_sectors_bytes(q));
+
+	return put_user(val, p);
+}
+
+static int sg_set_reserved_size(struct request_queue *q, int __user *p)
+{
+	int size, err = get_user(size, p);
+
+	if (err)
+		return err;
+
+	if (size < 0)
+		return -EINVAL;
+
+	q->sg_reserved_size = min(size, queue_max_sectors_bytes(q));
+	return 0;
+}
+
+/*
+ * will always return that we are ATAPI even for a real SCSI drive, I'm not
+ * so sure this is worth doing anything about (why would you care??)
+ */
+static int sg_emulated_host(struct request_queue *q, int __user *p)
+{
+	return put_user(1, p);
+}
+
+/* Send basic block requests */
+static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
+			      int cmd, int data)
+{
+	struct request *rq;
+	int err;
+
+	rq = blk_get_request(q, REQ_OP_DRV_OUT, 0);
+	if (IS_ERR(rq))
+		return PTR_ERR(rq);
+	rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+	scsi_req(rq)->cmd[0] = cmd;
+	scsi_req(rq)->cmd[4] = data;
+	scsi_req(rq)->cmd_len = 6;
+	blk_execute_rq(bd_disk, rq, 0);
+	err = scsi_req(rq)->result ? -EIO : 0;
+	blk_put_request(rq);
+
+	return err;
+}
+
+static inline int blk_send_start_stop(struct request_queue *q,
+				      struct gendisk *bd_disk, int data)
+{
+	return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
+}
+
+bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
+{
+	/* root can do any command. */
+	if (capable(CAP_SYS_RAWIO))
+		return true;
+
+	/* Anybody who can open the device can do a read-safe command */
+	switch (cmd[0]) {
+	/* Basic read-only commands */
+	case TEST_UNIT_READY:
+	case REQUEST_SENSE:
+	case READ_6:
+	case READ_10:
+	case READ_12:
+	case READ_16:
+	case READ_BUFFER:
+	case READ_DEFECT_DATA:
+	case READ_CAPACITY: /* also GPCMD_READ_CDVD_CAPACITY */
+	case READ_LONG:
+	case INQUIRY:
+	case MODE_SENSE:
+	case MODE_SENSE_10:
+	case LOG_SENSE:
+	case START_STOP:
+	case GPCMD_VERIFY_10:
+	case VERIFY_16:
+	case REPORT_LUNS:
+	case SERVICE_ACTION_IN_16:
+	case RECEIVE_DIAGNOSTIC:
+	case MAINTENANCE_IN: /* also GPCMD_SEND_KEY, which is a write command */
+	case GPCMD_READ_BUFFER_CAPACITY:
+	/* Audio CD commands */
+	case GPCMD_PLAY_CD:
+	case GPCMD_PLAY_AUDIO_10:
+	case GPCMD_PLAY_AUDIO_MSF:
+	case GPCMD_PLAY_AUDIO_TI:
+	case GPCMD_PAUSE_RESUME:
+	/* CD/DVD data reading */
+	case GPCMD_READ_CD:
+	case GPCMD_READ_CD_MSF:
+	case GPCMD_READ_DISC_INFO:
+	case GPCMD_READ_DVD_STRUCTURE:
+	case GPCMD_READ_HEADER:
+	case GPCMD_READ_TRACK_RZONE_INFO:
+	case GPCMD_READ_SUBCHANNEL:
+	case GPCMD_READ_TOC_PMA_ATIP:
+	case GPCMD_REPORT_KEY:
+	case GPCMD_SCAN:
+	case GPCMD_GET_CONFIGURATION:
+	case GPCMD_READ_FORMAT_CAPACITIES:
+	case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
+	case GPCMD_GET_PERFORMANCE:
+	case GPCMD_SEEK:
+	case GPCMD_STOP_PLAY_SCAN:
+	/* ZBC */
+	case ZBC_IN:
+		return true;
+	/* Basic writing commands */
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_VERIFY:
+	case WRITE_12:
+	case WRITE_VERIFY_12:
+	case WRITE_16:
+	case WRITE_LONG:
+	case WRITE_LONG_2:
+	case WRITE_SAME:
+	case WRITE_SAME_16:
+	case WRITE_SAME_32:
+	case ERASE:
+	case GPCMD_MODE_SELECT_10:
+	case MODE_SELECT:
+	case LOG_SELECT:
+	case GPCMD_BLANK:
+	case GPCMD_CLOSE_TRACK:
+	case GPCMD_FLUSH_CACHE:
+	case GPCMD_FORMAT_UNIT:
+	case GPCMD_REPAIR_RZONE_TRACK:
+	case GPCMD_RESERVE_RZONE_TRACK:
+	case GPCMD_SEND_DVD_STRUCTURE:
+	case GPCMD_SEND_EVENT:
+	case GPCMD_SEND_OPC:
+	case GPCMD_SEND_CUE_SHEET:
+	case GPCMD_SET_SPEED:
+	case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+	case GPCMD_LOAD_UNLOAD:
+	case GPCMD_SET_STREAMING:
+	case GPCMD_SET_READ_AHEAD:
+	/* ZBC */
+	case ZBC_OUT:
+		return (mode & FMODE_WRITE);
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(scsi_cmd_allowed);
+
+static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
+			     struct sg_io_hdr *hdr, fmode_t mode)
+{
+	struct scsi_request *req = scsi_req(rq);
+
+	if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len))
+		return -EFAULT;
+	if (!scsi_cmd_allowed(req->cmd, mode))
+		return -EPERM;
+
+	/*
+	 * fill in request structure
+	 */
+	req->cmd_len = hdr->cmd_len;
+
+	rq->timeout = msecs_to_jiffies(hdr->timeout);
+	if (!rq->timeout)
+		rq->timeout = q->sg_timeout;
+	if (!rq->timeout)
+		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+	if (rq->timeout < BLK_MIN_SG_TIMEOUT)
+		rq->timeout = BLK_MIN_SG_TIMEOUT;
+
+	return 0;
+}
+
+static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
+				 struct bio *bio)
+{
+	struct scsi_request *req = scsi_req(rq);
+	int r, ret = 0;
+
+	/*
+	 * fill in all the output members
+	 */
+	hdr->status = req->result & 0xff;
+	hdr->masked_status = status_byte(req->result);
+	hdr->msg_status = COMMAND_COMPLETE;
+	hdr->host_status = host_byte(req->result);
+	hdr->driver_status = 0;
+	if (scsi_status_is_check_condition(hdr->status))
+		hdr->driver_status = DRIVER_SENSE;
+	hdr->info = 0;
+	if (hdr->masked_status || hdr->host_status || hdr->driver_status)
+		hdr->info |= SG_INFO_CHECK;
+	hdr->resid = req->resid_len;
+	hdr->sb_len_wr = 0;
+
+	if (req->sense_len && hdr->sbp) {
+		int len = min((unsigned int) hdr->mx_sb_len, req->sense_len);
+
+		if (!copy_to_user(hdr->sbp, req->sense, len))
+			hdr->sb_len_wr = len;
+		else
+			ret = -EFAULT;
+	}
+
+	r = blk_rq_unmap_user(bio);
+	if (!ret)
+		ret = r;
+
+	return ret;
+}
+
+static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
+		struct sg_io_hdr *hdr, fmode_t mode)
+{
+	unsigned long start_time;
+	ssize_t ret = 0;
+	int writing = 0;
+	int at_head = 0;
+	struct request *rq;
+	struct scsi_request *req;
+	struct bio *bio;
+
+	if (hdr->interface_id != 'S')
+		return -EINVAL;
+
+	if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
+		return -EIO;
+
+	if (hdr->dxfer_len)
+		switch (hdr->dxfer_direction) {
+		default:
+			return -EINVAL;
+		case SG_DXFER_TO_DEV:
+			writing = 1;
+			break;
+		case SG_DXFER_TO_FROM_DEV:
+		case SG_DXFER_FROM_DEV:
+			break;
+		}
+	if (hdr->flags & SG_FLAG_Q_AT_HEAD)
+		at_head = 1;
+
+	ret = -ENOMEM;
+	rq = blk_get_request(q, writing ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
+	if (IS_ERR(rq))
+		return PTR_ERR(rq);
+	req = scsi_req(rq);
+
+	if (hdr->cmd_len > BLK_MAX_CDB) {
+		req->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
+		if (!req->cmd)
+			goto out_put_request;
+	}
+
+	ret = blk_fill_sghdr_rq(q, rq, hdr, mode);
+	if (ret < 0)
+		goto out_free_cdb;
+
+	ret = 0;
+	if (hdr->iovec_count) {
+		struct iov_iter i;
+		struct iovec *iov = NULL;
+
+		ret = import_iovec(rq_data_dir(rq), hdr->dxferp,
+				   hdr->iovec_count, 0, &iov, &i);
+		if (ret < 0)
+			goto out_free_cdb;
+
+		/* SG_IO howto says that the shorter of the two wins */
+		iov_iter_truncate(&i, hdr->dxfer_len);
+
+		ret = blk_rq_map_user_iov(q, rq, NULL, &i, GFP_KERNEL);
+		kfree(iov);
+	} else if (hdr->dxfer_len)
+		ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
+				      GFP_KERNEL);
+
+	if (ret)
+		goto out_free_cdb;
+
+	bio = rq->bio;
+	req->retries = 0;
+
+	start_time = jiffies;
+
+	blk_execute_rq(bd_disk, rq, at_head);
+
+	hdr->duration = jiffies_to_msecs(jiffies - start_time);
+
+	ret = blk_complete_sghdr_rq(rq, hdr, bio);
+
+out_free_cdb:
+	scsi_req_free_cmd(req);
+out_put_request:
+	blk_put_request(rq);
+	return ret;
+}
+
+/**
+ * sg_scsi_ioctl  --  handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
+ * @q:		request queue to send scsi commands down
+ * @disk:	gendisk to operate on (option)
+ * @mode:	mode used to open the file through which the ioctl has been
+ *		submitted
+ * @sic:	userspace structure describing the command to perform
+ *
+ * Send down the scsi command described by @sic to the device below
+ * the request queue @q.  If @file is non-NULL it's used to perform
+ * fine-grained permission checks that allow users to send down
+ * non-destructive SCSI commands.  If the caller has a struct gendisk
+ * available it should be passed in as @disk to allow the low level
+ * driver to use the information contained in it.  A non-NULL @disk
+ * is only allowed if the caller knows that the low level driver doesn't
+ * need it (e.g. in the scsi subsystem).
+ *
+ * Notes:
+ *   -  This interface is deprecated - users should use the SG_IO
+ *      interface instead, as this is a more flexible approach to
+ *      performing SCSI commands on a device.
+ *   -  The SCSI command length is determined by examining the 1st byte
+ *      of the given command. There is no way to override this.
+ *   -  Data transfers are limited to PAGE_SIZE
+ *   -  The length (x + y) must be at least OMAX_SB_LEN bytes long to
+ *      accommodate the sense buffer when an error occurs.
+ *      The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
+ *      old code will not be surprised.
+ *   -  If a Unix error occurs (e.g. ENOMEM) then the user will receive
+ *      a negative return and the Unix error code in 'errno'.
+ *      If the SCSI command succeeds then 0 is returned.
+ *      Positive numbers returned are the compacted SCSI error codes (4
+ *      bytes in one int) where the lowest byte is the SCSI status.
+ */
+int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
+		struct scsi_ioctl_command __user *sic)
+{
+	enum { OMAX_SB_LEN = 16 };	/* For backward compatibility */
+	struct request *rq;
+	struct scsi_request *req;
+	int err;
+	unsigned int in_len, out_len, bytes, opcode, cmdlen;
+	char *buffer = NULL;
+
+	if (!sic)
+		return -EINVAL;
+
+	/*
+	 * get in an out lengths, verify they don't exceed a page worth of data
+	 */
+	if (get_user(in_len, &sic->inlen))
+		return -EFAULT;
+	if (get_user(out_len, &sic->outlen))
+		return -EFAULT;
+	if (in_len > PAGE_SIZE || out_len > PAGE_SIZE)
+		return -EINVAL;
+	if (get_user(opcode, sic->data))
+		return -EFAULT;
+
+	bytes = max(in_len, out_len);
+	if (bytes) {
+		buffer = kzalloc(bytes, GFP_NOIO | GFP_USER | __GFP_NOWARN);
+		if (!buffer)
+			return -ENOMEM;
+
+	}
+
+	rq = blk_get_request(q, in_len ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
+	if (IS_ERR(rq)) {
+		err = PTR_ERR(rq);
+		goto error_free_buffer;
+	}
+	req = scsi_req(rq);
+
+	cmdlen = COMMAND_SIZE(opcode);
+
+	/*
+	 * get command and data to send to device, if any
+	 */
+	err = -EFAULT;
+	req->cmd_len = cmdlen;
+	if (copy_from_user(req->cmd, sic->data, cmdlen))
+		goto error;
+
+	if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
+		goto error;
+
+	err = -EPERM;
+	if (!scsi_cmd_allowed(req->cmd, mode))
+		goto error;
+
+	/* default.  possible overriden later */
+	req->retries = 5;
+
+	switch (opcode) {
+	case SEND_DIAGNOSTIC:
+	case FORMAT_UNIT:
+		rq->timeout = FORMAT_UNIT_TIMEOUT;
+		req->retries = 1;
+		break;
+	case START_STOP:
+		rq->timeout = START_STOP_TIMEOUT;
+		break;
+	case MOVE_MEDIUM:
+		rq->timeout = MOVE_MEDIUM_TIMEOUT;
+		break;
+	case READ_ELEMENT_STATUS:
+		rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
+		break;
+	case READ_DEFECT_DATA:
+		rq->timeout = READ_DEFECT_DATA_TIMEOUT;
+		req->retries = 1;
+		break;
+	default:
+		rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
+		break;
+	}
+
+	if (bytes) {
+		err = blk_rq_map_kern(q, rq, buffer, bytes, GFP_NOIO);
+		if (err)
+			goto error;
+	}
+
+	blk_execute_rq(disk, rq, 0);
+
+	err = req->result & 0xff;	/* only 8 bit SCSI status */
+	if (err) {
+		if (req->sense_len && req->sense) {
+			bytes = (OMAX_SB_LEN > req->sense_len) ?
+				req->sense_len : OMAX_SB_LEN;
+			if (copy_to_user(sic->data, req->sense, bytes))
+				err = -EFAULT;
+		}
+	} else {
+		if (copy_to_user(sic->data, buffer, out_len))
+			err = -EFAULT;
+	}
+	
+error:
+	blk_put_request(rq);
+
+error_free_buffer:
+	kfree(buffer);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
+
+int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp)
+{
+#ifdef CONFIG_COMPAT
+	if (in_compat_syscall()) {
+		struct compat_sg_io_hdr hdr32 =  {
+			.interface_id	 = hdr->interface_id,
+			.dxfer_direction = hdr->dxfer_direction,
+			.cmd_len	 = hdr->cmd_len,
+			.mx_sb_len	 = hdr->mx_sb_len,
+			.iovec_count	 = hdr->iovec_count,
+			.dxfer_len	 = hdr->dxfer_len,
+			.dxferp		 = (uintptr_t)hdr->dxferp,
+			.cmdp		 = (uintptr_t)hdr->cmdp,
+			.sbp		 = (uintptr_t)hdr->sbp,
+			.timeout	 = hdr->timeout,
+			.flags		 = hdr->flags,
+			.pack_id	 = hdr->pack_id,
+			.usr_ptr	 = (uintptr_t)hdr->usr_ptr,
+			.status		 = hdr->status,
+			.masked_status	 = hdr->masked_status,
+			.msg_status	 = hdr->msg_status,
+			.sb_len_wr	 = hdr->sb_len_wr,
+			.host_status	 = hdr->host_status,
+			.driver_status	 = hdr->driver_status,
+			.resid		 = hdr->resid,
+			.duration	 = hdr->duration,
+			.info		 = hdr->info,
+		};
+
+		if (copy_to_user(argp, &hdr32, sizeof(hdr32)))
+			return -EFAULT;
+
+		return 0;
+	}
+#endif
+
+	if (copy_to_user(argp, hdr, sizeof(*hdr)))
+		return -EFAULT;
+
+	return 0;
+}
+EXPORT_SYMBOL(put_sg_io_hdr);
+
+int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp)
+{
+#ifdef CONFIG_COMPAT
+	struct compat_sg_io_hdr hdr32;
+
+	if (in_compat_syscall()) {
+		if (copy_from_user(&hdr32, argp, sizeof(hdr32)))
+			return -EFAULT;
+
+		*hdr = (struct sg_io_hdr) {
+			.interface_id	 = hdr32.interface_id,
+			.dxfer_direction = hdr32.dxfer_direction,
+			.cmd_len	 = hdr32.cmd_len,
+			.mx_sb_len	 = hdr32.mx_sb_len,
+			.iovec_count	 = hdr32.iovec_count,
+			.dxfer_len	 = hdr32.dxfer_len,
+			.dxferp		 = compat_ptr(hdr32.dxferp),
+			.cmdp		 = compat_ptr(hdr32.cmdp),
+			.sbp		 = compat_ptr(hdr32.sbp),
+			.timeout	 = hdr32.timeout,
+			.flags		 = hdr32.flags,
+			.pack_id	 = hdr32.pack_id,
+			.usr_ptr	 = compat_ptr(hdr32.usr_ptr),
+			.status		 = hdr32.status,
+			.masked_status	 = hdr32.masked_status,
+			.msg_status	 = hdr32.msg_status,
+			.sb_len_wr	 = hdr32.sb_len_wr,
+			.host_status	 = hdr32.host_status,
+			.driver_status	 = hdr32.driver_status,
+			.resid		 = hdr32.resid,
+			.duration	 = hdr32.duration,
+			.info		 = hdr32.info,
+		};
+
+		return 0;
+	}
+#endif
+
+	if (copy_from_user(hdr, argp, sizeof(*hdr)))
+		return -EFAULT;
+
+	return 0;
+}
+EXPORT_SYMBOL(get_sg_io_hdr);
+
+#ifdef CONFIG_COMPAT
+struct compat_cdrom_generic_command {
+	unsigned char	cmd[CDROM_PACKET_SIZE];
+	compat_caddr_t	buffer;
+	compat_uint_t	buflen;
+	compat_int_t	stat;
+	compat_caddr_t	sense;
+	unsigned char	data_direction;
+	unsigned char	pad[3];
+	compat_int_t	quiet;
+	compat_int_t	timeout;
+	compat_caddr_t	unused;
+};
+#endif
+
+static int scsi_get_cdrom_generic_arg(struct cdrom_generic_command *cgc,
+				      const void __user *arg)
+{
+#ifdef CONFIG_COMPAT
+	if (in_compat_syscall()) {
+		struct compat_cdrom_generic_command cgc32;
+
+		if (copy_from_user(&cgc32, arg, sizeof(cgc32)))
+			return -EFAULT;
+
+		*cgc = (struct cdrom_generic_command) {
+			.buffer		= compat_ptr(cgc32.buffer),
+			.buflen		= cgc32.buflen,
+			.stat		= cgc32.stat,
+			.sense		= compat_ptr(cgc32.sense),
+			.data_direction	= cgc32.data_direction,
+			.quiet		= cgc32.quiet,
+			.timeout	= cgc32.timeout,
+			.unused		= compat_ptr(cgc32.unused),
+		};
+		memcpy(&cgc->cmd, &cgc32.cmd, CDROM_PACKET_SIZE);
+		return 0;
+	}
+#endif
+	if (copy_from_user(cgc, arg, sizeof(*cgc)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc,
+				      void __user *arg)
+{
+#ifdef CONFIG_COMPAT
+	if (in_compat_syscall()) {
+		struct compat_cdrom_generic_command cgc32 = {
+			.buffer		= (uintptr_t)(cgc->buffer),
+			.buflen		= cgc->buflen,
+			.stat		= cgc->stat,
+			.sense		= (uintptr_t)(cgc->sense),
+			.data_direction	= cgc->data_direction,
+			.quiet		= cgc->quiet,
+			.timeout	= cgc->timeout,
+			.unused		= (uintptr_t)(cgc->unused),
+		};
+		memcpy(&cgc32.cmd, &cgc->cmd, CDROM_PACKET_SIZE);
+
+		if (copy_to_user(arg, &cgc32, sizeof(cgc32)))
+			return -EFAULT;
+
+		return 0;
+	}
+#endif
+	if (copy_to_user(arg, cgc, sizeof(*cgc)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int scsi_cdrom_send_packet(struct request_queue *q,
+				  struct gendisk *bd_disk,
+				  fmode_t mode, void __user *arg)
+{
+	struct cdrom_generic_command cgc;
+	struct sg_io_hdr hdr;
+	int err;
+
+	err = scsi_get_cdrom_generic_arg(&cgc, arg);
+	if (err)
+		return err;
+
+	cgc.timeout = clock_t_to_jiffies(cgc.timeout);
+	memset(&hdr, 0, sizeof(hdr));
+	hdr.interface_id = 'S';
+	hdr.cmd_len = sizeof(cgc.cmd);
+	hdr.dxfer_len = cgc.buflen;
+	switch (cgc.data_direction) {
+		case CGC_DATA_UNKNOWN:
+			hdr.dxfer_direction = SG_DXFER_UNKNOWN;
+			break;
+		case CGC_DATA_WRITE:
+			hdr.dxfer_direction = SG_DXFER_TO_DEV;
+			break;
+		case CGC_DATA_READ:
+			hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+			break;
+		case CGC_DATA_NONE:
+			hdr.dxfer_direction = SG_DXFER_NONE;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	hdr.dxferp = cgc.buffer;
+	hdr.sbp = cgc.sense;
+	if (hdr.sbp)
+		hdr.mx_sb_len = sizeof(struct request_sense);
+	hdr.timeout = jiffies_to_msecs(cgc.timeout);
+	hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd;
+	hdr.cmd_len = sizeof(cgc.cmd);
+
+	err = sg_io(q, bd_disk, &hdr, mode);
+	if (err == -EFAULT)
+		return -EFAULT;
+
+	if (hdr.status)
+		return -EIO;
+
+	cgc.stat = err;
+	cgc.buflen = hdr.resid;
+	if (scsi_put_cdrom_generic_arg(&cgc, arg))
+		return -EFAULT;
+
+	return err;
+}
+
 /**
  * scsi_ioctl - Dispatch ioctl to scsi device
  * @sdev: scsi device receiving ioctl
@@ -225,13 +920,42 @@ int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
 		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)
+	switch (cmd) {
+	case SG_GET_VERSION_NUM:
+		return sg_get_version(arg);
+	case SG_SET_TIMEOUT:
+		return sg_set_timeout(q, arg);
+	case SG_GET_TIMEOUT:
+		return sg_get_timeout(q);
+	case SG_GET_RESERVED_SIZE:
+		return sg_get_reserved_size(q, arg);
+	case SG_SET_RESERVED_SIZE:
+		return sg_set_reserved_size(q, arg);
+	case SG_EMULATED_HOST:
+		return sg_emulated_host(q, arg);
+	case SG_IO: {
+		struct sg_io_hdr hdr;
+
+		error = get_sg_io_hdr(&hdr, arg);
+		if (error)
 			return error;
-	}
 
-	switch (cmd) {
+		error = sg_io(q, disk, &hdr, mode);
+		if (error == -EFAULT)
+			return error;
+
+		if (put_sg_io_hdr(&hdr, arg))
+			return -EFAULT;
+		return 0;
+	}
+	case SCSI_IOCTL_SEND_COMMAND:
+		return sg_scsi_ioctl(q, disk, mode, arg);
+	case CDROM_SEND_PACKET:
+		return scsi_cdrom_send_packet(q, disk, mode, arg);
+	case CDROMCLOSETRAY:
+		return blk_send_start_stop(q, disk, 0x03);
+	case CDROMEJECT:
+		return blk_send_start_stop(q, disk, 0x02);
 	case SCSI_IOCTL_GET_IDLUN: {
 		struct scsi_idlun v = {
 			.dev_id = (sdev->id & 0xff)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 3522e8cbee26..d6f84aa71e40 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -28,8 +28,6 @@
 #include <linux/sbitmap.h>
 
 struct module;
-struct scsi_ioctl_command;
-
 struct request_queue;
 struct elevator_queue;
 struct blk_trace;
@@ -888,13 +886,6 @@ extern blk_status_t blk_insert_cloned_request(struct request_queue *q,
 				     struct request *rq);
 int blk_rq_append_bio(struct request *rq, struct bio *bio);
 extern void blk_queue_split(struct bio **);
-extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
-			  unsigned int, void __user *);
-extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
-			 struct scsi_ioctl_command __user *);
-extern int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp);
-extern int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp);
-
 extern int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags);
 extern void blk_queue_exit(struct request_queue *q);
 extern void blk_sync_queue(struct request_queue *q);
@@ -1343,8 +1334,6 @@ static inline int sb_issue_zeroout(struct super_block *sb, sector_t block,
 				    gfp_mask, 0);
 }
 
-bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode);
-
 static inline bool bdev_is_partition(struct block_device *bdev)
 {
 	return bdev->bd_partno;
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index defbe8084eb8..b3918fded464 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -20,6 +20,7 @@
 
 struct gendisk;
 struct scsi_device;
+struct sg_io_hdr;
 
 /*
  * Structures used for scsi_ioctl et al.
@@ -46,6 +47,11 @@ int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
 		int cmd, bool ndelay);
 int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
 		int cmd, void __user *arg);
+int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
+			 struct scsi_ioctl_command __user *argp);
+int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp);
+int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp);
+bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode);
 
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 19/24] scsi: rename CONFIG_BLK_SCSI_REQUEST to CONFIG_SCSI_COMMON
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (17 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 18/24] scsi_ioctl: move all "block layer" SCSI ioctl handling to drivers/scsi Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-22 17:51   ` Martin K. Petersen
  2021-07-12  5:48 ` [PATCH 20/24] scsi: remove a very misleading comment Christoph Hellwig
                   ` (5 subsequent siblings)
  24 siblings, 1 reply; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

CONFIG_BLK_SCSI_REQUEST is rather misnamed now as it just enabled
building a small amount of code shared by the scsi initiator, target
and consumers of the scsi_request passthrough API.  Rename it and
also allow building it as a module.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/Kconfig          | 3 ---
 drivers/block/Kconfig  | 2 +-
 drivers/scsi/Kconfig   | 5 ++++-
 drivers/scsi/Makefile  | 2 +-
 drivers/target/Kconfig | 2 +-
 fs/nfsd/Kconfig        | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/block/Kconfig b/block/Kconfig
index 88aa88241795..97c1d999b920 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -29,9 +29,6 @@ if BLOCK
 config BLK_RQ_ALLOC_TIME
 	bool
 
-config BLK_SCSI_REQUEST
-	bool
-
 config BLK_CGROUP_RWSTAT
 	bool
 
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 4652bcdb9efb..90ed1642304a 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -305,7 +305,7 @@ config CDROM_PKTCDVD
 	tristate "Packet writing on CD/DVD media (DEPRECATED)"
 	depends on !UML
 	select CDROM
-	select BLK_SCSI_REQUEST
+	select SCSI_COMMON
 	help
 	  Note: This driver is deprecated and will be removed from the
 	  kernel in the near future!
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 86ecab196dfd..6e3a04107bb6 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -14,12 +14,15 @@ config RAID_ATTRS
 	help
 	  Provides RAID
 
+config SCSI_COMMON
+	tristate
+
 config SCSI
 	tristate "SCSI device support"
 	depends on BLOCK
 	select SCSI_DMA if HAS_DMA
 	select SG_POOL
-	select BLK_SCSI_REQUEST
+	select SCSI_COMMON
 	select BLK_DEV_BSG_COMMON if BLK_DEV_BSG
 	help
 	  If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 240b831b5a11..f086eca2bcd7 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -20,7 +20,7 @@ CFLAGS_aha152x.o =   -DAHA152X_STAT -DAUTOCONF
 obj-$(CONFIG_PCMCIA)		+= pcmcia/
 
 obj-$(CONFIG_SCSI)		+= scsi_mod.o
-obj-$(CONFIG_BLK_SCSI_REQUEST)	+= scsi_common.o
+obj-$(CONFIG_SCSI_COMMON)	+= scsi_common.o
 
 obj-$(CONFIG_RAID_ATTRS)	+= raid_class.o
 
diff --git a/drivers/target/Kconfig b/drivers/target/Kconfig
index c163b14774d7..72171ea3dd53 100644
--- a/drivers/target/Kconfig
+++ b/drivers/target/Kconfig
@@ -5,7 +5,7 @@ menuconfig TARGET_CORE
 	depends on BLOCK
 	select CONFIGFS_FS
 	select CRC_T10DIF
-	select BLK_SCSI_REQUEST
+	select SCSI_COMMON
 	select SGL_ALLOC
 	default n
 	help
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index f229172652be..6e9ea4ee0f73 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -109,7 +109,7 @@ config NFSD_SCSILAYOUT
 	depends on NFSD_V4 && BLOCK
 	select NFSD_PNFS
 	select EXPORTFS_BLOCK_OPS
-	select BLK_SCSI_REQUEST
+	select SCSI_COMMON
 	help
 	  This option enables support for the exporting pNFS SCSI layouts
 	  in the kernel's NFS server. The pNFS SCSI layout enables NFS
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 20/24] scsi: remove a very misleading comment
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (18 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 19/24] scsi: rename CONFIG_BLK_SCSI_REQUEST to CONFIG_SCSI_COMMON Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-22 17:52   ` Bart Van Assche
  2021-07-12  5:48 ` [PATCH 21/24] scsi: consolidate the START STOP UNIT handling Christoph Hellwig
                   ` (4 subsequent siblings)
  24 siblings, 1 reply; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Remove the comment above ioctl_internal_command, which doesn't
document this function at all.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/scsi_ioctl.c | 23 -----------------------
 1 file changed, 23 deletions(-)

diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index a70ddc1eb313..3d4311a78383 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -64,29 +64,6 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
 	return 1;
 }
 
-/*
-
- * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
- * The IOCTL_NORMAL_TIMEOUT and NORMAL_RETRIES  variables are used.  
- * 
- * dev is the SCSI device struct ptr, *(int *) arg is the length of the
- * input data, if any, not including the command string & counts, 
- * *((int *)arg + 1) is the output buffer size in bytes.
- * 
- * *(char *) ((int *) arg)[2] the actual command byte.   
- * 
- * Note that if more than MAX_BUF bytes are requested to be transferred,
- * the ioctl will fail with error EINVAL.
- * 
- * This size *does not* include the initial lengths that were passed.
- * 
- * The SCSI command is read from the memory location immediately after the
- * length words, and the input data is right after the command.  The SCSI
- * routines know the command size based on the opcode decode.  
- * 
- * The output area is then filled in starting from the command byte. 
- */
-
 static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
 				  int timeout, int retries)
 {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 21/24] scsi: consolidate the START STOP UNIT handling
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (19 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 20/24] scsi: remove a very misleading comment Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-22 18:44   ` Bart Van Assche
  2021-07-12  5:48 ` [PATCH 22/24] scsi: factor SCSI_IOCTL_GET_IDLUN handling into a helper Christoph Hellwig
                   ` (3 subsequent siblings)
  24 siblings, 1 reply; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Factor out a helper for the various flavors of START STOP UNIT
command ioctls.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/scsi_ioctl.c | 48 ++++++++-------------------------------
 1 file changed, 10 insertions(+), 38 deletions(-)

diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 3d4311a78383..f6f16edecc67 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -218,31 +218,14 @@ static int sg_emulated_host(struct request_queue *q, int __user *p)
 	return put_user(1, p);
 }
 
-/* Send basic block requests */
-static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
-			      int cmd, int data)
+static int scsi_send_start_stop(struct scsi_device *sdev, int data)
 {
-	struct request *rq;
-	int err;
-
-	rq = blk_get_request(q, REQ_OP_DRV_OUT, 0);
-	if (IS_ERR(rq))
-		return PTR_ERR(rq);
-	rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
-	scsi_req(rq)->cmd[0] = cmd;
-	scsi_req(rq)->cmd[4] = data;
-	scsi_req(rq)->cmd_len = 6;
-	blk_execute_rq(bd_disk, rq, 0);
-	err = scsi_req(rq)->result ? -EIO : 0;
-	blk_put_request(rq);
+	char cdb[MAX_COMMAND_SIZE] = { };
 
-	return err;
-}
-
-static inline int blk_send_start_stop(struct request_queue *q,
-				      struct gendisk *bd_disk, int data)
-{
-	return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
+	cdb[0] = START_STOP;
+	cdb[4] = data;
+	return ioctl_internal_command(sdev, cdb, START_STOP_TIMEOUT,
+				      NORMAL_RETRIES);
 }
 
 bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
@@ -877,7 +860,6 @@ 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;
 
@@ -930,9 +912,9 @@ int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
 	case CDROM_SEND_PACKET:
 		return scsi_cdrom_send_packet(q, disk, mode, arg);
 	case CDROMCLOSETRAY:
-		return blk_send_start_stop(q, disk, 0x03);
+		return scsi_send_start_stop(sdev, 3);
 	case CDROMEJECT:
-		return blk_send_start_stop(q, disk, 0x02);
+		return scsi_send_start_stop(sdev, 2);
 	case SCSI_IOCTL_GET_IDLUN: {
 		struct scsi_idlun v = {
 			.dev_id = (sdev->id & 0xff)
@@ -957,19 +939,9 @@ int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
 		return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT,
 					    NORMAL_RETRIES, &sense_hdr);
 	case SCSI_IOCTL_START_UNIT:
-		scsi_cmd[0] = START_STOP;
-		scsi_cmd[1] = 0;
-		scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-		scsi_cmd[4] = 1;
-		return ioctl_internal_command(sdev, scsi_cmd,
-				     START_STOP_TIMEOUT, NORMAL_RETRIES);
+		return scsi_send_start_stop(sdev, 1);
 	case SCSI_IOCTL_STOP_UNIT:
-		scsi_cmd[0] = START_STOP;
-		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,
-				     START_STOP_TIMEOUT, NORMAL_RETRIES);
+		return scsi_send_start_stop(sdev, 0);
         case SCSI_IOCTL_GET_PCI:
                 return scsi_ioctl_get_pci(sdev, arg);
 	case SG_SCSI_RESET:
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 22/24] scsi: factor SCSI_IOCTL_GET_IDLUN handling into a helper
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (20 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 21/24] scsi: consolidate the START STOP UNIT handling Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 23/24] scsi: factor SG_IO " Christoph Hellwig
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Split the SCSI_IOCTL_GET_IDLUN handler from the main scsi_ioctl routine.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/scsi_ioctl.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index f6f16edecc67..634cf62ec6fd 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -218,6 +218,20 @@ static int sg_emulated_host(struct request_queue *q, int __user *p)
 	return put_user(1, p);
 }
 
+static int scsi_get_idlun(struct scsi_device *sdev, void __user *argp)
+{
+	struct scsi_idlun v = {
+		.dev_id = (sdev->id & 0xff) +
+			((sdev->lun & 0xff) << 8) +
+			((sdev->channel & 0xff) << 16) +
+			((sdev->host->host_no & 0xff) << 24),
+		.host_unique_id = sdev->host->unique_id
+	};
+	if (copy_to_user(argp, &v, sizeof(struct scsi_idlun)))
+		return -EFAULT;
+	return 0;
+}
+
 static int scsi_send_start_stop(struct scsi_device *sdev, int data)
 {
 	char cdb[MAX_COMMAND_SIZE] = { };
@@ -915,18 +929,8 @@ int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
 		return scsi_send_start_stop(sdev, 3);
 	case CDROMEJECT:
 		return scsi_send_start_stop(sdev, 2);
-	case SCSI_IOCTL_GET_IDLUN: {
-		struct scsi_idlun v = {
-			.dev_id = (sdev->id & 0xff)
-				 + ((sdev->lun & 0xff) << 8)
-				 + ((sdev->channel & 0xff) << 16)
-				 + ((sdev->host->host_no & 0xff) << 24),
-			.host_unique_id = sdev->host->unique_id
-		};
-		if (copy_to_user(arg, &v, sizeof(struct scsi_idlun)))
-			return -EFAULT;
-		return 0;
-	}
+	case SCSI_IOCTL_GET_IDLUN:
+		return scsi_get_idlun(sdev, arg);
 	case SCSI_IOCTL_GET_BUS_NUMBER:
 		return put_user(sdev->host->host_no, (int __user *)arg);
 	case SCSI_IOCTL_PROBE_HOST:
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 23/24] scsi: factor SG_IO handling into a helper
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (21 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 22/24] scsi: factor SCSI_IOCTL_GET_IDLUN handling into a helper Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-12  5:48 ` [PATCH 24/24] scsi: unexport sg_scsi_ioctl Christoph Hellwig
  2021-07-21  5:38 ` cleanup SCSI ioctl support Christoph Hellwig
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Split the SG_IO handler from the main scsi_ioctl routine.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/scsi_ioctl.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 634cf62ec6fd..2492c628fd38 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -858,6 +858,23 @@ static int scsi_cdrom_send_packet(struct request_queue *q,
 	return err;
 }
 
+static int scsi_ioctl_sg_io(struct request_queue *q, struct gendisk *disk,
+		fmode_t mode, void __user *argp)
+{
+	struct sg_io_hdr hdr;
+	int error;
+
+	error = get_sg_io_hdr(&hdr, argp);
+	if (error)
+		return error;
+	error = sg_io(q, disk, &hdr, mode);
+	if (error == -EFAULT)
+		return error;
+	if (put_sg_io_hdr(&hdr, argp))
+		return -EFAULT;
+	return 0;
+}
+
 /**
  * scsi_ioctl - Dispatch ioctl to scsi device
  * @sdev: scsi device receiving ioctl
@@ -875,7 +892,6 @@ int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
 {
 	struct request_queue *q = sdev->request_queue;
 	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 */
@@ -906,21 +922,8 @@ int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
 		return sg_set_reserved_size(q, arg);
 	case SG_EMULATED_HOST:
 		return sg_emulated_host(q, arg);
-	case SG_IO: {
-		struct sg_io_hdr hdr;
-
-		error = get_sg_io_hdr(&hdr, arg);
-		if (error)
-			return error;
-
-		error = sg_io(q, disk, &hdr, mode);
-		if (error == -EFAULT)
-			return error;
-
-		if (put_sg_io_hdr(&hdr, arg))
-			return -EFAULT;
-		return 0;
-	}
+	case SG_IO:
+		return scsi_ioctl_sg_io(q, disk, mode, arg);
 	case SCSI_IOCTL_SEND_COMMAND:
 		return sg_scsi_ioctl(q, disk, mode, arg);
 	case CDROM_SEND_PACKET:
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 24/24] scsi: unexport sg_scsi_ioctl
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (22 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 23/24] scsi: factor SG_IO " Christoph Hellwig
@ 2021-07-12  5:48 ` Christoph Hellwig
  2021-07-21  5:38 ` cleanup SCSI ioctl support Christoph Hellwig
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-12  5:48 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Just call scsi_ioctl in sg as that has the same effect.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/scsi_ioctl.c | 5 ++---
 drivers/scsi/sg.c         | 2 +-
 include/scsi/scsi_ioctl.h | 2 --
 3 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 2492c628fd38..2cbbd49760f8 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -524,8 +524,8 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
  *      Positive numbers returned are the compacted SCSI error codes (4
  *      bytes in one int) where the lowest byte is the SCSI status.
  */
-int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
-		struct scsi_ioctl_command __user *sic)
+static int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk,
+		fmode_t mode, struct scsi_ioctl_command __user *sic)
 {
 	enum { OMAX_SB_LEN = 16 };	/* For backward compatibility */
 	struct request *rq;
@@ -637,7 +637,6 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
 
 	return err;
 }
-EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
 
 int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp)
 {
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index c86fa4476334..9be76deea242 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1109,7 +1109,7 @@ sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp,
 	case SCSI_IOCTL_SEND_COMMAND:
 		if (atomic_read(&sdp->detaching))
 			return -ENODEV;
-		return sg_scsi_ioctl(sdp->device->request_queue, NULL, filp->f_mode, p);
+		return scsi_ioctl(sdp->device, NULL, filp->f_mode, cmd_in, p);
 	case SG_SET_DEBUG:
 		result = get_user(val, ip);
 		if (result)
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index b3918fded464..d2cb9aeaf1f1 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -47,8 +47,6 @@ int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
 		int cmd, bool ndelay);
 int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
 		int cmd, void __user *arg);
-int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
-			 struct scsi_ioctl_command __user *argp);
 int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp);
 int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp);
 bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: cleanup SCSI ioctl support
  2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
                   ` (23 preceding siblings ...)
  2021-07-12  5:48 ` [PATCH 24/24] scsi: unexport sg_scsi_ioctl Christoph Hellwig
@ 2021-07-21  5:38 ` Christoph Hellwig
  24 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-21  5:38 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Any comments?

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 01/24] bsg: remove support for SCSI_IOCTL_SEND_COMMAND
  2021-07-12  5:47 ` [PATCH 01/24] bsg: remove support for SCSI_IOCTL_SEND_COMMAND Christoph Hellwig
@ 2021-07-22 17:31   ` Bart Van Assche
  2021-07-22 19:05     ` Christoph Hellwig
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Van Assche @ 2021-07-22 17:31 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

On 7/11/21 10:47 PM, Christoph Hellwig wrote:
> SCSI_IOCTL_SEND_COMMAND has been deprecated longer than bsg exists
> and has been warning for just as long.  More importantly it harcodes
> SCSI CDBs and thus will do the wrong thing on non-scsi bsg nodes.
> 
> Fixes: aa387cc89567 ("block: add bsg helper library")
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>   block/bsg.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/block/bsg.c b/block/bsg.c
> index 1f196563ae6c..79b42c5cafeb 100644
> --- a/block/bsg.c
> +++ b/block/bsg.c
> @@ -373,10 +373,13 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>   	case SG_GET_RESERVED_SIZE:
>   	case SG_SET_RESERVED_SIZE:
>   	case SG_EMULATED_HOST:
> -	case SCSI_IOCTL_SEND_COMMAND:
>   		return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg);
>   	case SG_IO:
>   		return bsg_sg_io(bd->queue, file->f_mode, uarg);
> +	case SCSI_IOCTL_SEND_COMMAND:
> +		pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND\n",
> +				current->comm);
> +		return -EINVAL;
>   	default:
>   		return -ENOTTY;
>   	}

The Fixes: tag will cause this patch to be backported to stable trees. 
Is that intentional?

Anyway:

Reviewed-by: Bart Van Assche <bvanassche@acm.org>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 12/24] block: add a queue_max_sectors_bytes helper
  2021-07-12  5:48 ` [PATCH 12/24] block: add a queue_max_sectors_bytes helper Christoph Hellwig
@ 2021-07-22 17:37   ` Bart Van Assche
  2021-07-22 19:08     ` Christoph Hellwig
  2021-07-22 18:00   ` Martin K. Petersen
  1 sibling, 1 reply; 45+ messages in thread
From: Bart Van Assche @ 2021-07-22 17:37 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

On 7/11/21 10:48 PM, Christoph Hellwig wrote:
> +static inline int queue_max_sectors_bytes(struct request_queue *q)
> +{
> +	return min_t(unsigned int, queue_max_sectors(q), INT_MAX >> 9) << 9;
> +}

Should this function return a signed or an unsigned integer? I'm asking 
because I see 'unsigned int' as the first argument for min_t().

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 17/24] scsi_ioctl: simplify SCSI passthrough permission checking
  2021-07-12  5:48 ` [PATCH 17/24] scsi_ioctl: simplify SCSI passthrough permission checking Christoph Hellwig
@ 2021-07-22 17:47   ` Bart Van Assche
  2021-07-22 19:12     ` Christoph Hellwig
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Van Assche @ 2021-07-22 17:47 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

On 7/11/21 10:48 PM, Christoph Hellwig wrote:
> +bool scsi_cmd_allowed(unsigned char *cmd, fmode_t mode)
>   {

The first time I encountered this function it was not clear to me what 
the purpose of this function is. I think this is a good time to add a 
comment above this function that explains its purpose, namely to prevent 
that unprivileged SG I/O users can modify storage device firmware.

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 19/24] scsi: rename CONFIG_BLK_SCSI_REQUEST to CONFIG_SCSI_COMMON
  2021-07-12  5:48 ` [PATCH 19/24] scsi: rename CONFIG_BLK_SCSI_REQUEST to CONFIG_SCSI_COMMON Christoph Hellwig
@ 2021-07-22 17:51   ` Martin K. Petersen
  2021-07-22 19:17     ` Christoph Hellwig
  0 siblings, 1 reply; 45+ messages in thread
From: Martin K. Petersen @ 2021-07-22 17:51 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Martin K. Petersen, Jens Axboe, FUJITA Tomonori, Doug Gilbert,
	Kai Mäkisara, linux-block, linux-scsi


Christoph,

> CONFIG_BLK_SCSI_REQUEST is rather misnamed now as it just enabled
> building a small amount of code shared by the scsi initiator, target
> and consumers of the scsi_request passthrough API.  Rename it and also
> allow building it as a module.

Build now fails. Needs:

diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c
index 8aac4e5e8c4c..4fb16e70dddf 100644
--- a/drivers/scsi/scsi_common.c
+++ b/drivers/scsi/scsi_common.c
@@ -7,9 +7,12 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi_common.h>

+MODULE_LICENSE("GPL v2");
+

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [PATCH 20/24] scsi: remove a very misleading comment
  2021-07-12  5:48 ` [PATCH 20/24] scsi: remove a very misleading comment Christoph Hellwig
@ 2021-07-22 17:52   ` Bart Van Assche
  2021-07-22 19:21     ` Christoph Hellwig
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Van Assche @ 2021-07-22 17:52 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

On 7/11/21 10:48 PM, Christoph Hellwig wrote:
> Remove the comment above ioctl_internal_command, which doesn't
> document this function at all.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>   drivers/scsi/scsi_ioctl.c | 23 -----------------------
>   1 file changed, 23 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
> index a70ddc1eb313..3d4311a78383 100644
> --- a/drivers/scsi/scsi_ioctl.c
> +++ b/drivers/scsi/scsi_ioctl.c
> @@ -64,29 +64,6 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer)
>   	return 1;
>   }
>   
> -/*
> -
> - * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
> - * The IOCTL_NORMAL_TIMEOUT and NORMAL_RETRIES  variables are used.
> - *
> - * dev is the SCSI device struct ptr, *(int *) arg is the length of the
> - * input data, if any, not including the command string & counts,
> - * *((int *)arg + 1) is the output buffer size in bytes.
> - *
> - * *(char *) ((int *) arg)[2] the actual command byte.
> - *
> - * Note that if more than MAX_BUF bytes are requested to be transferred,
> - * the ioctl will fail with error EINVAL.
> - *
> - * This size *does not* include the initial lengths that were passed.
> - *
> - * The SCSI command is read from the memory location immediately after the
> - * length words, and the input data is right after the command.  The SCSI
> - * routines know the command size based on the opcode decode.
> - *
> - * The output area is then filled in starting from the command byte.
> - */
> -
>   static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
>   				  int timeout, int retries)
>   {

How about adding a comment that explains what this function does? How 
about declaring 'cmd' const and adding a comment that it is a pointer to 
a SCSI CDB? How about documenting the unit of 'timeout'?

Thanks,

Bart.


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 12/24] block: add a queue_max_sectors_bytes helper
  2021-07-12  5:48 ` [PATCH 12/24] block: add a queue_max_sectors_bytes helper Christoph Hellwig
  2021-07-22 17:37   ` Bart Van Assche
@ 2021-07-22 18:00   ` Martin K. Petersen
  2021-07-22 19:10     ` Christoph Hellwig
  1 sibling, 1 reply; 45+ messages in thread
From: Martin K. Petersen @ 2021-07-22 18:00 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Martin K. Petersen, Jens Axboe, FUJITA Tomonori, Doug Gilbert,
	Kai Mäkisara, linux-block, linux-scsi


Christoph,

> +static inline int queue_max_sectors_bytes(struct request_queue *q)
> +{
> +	return min_t(unsigned int, queue_max_sectors(q), INT_MAX >> 9) << 9;
> +}
> +

Maybe simply queue_max_bytes()?

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 14/24] bsg: move bsg_scsi_ops to drivers/scsi/
  2021-07-12  5:48 ` [PATCH 14/24] bsg: move bsg_scsi_ops to drivers/scsi/ Christoph Hellwig
@ 2021-07-22 18:03   ` Martin K. Petersen
  2021-07-22 19:11     ` Christoph Hellwig
  0 siblings, 1 reply; 45+ messages in thread
From: Martin K. Petersen @ 2021-07-22 18:03 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Martin K. Petersen, Jens Axboe, FUJITA Tomonori, Doug Gilbert,
	Kai Mäkisara, linux-block, linux-scsi


Christoph,

> Move the SCSI-specific bsg code in the SCSI midlayer instead of in the
> common bsg code.  This just keeps the common bsg code block/ and also
> allows building it as a module.

> +static const struct bsg_ops bsg_scsi_ops = {
> +	.check_proto		= bsg_scsi_check_proto,
> +	.fill_hdr		= bsg_scsi_fill_hdr,
> +	.complete_rq		= bsg_scsi_complete_rq,
> +	.free_rq		= bsg_scsi_free_rq,
> +};

Maybe just cosmetic, but now that this code lives in scsi_bsg.c (which I
do like), I think these functions should be named
scsi_bsg_check_proto(), etc.

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 18/24] scsi_ioctl: move all "block layer" SCSI ioctl handling to drivers/scsi
  2021-07-12  5:48 ` [PATCH 18/24] scsi_ioctl: move all "block layer" SCSI ioctl handling to drivers/scsi Christoph Hellwig
@ 2021-07-22 18:06   ` Martin K. Petersen
  2021-07-22 19:16     ` Christoph Hellwig
  0 siblings, 1 reply; 45+ messages in thread
From: Martin K. Petersen @ 2021-07-22 18:06 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Martin K. Petersen, Jens Axboe, FUJITA Tomonori, Doug Gilbert,
	Kai Mäkisara, linux-block, linux-scsi


Christoph,

> Merge the ioctl handling in block/scsi_ioctl.c into its only caller in
> drivers/scsi/scsi_ioctl.c.

> +static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
> +			     struct sg_io_hdr *hdr, fmode_t mode)

[...]

> +static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
> +				 struct bio *bio)
> +{

Another couple of peculiar naming vestiges. These probably shouldn't
have a "blk_" prefix now that they are under SCSI. Since they are
internal to scsi_ioctl.c I propose you either drop the prefix completely
or make it "scsi_".

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 21/24] scsi: consolidate the START STOP UNIT handling
  2021-07-12  5:48 ` [PATCH 21/24] scsi: consolidate the START STOP UNIT handling Christoph Hellwig
@ 2021-07-22 18:44   ` Bart Van Assche
  2021-07-22 19:20     ` Christoph Hellwig
  0 siblings, 1 reply; 45+ messages in thread
From: Bart Van Assche @ 2021-07-22 18:44 UTC (permalink / raw)
  To: Christoph Hellwig, Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

On 7/11/21 10:48 PM, Christoph Hellwig wrote:
> +	char cdb[MAX_COMMAND_SIZE] = { };

How about using 'u8' instead of 'char'?

Additionally, MAX_COMMAND_SIZE equals 16. According to SBC-4 6 bytes is 
enough for the START STOP UNIT command.

> +	cdb[0] = START_STOP;
> +	cdb[4] = data;

Please combine the above two statements with the cdb[] declaration into 
a single line.

Additionally, please split data into two arguments to make calls of this 
function easier to read. This is what I found in SBC-4:
* bit 1 of byte 4 has the name LOEJ (load eject).
* bit 0 of byte 4 has the name START (start unit).

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 01/24] bsg: remove support for SCSI_IOCTL_SEND_COMMAND
  2021-07-22 17:31   ` Bart Van Assche
@ 2021-07-22 19:05     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:05 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Christoph Hellwig, Martin K. Petersen, Jens Axboe,
	FUJITA Tomonori, Doug Gilbert, Kai Mäkisara, linux-block,
	linux-scsi

On Thu, Jul 22, 2021 at 10:31:13AM -0700, Bart Van Assche wrote:
>> +				current->comm);
>> +		return -EINVAL;
>>   	default:
>>   		return -ENOTTY;
>>   	}
>
> The Fixes: tag will cause this patch to be backported to stable trees. Is 
> that intentional?

Yes, as this ioctl actively does the wrong thing for non-scsi queues.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 12/24] block: add a queue_max_sectors_bytes helper
  2021-07-22 17:37   ` Bart Van Assche
@ 2021-07-22 19:08     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:08 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Christoph Hellwig, Martin K. Petersen, Jens Axboe,
	FUJITA Tomonori, Doug Gilbert, Kai Mäkisara, linux-block,
	linux-scsi

On Thu, Jul 22, 2021 at 10:37:36AM -0700, Bart Van Assche wrote:
> On 7/11/21 10:48 PM, Christoph Hellwig wrote:
>> +static inline int queue_max_sectors_bytes(struct request_queue *q)
>> +{
>> +	return min_t(unsigned int, queue_max_sectors(q), INT_MAX >> 9) << 9;
>> +}
>
> Should this function return a signed or an unsigned integer? I'm asking 
> because I see 'unsigned int' as the first argument for min_t().

Yes, it really should be unsigned.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 12/24] block: add a queue_max_sectors_bytes helper
  2021-07-22 18:00   ` Martin K. Petersen
@ 2021-07-22 19:10     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Christoph Hellwig, Jens Axboe, FUJITA Tomonori, Doug Gilbert,
	Kai Mäkisara, linux-block, linux-scsi

On Thu, Jul 22, 2021 at 02:00:57PM -0400, Martin K. Petersen wrote:
> Maybe simply queue_max_bytes()?

Fine with me.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 14/24] bsg: move bsg_scsi_ops to drivers/scsi/
  2021-07-22 18:03   ` Martin K. Petersen
@ 2021-07-22 19:11     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:11 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Christoph Hellwig, Jens Axboe, FUJITA Tomonori, Doug Gilbert,
	Kai Mäkisara, linux-block, linux-scsi

On Thu, Jul 22, 2021 at 02:03:10PM -0400, Martin K. Petersen wrote:
> Maybe just cosmetic, but now that this code lives in scsi_bsg.c (which I
> do like), I think these functions should be named
> scsi_bsg_check_proto(), etc.

Done.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 17/24] scsi_ioctl: simplify SCSI passthrough permission checking
  2021-07-22 17:47   ` Bart Van Assche
@ 2021-07-22 19:12     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:12 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Christoph Hellwig, Martin K. Petersen, Jens Axboe,
	FUJITA Tomonori, Doug Gilbert, Kai Mäkisara, linux-block,
	linux-scsi

On Thu, Jul 22, 2021 at 10:47:35AM -0700, Bart Van Assche wrote:
> The first time I encountered this function it was not clear to me what the 
> purpose of this function is. I think this is a good time to add a comment 
> above this function that explains its purpose, namely to prevent that 
> unprivileged SG I/O users can modify storage device firmware.

Or generally do unexpected things, yes.  I'll add a patch at the end of
the series to avoid the pain of adding a comment first and then moving
the whole code around.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 18/24] scsi_ioctl: move all "block layer" SCSI ioctl handling to drivers/scsi
  2021-07-22 18:06   ` Martin K. Petersen
@ 2021-07-22 19:16     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:16 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Christoph Hellwig, Jens Axboe, FUJITA Tomonori, Doug Gilbert,
	Kai Mäkisara, linux-block, linux-scsi

On Thu, Jul 22, 2021 at 02:06:40PM -0400, Martin K. Petersen wrote:
> > +static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
> > +			     struct sg_io_hdr *hdr, fmode_t mode)
> 
> [...]
> 
> > +static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
> > +				 struct bio *bio)
> > +{
> 
> Another couple of peculiar naming vestiges. These probably shouldn't
> have a "blk_" prefix now that they are under SCSI. Since they are
> internal to scsi_ioctl.c I propose you either drop the prefix completely
> or make it "scsi_".

Ok.  I'll keep __blk_send_generic and its callers for now as they'll
get removed later in the series.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 19/24] scsi: rename CONFIG_BLK_SCSI_REQUEST to CONFIG_SCSI_COMMON
  2021-07-22 17:51   ` Martin K. Petersen
@ 2021-07-22 19:17     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:17 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Christoph Hellwig, Jens Axboe, FUJITA Tomonori, Doug Gilbert,
	Kai Mäkisara, linux-block, linux-scsi

On Thu, Jul 22, 2021 at 01:51:28PM -0400, Martin K. Petersen wrote:
> 
> Christoph,
> 
> > CONFIG_BLK_SCSI_REQUEST is rather misnamed now as it just enabled
> > building a small amount of code shared by the scsi initiator, target
> > and consumers of the scsi_request passthrough API.  Rename it and also
> > allow building it as a module.
> 
> Build now fails. Needs:

Interesting - this did not show up in any of my builds and not in weeks
of buildbot coverage.  But I'll add the include just to be on the safe
side.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 21/24] scsi: consolidate the START STOP UNIT handling
  2021-07-22 18:44   ` Bart Van Assche
@ 2021-07-22 19:20     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:20 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Christoph Hellwig, Martin K. Petersen, Jens Axboe,
	FUJITA Tomonori, Doug Gilbert, Kai Mäkisara, linux-block,
	linux-scsi

On Thu, Jul 22, 2021 at 11:44:33AM -0700, Bart Van Assche wrote:
> On 7/11/21 10:48 PM, Christoph Hellwig wrote:
>> +	char cdb[MAX_COMMAND_SIZE] = { };
>
> How about using 'u8' instead of 'char'?

Sure.

>
> Additionally, MAX_COMMAND_SIZE equals 16. According to SBC-4 6 bytes is 
> enough for the START STOP UNIT command.

This just keeps the existing logic.

>
>> +	cdb[0] = START_STOP;
>> +	cdb[4] = data;
>
> Please combine the above two statements with the cdb[] declaration into a 
> single line.

Just keeping the style of the existing code, which seems fine.  Even
when initializing at declaration time this would have to be multiple
lines to stay readable.

> Additionally, please split data into two arguments to make calls of this 
> function easier to read. This is what I found in SBC-4:
> * bit 1 of byte 4 has the name LOEJ (load eject).
> * bit 0 of byte 4 has the name START (start unit).

Not sure how that really helps anyone.  And again I'm not trying to
do a grand rewrite, just consoidating the existing code a bit.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH 20/24] scsi: remove a very misleading comment
  2021-07-22 17:52   ` Bart Van Assche
@ 2021-07-22 19:21     ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-22 19:21 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Christoph Hellwig, Martin K. Petersen, Jens Axboe,
	FUJITA Tomonori, Doug Gilbert, Kai Mäkisara, linux-block,
	linux-scsi

On Thu, Jul 22, 2021 at 10:52:44AM -0700, Bart Van Assche wrote:
>> - * routines know the command size based on the opcode decode.
>> - *
>> - * The output area is then filled in starting from the command byte.
>> - */
>> -
>>   static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
>>   				  int timeout, int retries)
>>   {
>
> How about adding a comment that explains what this function does? How about 
> declaring 'cmd' const and adding a comment that it is a pointer to a SCSI 
> CDB? How about documenting the unit of 'timeout'?

Not sure there is much of a point for a static function in (pun intended)
fairly static code.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH 04/24] ch: consolidate compat ioctl handling
  2021-07-24  7:20 cleanup SCSI ioctl support v2 Christoph Hellwig
@ 2021-07-24  7:20 ` Christoph Hellwig
  0 siblings, 0 replies; 45+ messages in thread
From: Christoph Hellwig @ 2021-07-24  7:20 UTC (permalink / raw)
  To: Martin K. Petersen, Jens Axboe, FUJITA Tomonori
  Cc: Doug Gilbert, Kai Mäkisara, linux-block, linux-scsi

Merge the native and compat ioctl handlers into a single one using
in_compat_syscall().

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/scsi/ch.c | 73 ++++++++++++++---------------------------------
 1 file changed, 22 insertions(+), 51 deletions(-)

diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index fc7197abfcdf..e89f226cae5c 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -618,6 +618,12 @@ ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
 	return 0;
 }
 
+struct changer_element_status32 {
+	int		ces_type;
+	compat_uptr_t	ces_data;
+};
+#define CHIOGSTATUS32  _IOW('c', 8,struct changer_element_status32)
+
 static long ch_ioctl(struct file *file,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -748,7 +754,20 @@ static long ch_ioctl(struct file *file,
 
 		return ch_gstatus(ch, ces.ces_type, ces.ces_data);
 	}
+#ifdef CONFIG_COMPAT
+	case CHIOGSTATUS32:
+	{
+		struct changer_element_status32 ces32;
+
+		if (copy_from_user(&ces32, argp, sizeof (ces32)))
+			return -EFAULT;
+		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
+			return -EINVAL;
 
+		return ch_gstatus(ch, ces32.ces_type,
+				  compat_ptr(ces32.ces_data));
+	}
+#endif
 	case CHIOGELEM:
 	{
 		struct changer_get_element cge;
@@ -858,59 +877,13 @@ static long ch_ioctl(struct file *file,
 	}
 
 	default:
+		if (in_compat_syscall())
+			return scsi_compat_ioctl(ch->device, cmd, argp);
 		return scsi_ioctl(ch->device, cmd, argp);
 
 	}
 }
 
-#ifdef CONFIG_COMPAT
-
-struct changer_element_status32 {
-	int		ces_type;
-	compat_uptr_t	ces_data;
-};
-#define CHIOGSTATUS32  _IOW('c', 8,struct changer_element_status32)
-
-static long ch_ioctl_compat(struct file * file,
-			    unsigned int cmd, unsigned long arg)
-{
-	scsi_changer *ch = file->private_data;
-	int retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
-							file->f_flags & O_NDELAY);
-	if (retval)
-		return retval;
-
-	switch (cmd) {
-	case CHIOGPARAMS:
-	case CHIOGVPARAMS:
-	case CHIOPOSITION:
-	case CHIOMOVE:
-	case CHIOEXCHANGE:
-	case CHIOGELEM:
-	case CHIOINITELEM:
-	case CHIOSVOLTAG:
-		/* compatible */
-		return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
-	case CHIOGSTATUS32:
-	{
-		struct changer_element_status32 ces32;
-		unsigned char __user *data;
-
-		if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
-			return -EFAULT;
-		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
-			return -EINVAL;
-
-		data = compat_ptr(ces32.ces_data);
-		return ch_gstatus(ch, ces32.ces_type, data);
-	}
-	default:
-		return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg));
-
-	}
-}
-#endif
-
 /* ------------------------------------------------------------------------ */
 
 static int ch_probe(struct device *dev)
@@ -1015,9 +988,7 @@ static const struct file_operations changer_fops = {
 	.open		= ch_open,
 	.release	= ch_release,
 	.unlocked_ioctl	= ch_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= ch_ioctl_compat,
-#endif
+	.compat_ioctl	= compat_ptr_ioctl,
 	.llseek		= noop_llseek,
 };
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2021-07-24  7:22 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-12  5:47 cleanup SCSI ioctl support Christoph Hellwig
2021-07-12  5:47 ` [PATCH 01/24] bsg: remove support for SCSI_IOCTL_SEND_COMMAND Christoph Hellwig
2021-07-22 17:31   ` Bart Van Assche
2021-07-22 19:05     ` Christoph Hellwig
2021-07-12  5:47 ` [PATCH 02/24] sr: consolidate compat ioctl handling Christoph Hellwig
2021-07-12  5:47 ` [PATCH 03/24] sd: " Christoph Hellwig
2021-07-12  5:47 ` [PATCH 04/24] ch: " Christoph Hellwig
2021-07-12  5:47 ` [PATCH 05/24] cg: " Christoph Hellwig
2021-07-12  5:47 ` [PATCH 06/24] scsi: remove scsi_compat_ioctl Christoph Hellwig
2021-07-12  5:47 ` [PATCH 07/24] st: simplify ioctl handling Christoph Hellwig
2021-07-12  5:48 ` [PATCH 08/24] cdrom: remove the call to scsi_cmd_blk_ioctl from cdrom_ioctl Christoph Hellwig
2021-07-12  5:48 ` [PATCH 09/24] scsi_ioctl: remove scsi_cmd_blk_ioctl Christoph Hellwig
2021-07-12  5:48 ` [PATCH 10/24] scsi_ioctl: remove scsi_verify_blk_ioctl Christoph Hellwig
2021-07-12  5:48 ` [PATCH 11/24] scsi: call scsi_cmd_ioctl from scsi_ioctl Christoph Hellwig
2021-07-12  5:48 ` [PATCH 12/24] block: add a queue_max_sectors_bytes helper Christoph Hellwig
2021-07-22 17:37   ` Bart Van Assche
2021-07-22 19:08     ` Christoph Hellwig
2021-07-22 18:00   ` Martin K. Petersen
2021-07-22 19:10     ` Christoph Hellwig
2021-07-12  5:48 ` [PATCH 13/24] bsg: decouple from scsi_cmd_ioctl Christoph Hellwig
2021-07-12  5:48 ` [PATCH 14/24] bsg: move bsg_scsi_ops to drivers/scsi/ Christoph Hellwig
2021-07-22 18:03   ` Martin K. Petersen
2021-07-22 19:11     ` Christoph Hellwig
2021-07-12  5:48 ` [PATCH 15/24] scsi_ioctl: remove scsi_req_init Christoph Hellwig
2021-07-12  5:48 ` [PATCH 16/24] scsi_ioctl: move scsi_command_size_tbl to scsi_common.c Christoph Hellwig
2021-07-12  5:48 ` [PATCH 17/24] scsi_ioctl: simplify SCSI passthrough permission checking Christoph Hellwig
2021-07-22 17:47   ` Bart Van Assche
2021-07-22 19:12     ` Christoph Hellwig
2021-07-12  5:48 ` [PATCH 18/24] scsi_ioctl: move all "block layer" SCSI ioctl handling to drivers/scsi Christoph Hellwig
2021-07-22 18:06   ` Martin K. Petersen
2021-07-22 19:16     ` Christoph Hellwig
2021-07-12  5:48 ` [PATCH 19/24] scsi: rename CONFIG_BLK_SCSI_REQUEST to CONFIG_SCSI_COMMON Christoph Hellwig
2021-07-22 17:51   ` Martin K. Petersen
2021-07-22 19:17     ` Christoph Hellwig
2021-07-12  5:48 ` [PATCH 20/24] scsi: remove a very misleading comment Christoph Hellwig
2021-07-22 17:52   ` Bart Van Assche
2021-07-22 19:21     ` Christoph Hellwig
2021-07-12  5:48 ` [PATCH 21/24] scsi: consolidate the START STOP UNIT handling Christoph Hellwig
2021-07-22 18:44   ` Bart Van Assche
2021-07-22 19:20     ` Christoph Hellwig
2021-07-12  5:48 ` [PATCH 22/24] scsi: factor SCSI_IOCTL_GET_IDLUN handling into a helper Christoph Hellwig
2021-07-12  5:48 ` [PATCH 23/24] scsi: factor SG_IO " Christoph Hellwig
2021-07-12  5:48 ` [PATCH 24/24] scsi: unexport sg_scsi_ioctl Christoph Hellwig
2021-07-21  5:38 ` cleanup SCSI ioctl support Christoph Hellwig
2021-07-24  7:20 cleanup SCSI ioctl support v2 Christoph Hellwig
2021-07-24  7:20 ` [PATCH 04/24] ch: consolidate compat ioctl handling Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).