Hi Jens, James and Martin, This series concludes the work I did for linux-5.5 on the compat_ioctl() cleanup, killing off fs/compat_ioctl.c and block/compat_ioctl.c by moving everything into drivers. Overall this would be a reduction both in complexity and line count, but as I'm also adding documentation the overall number of lines increases in the end. My plan was originally to keep the SCSI and block parts separate. This did not work easily because of interdependencies: I cannot do the final SCSI cleanup in a good way without first addressing the CDROM ioctls, so this is one series that I hope could be merged through either the block or the scsi git trees, or possibly both if you can pull in the same branch. The series comes in these steps: 1. clean up the sg v3 interface as suggested by Linus. I have talked about this with Doug Gilbert as well, and he would rebase his sg v4 patches on top of "compat: scsi: sg: fix v3 compat read/write interface" 2. Four patches for missing block compat_ioctl handlers, to be backported into stable kernels. Separate patches because they are needed in different stable versions. 3. Actually moving handlers out of block/compat_ioctl.c and block/scsi_ioctl.c into drivers, mixed in with cleanup patches 4. Document how to do this right. I keep getting asked about this, and it helps to point to some documentation file. The series is avaialable for testing at [1]. Arnd [1] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git/log/?h=compat-ioctl-endgame Arnd Bergmann (24): compat: ARM64: always include asm-generic/compat.h compat: scsi: sg: fix v3 compat read/write interface compat_ioctl: block: handle BLKREPORTZONE/BLKRESETZONE compat_ioctl: block: handle BLKGETZONESZ/BLKGETNRZONES compat_ioctl: block: handle add zone open, close and finish ioctl compat_ioctl: block: handle Persistent Reservations compaT_ioctl: ubd, aoe: use blkdev_compat_ptr_ioctl compat_ioctl: move CDROM_SEND_PACKET handling into scsi compat_ioctl: move CDROMREADADIO to cdrom.c compat_ioctl: cdrom: handle CDROM_LAST_WRITTEN compat_ioctl: block: handle cdrom compat ioctl in non-cdrom drivers compat_ioctl: add scsi_compat_ioctl compat_ioctl: bsg: add handler compat_ioctl: ide: floppy: add handler compat_ioctl: scsi: move ioctl handling into drivers compat_ioctl: move sys_compat_ioctl() to ioctl.c compat_ioctl: simplify the implementation compat_ioctl: move cdrom commands into cdrom.c compat_ioctl: scsi: handle HDIO commands from drivers compat_ioctl: move HDIO ioctl handling into drivers/ide compat_ioctl: block: move blkdev_compat_ioctl() into ioctl.c compat_ioctl: block: simplify compat_blkpg_ioctl() compat_ioctl: simplify up block/ioctl.c Documentation: document ioctl interfaces better Documentation/core-api/index.rst | 1 + Documentation/core-api/ioctl.rst | 250 +++++++++++++++ arch/arm64/include/asm/compat.h | 5 +- arch/um/drivers/ubd_kern.c | 1 + block/Makefile | 1 - block/bsg.c | 1 + block/compat_ioctl.c | 411 ------------------------- block/ioctl.c | 319 +++++++++++++++---- block/scsi_ioctl.c | 214 ++++++++----- drivers/ata/libata-scsi.c | 9 + drivers/block/aoe/aoeblk.c | 1 + drivers/block/floppy.c | 3 + drivers/block/paride/pcd.c | 3 + drivers/block/paride/pd.c | 1 + drivers/block/paride/pf.c | 1 + drivers/block/pktcdvd.c | 26 +- drivers/block/sunvdc.c | 1 + drivers/block/virtio_blk.c | 3 + drivers/block/xen-blkfront.c | 1 + drivers/cdrom/cdrom.c | 35 ++- drivers/cdrom/gdrom.c | 3 + drivers/ide/ide-cd.c | 40 +++ drivers/ide/ide-disk.c | 3 + drivers/ide/ide-floppy.c | 4 + drivers/ide/ide-floppy.h | 2 + drivers/ide/ide-floppy_ioctl.c | 35 +++ drivers/ide/ide-gd.c | 14 + drivers/ide/ide-ioctls.c | 47 ++- drivers/ide/ide-tape.c | 14 + drivers/scsi/aic94xx/aic94xx_init.c | 3 + drivers/scsi/ch.c | 9 +- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 + drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 + drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 + drivers/scsi/ipr.c | 3 + drivers/scsi/isci/init.c | 3 + drivers/scsi/mvsas/mv_init.c | 3 + drivers/scsi/pm8001/pm8001_init.c | 3 + drivers/scsi/scsi_ioctl.c | 54 +++- drivers/scsi/sd.c | 50 ++- drivers/scsi/sg.c | 169 +++++----- drivers/scsi/sr.c | 53 +++- drivers/scsi/st.c | 51 +-- fs/Makefile | 2 +- fs/compat_ioctl.c | 261 ---------------- fs/internal.h | 6 - fs/ioctl.c | 131 +++++--- include/linux/blkdev.h | 7 + include/linux/falloc.h | 2 - include/linux/fs.h | 4 - include/linux/ide.h | 2 + include/linux/libata.h | 6 + include/scsi/scsi_ioctl.h | 1 + include/scsi/sg.h | 30 ++ 54 files changed, 1249 insertions(+), 1062 deletions(-) create mode 100644 Documentation/core-api/ioctl.rst delete mode 100644 block/compat_ioctl.c delete mode 100644 fs/compat_ioctl.c -- 2.20.0 Cc: corbet at lwn.net Cc: catalin.marinas at arm.com Cc: will at kernel.org Cc: jdike at addtoit.com Cc: richard at nod.at Cc: anton.ivanov at cambridgegreys.com Cc: fujita.tomonori at lab.ntt.co.jp Cc: justin at coraid.com Cc: efremov at linux.com Cc: tim at cyberelk.net Cc: mst at redhat.com Cc: jasowang at redhat.com Cc: pbonzini at redhat.com Cc: stefanha at redhat.com Cc: boris.ostrovsky at oracle.com Cc: jgross at suse.com Cc: sstabellini at kernel.org Cc: konrad.wilk at oracle.com Cc: roger.pau at citrix.com Cc: bp at alien8.de Cc: davem at davemloft.net Cc: john.garry at huawei.com Cc: brking at us.ibm.com Cc: intel-linux-scu at intel.com Cc: artur.paszkiewicz at intel.com Cc: jinpu.wang at cloud.ionos.com Cc: dgilbert at interlog.com Cc: Kai.Makisara at kolumbus.fi Cc: arnd at arndb.de Cc: damien.lemoal at hgst.com Cc: hare at suse.com Cc: linux-doc at vger.kernel.org Cc: linux-kernel at vger.kernel.org Cc: linux-block at vger.kernel.org Cc: linux-arm-kernel at lists.infradead.org Cc: linux-um at lists.infradead.org Cc: linux-scsi at vger.kernel.org Cc: linux-ide at vger.kernel.org Cc: virtualization at lists.linux-foundation.org Cc: xen-devel at lists.xenproject.org Cc: linux-fsdevel at vger.kernel.org
Arnd Bergmann
2019-Dec-11 20:42 UTC
[PATCH 15/24] compat_ioctl: scsi: move ioctl handling into drivers
Each driver calling scsi_ioctl() gets an equivalent compat_ioctl() handler that implements the same commands by calling scsi_compat_ioctl(). The scsi_cmd_ioctl() and scsi_cmd_blk_ioctl() functions are compatible at this point, so any driver that calls those can do so for both native and compat mode, with the argument passed through compat_ptr(). With this, we can remove the entries from fs/compat_ioctl.c. The new code is larger, but should be easier to maintain and keep updated with newly added commands. Signed-off-by: Arnd Bergmann <arnd at arndb.de> --- drivers/block/virtio_blk.c | 3 + drivers/scsi/ch.c | 9 ++- drivers/scsi/sd.c | 50 ++++++-------- drivers/scsi/sg.c | 44 ++++++++----- drivers/scsi/sr.c | 57 ++++++++++++++-- drivers/scsi/st.c | 51 ++++++++------ fs/compat_ioctl.c | 132 +------------------------------------ 7 files changed, 142 insertions(+), 204 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 7ffd719d89de..fbbf18ac1d5d 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -405,6 +405,9 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) static const struct block_device_operations virtblk_fops = { .ioctl = virtblk_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = blkdev_compat_ptr_ioctl, +#endif .owner = THIS_MODULE, .getgeo = virtblk_getgeo, }; diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 76751d6c7f0d..ed5f4a6ae270 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -872,6 +872,10 @@ 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: @@ -883,7 +887,7 @@ static long ch_ioctl_compat(struct file * file, case CHIOINITELEM: case CHIOSVOLTAG: /* compatible */ - return ch_ioctl(file, cmd, arg); + return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); case CHIOGSTATUS32: { struct changer_element_status32 ces32; @@ -898,8 +902,7 @@ static long ch_ioctl_compat(struct file * file, return ch_gstatus(ch, ces32.ces_type, data); } default: - // return scsi_ioctl_compat(ch->device, cmd, (void*)arg); - return -ENOIOCTLCMD; + return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg)); } } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cea625906440..5afb0046b12a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1465,13 +1465,12 @@ 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(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) +static int sd_ioctl_common(struct block_device *bdev, fmode_t mode, + unsigned int cmd, void __user *p) { 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, " @@ -1507,9 +1506,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, break; default: error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); - if (error != -ENOTTY) - break; - error = scsi_ioctl(sdp, cmd, p); break; } out: @@ -1691,39 +1687,31 @@ static void sd_rescan(struct device *dev) 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 -/* - * This gets directly called from VFS. When the ioctl - * is not recognized we go back to the other translation paths. - */ static int sd_compat_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 *sdev = sdkp->device; void __user *p = compat_ptr(arg); - int error; - - error = scsi_verify_blk_ioctl(bdev, cmd); - if (error < 0) - return error; + int ret; - error = scsi_ioctl_block_when_processing_errors(sdev, cmd, - (mode & FMODE_NDELAY) != 0); - if (error) - return error; + ret = sd_ioctl_common(bdev, mode, cmd, p); + if (ret != -ENOTTY) + return ret; - if (is_sed_ioctl(cmd)) - return sed_ioctl(sdkp->opal_dev, cmd, p); - - /* - * Let the static ioctl translation table take care of it. - */ - if (!sdev->host->hostt->compat_ioctl) - return -ENOIOCTLCMD; - return sdev->host->hostt->compat_ioctl(sdev, cmd, p); + return scsi_compat_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p); } #endif diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 985546aac236..08efcee7a34d 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -910,19 +910,14 @@ static int put_compat_request_table(struct compat_sg_req_info __user *o, #endif static long -sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) +sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp, + unsigned int cmd_in, void __user *p) { - void __user *p = (void __user *)arg; int __user *ip = p; int result, val, read_only; - Sg_device *sdp; - Sg_fd *sfp; Sg_request *srp; unsigned long iflags; - if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) - return -ENXIO; - SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_ioctl: cmd=0x%x\n", (int) cmd_in)); read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); @@ -1145,29 +1140,44 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) cmd_in, filp->f_flags & O_NDELAY); if (result) return result; + + return -ENOIOCTLCMD; +} + +static long +sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) +{ + void __user *p = (void __user *)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_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; - struct scsi_device *sdev; + int ret; if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - sdev = sdp->device; - if (sdev->host->hostt->compat_ioctl) { - int ret; - - ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); - + ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p); + if (ret != -ENOIOCTLCMD) return ret; - } - - return -ENOIOCTLCMD; + + return scsi_compat_ioctl(sdp->device, cmd_in, p); } #endif diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 4664fdf75c0f..6033a886c42c 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -38,6 +38,7 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/bio.h> +#include <linux/compat.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/cdrom.h> @@ -598,6 +599,55 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, 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(&sr_mutex); + + 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: + ret = scsi_compat_ioctl(sdev, cmd, argp); + goto put; + } + + /* + * CDROM ioctls are handled in the block layer, but + * do the scsi blk ioctls here. + */ + ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); + if (ret != -ENOTTY) + return ret; + + ret = scsi_compat_ioctl(sdev, cmd, argp); + +put: + scsi_autopm_put_device(sdev); + +out: + mutex_unlock(&sr_mutex); + return ret; + +} +#endif + static unsigned int sr_block_check_events(struct gendisk *disk, unsigned int clearing) { @@ -641,12 +691,11 @@ static const struct block_device_operations sr_bdops .open = sr_block_open, .release = sr_block_release, .ioctl = sr_block_ioctl, +#ifdef CONFIG_COMPAT + .ioctl = sr_block_compat_ioctl, +#endif .check_events = sr_block_check_events, .revalidate_disk = sr_block_revalidate_disk, - /* - * No compat_ioctl for now because sr_block_ioctl never - * seems to pass arbitrary ioctls down to host drivers. - */ }; static int sr_open(struct cdrom_device_info *cdi, int purpose) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 9e3fff2de83e..393f3019ccac 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3501,7 +3501,7 @@ static int partition_tape(struct scsi_tape *STp, int size) /* The ioctl command */ -static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) +static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user *p) { int i, cmd_nr, cmd_type, bt; int retval = 0; @@ -3509,7 +3509,6 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) struct scsi_tape *STp = file->private_data; struct st_modedef *STm; struct st_partstat *STps; - void __user *p = (void __user *)arg; if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -3824,9 +3823,19 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) } 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; + } + return retval; + case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: break; + default: if ((cmd_in == SG_IO || cmd_in == SCSI_IOCTL_SEND_COMMAND || @@ -3840,42 +3849,46 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) 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 retval; + return -ENOTTY; 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; - struct scsi_device *sdev = STp->device; - int ret = -ENOIOCTLCMD; + int ret; /* argument conversion is handled using put_user_mtpos/put_user_mtget */ switch (cmd_in) { - case MTIOCTOP: - return st_ioctl(file, MTIOCTOP, (unsigned long)p); case MTIOCPOS32: - return st_ioctl(file, MTIOCPOS, (unsigned long)p); + return st_ioctl_common(file, MTIOCPOS, p); case MTIOCGET32: - return st_ioctl(file, MTIOCGET, (unsigned long)p); + return st_ioctl_common(file, MTIOCGET, p); } - if (sdev->host->hostt->compat_ioctl) { + ret = st_ioctl_common(file, cmd_in, p); + if (ret != -ENOTTY) + return ret; - ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); - - } - return ret; + return scsi_compat_ioctl(STp->device, cmd_in, p); } #endif diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 358ea2ecf36b..ab4471f469e6 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -36,109 +36,11 @@ #include "internal.h" -#ifdef CONFIG_BLOCK -#include <linux/cdrom.h> -#include <linux/fd.h> -#include <scsi/scsi.h> -#include <scsi/scsi_ioctl.h> -#include <scsi/sg.h> -#endif - #include <linux/uaccess.h> #include <linux/watchdog.h> #include <linux/hiddev.h> - -#include <linux/sort.h> - -/* - * simple reversible transform to make our table more evenly - * distributed after sorting. - */ -#define XFORM(i) (((i) ^ ((i) << 27) ^ ((i) << 17)) & 0xffffffff) - -#define COMPATIBLE_IOCTL(cmd) XFORM((u32)cmd), -static unsigned int ioctl_pointer[] = { -#ifdef CONFIG_BLOCK -/* Big S */ -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) -COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) -COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) -#endif -#ifdef CONFIG_BLOCK -/* SG stuff */ -COMPATIBLE_IOCTL(SG_IO) -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) -COMPATIBLE_IOCTL(SG_SET_TIMEOUT) -COMPATIBLE_IOCTL(SG_GET_TIMEOUT) -COMPATIBLE_IOCTL(SG_EMULATED_HOST) -COMPATIBLE_IOCTL(SG_GET_TRANSFORM) -COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_SCSI_ID) -COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) -COMPATIBLE_IOCTL(SG_GET_LOW_DMA) -COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) -COMPATIBLE_IOCTL(SG_SET_DEBUG) -COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) -COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) -COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) -COMPATIBLE_IOCTL(SG_SCSI_RESET) -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) -COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) -COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) -#endif -}; - -/* - * Convert common ioctl arguments based on their command number - * - * Please do not add any code in here. Instead, implement - * a compat_ioctl operation in the place that handle? the - * ioctl for the native case. - */ -static long do_ioctl_trans(unsigned int cmd, - unsigned long arg, struct file *file) -{ - return -ENOIOCTLCMD; -} - -static int compat_ioctl_check_table(unsigned int xcmd) -{ -#ifdef CONFIG_BLOCK - int i; - const int max = ARRAY_SIZE(ioctl_pointer) - 1; - - BUILD_BUG_ON(max >= (1 << 16)); - - /* guess initial offset into table, assuming a - normalized distribution */ - i = ((xcmd >> 16) * max) >> 16; - - /* do linear search up first, until greater or equal */ - while (ioctl_pointer[i] < xcmd && i < max) - i++; - - /* then do linear search down */ - while (ioctl_pointer[i] > xcmd && i > 0) - i--; - - return ioctl_pointer[i] == xcmd; -#else - return 0; -#endif -} - COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, compat_ulong_t, arg32) { @@ -216,19 +118,9 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, goto out_fput; } - if (!f.file->f_op->unlocked_ioctl) - goto do_ioctl; - break; - } - - if (compat_ioctl_check_table(XFORM(cmd))) - goto found_handler; - - error = do_ioctl_trans(cmd, arg, f.file); - if (error == -ENOIOCTLCMD) error = -ENOTTY; - - goto out_fput; + goto out_fput; + } found_handler: arg = (unsigned long)compat_ptr(arg); @@ -239,23 +131,3 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, out: return error; } - -static int __init init_sys32_ioctl_cmp(const void *p, const void *q) -{ - unsigned int a, b; - a = *(unsigned int *)p; - b = *(unsigned int *)q; - if (a > b) - return 1; - if (a < b) - return -1; - return 0; -} - -static int __init init_sys32_ioctl(void) -{ - sort(ioctl_pointer, ARRAY_SIZE(ioctl_pointer), sizeof(*ioctl_pointer), - init_sys32_ioctl_cmp, NULL); - return 0; -} -__initcall(init_sys32_ioctl); -- 2.20.0
Michael S. Tsirkin
2019-Dec-11 23:05 UTC
[PATCH 15/24] compat_ioctl: scsi: move ioctl handling into drivers
On Wed, Dec 11, 2019 at 09:42:49PM +0100, Arnd Bergmann wrote:> Each driver calling scsi_ioctl() gets an equivalent compat_ioctl() > handler that implements the same commands by calling scsi_compat_ioctl(). > > The scsi_cmd_ioctl() and scsi_cmd_blk_ioctl() functions are compatible > at this point, so any driver that calls those can do so for both native > and compat mode, with the argument passed through compat_ptr(). > > With this, we can remove the entries from fs/compat_ioctl.c. The new > code is larger, but should be easier to maintain and keep updated with > newly added commands. > > Signed-off-by: Arnd Bergmann <arnd at arndb.de> > --- > drivers/block/virtio_blk.c | 3 + > drivers/scsi/ch.c | 9 ++- > drivers/scsi/sd.c | 50 ++++++-------- > drivers/scsi/sg.c | 44 ++++++++----- > drivers/scsi/sr.c | 57 ++++++++++++++-- > drivers/scsi/st.c | 51 ++++++++------ > fs/compat_ioctl.c | 132 +------------------------------------ > 7 files changed, 142 insertions(+), 204 deletions(-) > > diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c > index 7ffd719d89de..fbbf18ac1d5d 100644 > --- a/drivers/block/virtio_blk.c > +++ b/drivers/block/virtio_blk.c > @@ -405,6 +405,9 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) > > static const struct block_device_operations virtblk_fops = { > .ioctl = virtblk_ioctl, > +#ifdef CONFIG_COMPAT > + .compat_ioctl = blkdev_compat_ptr_ioctl, > +#endif > .owner = THIS_MODULE, > .getgeo = virtblk_getgeo, > };Hmm - is virtio blk lumped in with scsi things intentionally? -- MST
Michael S. Tsirkin
2019-Dec-12 10:25 UTC
[PATCH 15/24] compat_ioctl: scsi: move ioctl handling into drivers
On Wed, Dec 11, 2019 at 09:42:49PM +0100, Arnd Bergmann wrote:> Each driver calling scsi_ioctl() gets an equivalent compat_ioctl() > handler that implements the same commands by calling scsi_compat_ioctl(). > > The scsi_cmd_ioctl() and scsi_cmd_blk_ioctl() functions are compatible > at this point, so any driver that calls those can do so for both native > and compat mode, with the argument passed through compat_ptr(). > > With this, we can remove the entries from fs/compat_ioctl.c. The new > code is larger, but should be easier to maintain and keep updated with > newly added commands. > > Signed-off-by: Arnd Bergmann <arnd at arndb.de> > --- > drivers/block/virtio_blk.c | 3 + > drivers/scsi/ch.c | 9 ++- > drivers/scsi/sd.c | 50 ++++++-------- > drivers/scsi/sg.c | 44 ++++++++----- > drivers/scsi/sr.c | 57 ++++++++++++++-- > drivers/scsi/st.c | 51 ++++++++------ > fs/compat_ioctl.c | 132 +------------------------------------ > 7 files changed, 142 insertions(+), 204 deletions(-) > > diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c > index 7ffd719d89de..fbbf18ac1d5d 100644 > --- a/drivers/block/virtio_blk.c > +++ b/drivers/block/virtio_blk.c > @@ -405,6 +405,9 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) > > static const struct block_device_operations virtblk_fops = { > .ioctl = virtblk_ioctl, > +#ifdef CONFIG_COMPAT > + .compat_ioctl = blkdev_compat_ptr_ioctl, > +#endif > .owner = THIS_MODULE, > .getgeo = virtblk_getgeo, > };virtio part: Acked-by: Michael S. Tsirkin <mst at redhat.com>> diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c > index 76751d6c7f0d..ed5f4a6ae270 100644 > --- a/drivers/scsi/ch.c > +++ b/drivers/scsi/ch.c > @@ -872,6 +872,10 @@ 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: > @@ -883,7 +887,7 @@ static long ch_ioctl_compat(struct file * file, > case CHIOINITELEM: > case CHIOSVOLTAG: > /* compatible */ > - return ch_ioctl(file, cmd, arg); > + return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); > case CHIOGSTATUS32: > { > struct changer_element_status32 ces32; > @@ -898,8 +902,7 @@ static long ch_ioctl_compat(struct file * file, > return ch_gstatus(ch, ces32.ces_type, data); > } > default: > - // return scsi_ioctl_compat(ch->device, cmd, (void*)arg); > - return -ENOIOCTLCMD; > + return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg)); > > } > } > diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c > index cea625906440..5afb0046b12a 100644 > --- a/drivers/scsi/sd.c > +++ b/drivers/scsi/sd.c > @@ -1465,13 +1465,12 @@ 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(struct block_device *bdev, fmode_t mode, > - unsigned int cmd, unsigned long arg) > +static int sd_ioctl_common(struct block_device *bdev, fmode_t mode, > + unsigned int cmd, void __user *p) > { > 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, " > @@ -1507,9 +1506,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, > break; > default: > error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); > - if (error != -ENOTTY) > - break; > - error = scsi_ioctl(sdp, cmd, p); > break; > } > out: > @@ -1691,39 +1687,31 @@ static void sd_rescan(struct device *dev) > 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 > -/* > - * This gets directly called from VFS. When the ioctl > - * is not recognized we go back to the other translation paths. > - */ > static int sd_compat_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 *sdev = sdkp->device; > void __user *p = compat_ptr(arg); > - int error; > - > - error = scsi_verify_blk_ioctl(bdev, cmd); > - if (error < 0) > - return error; > + int ret; > > - error = scsi_ioctl_block_when_processing_errors(sdev, cmd, > - (mode & FMODE_NDELAY) != 0); > - if (error) > - return error; > + ret = sd_ioctl_common(bdev, mode, cmd, p); > + if (ret != -ENOTTY) > + return ret; > > - if (is_sed_ioctl(cmd)) > - return sed_ioctl(sdkp->opal_dev, cmd, p); > - > - /* > - * Let the static ioctl translation table take care of it. > - */ > - if (!sdev->host->hostt->compat_ioctl) > - return -ENOIOCTLCMD; > - return sdev->host->hostt->compat_ioctl(sdev, cmd, p); > + return scsi_compat_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p); > } > #endif > > diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c > index 985546aac236..08efcee7a34d 100644 > --- a/drivers/scsi/sg.c > +++ b/drivers/scsi/sg.c > @@ -910,19 +910,14 @@ static int put_compat_request_table(struct compat_sg_req_info __user *o, > #endif > > static long > -sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) > +sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp, > + unsigned int cmd_in, void __user *p) > { > - void __user *p = (void __user *)arg; > int __user *ip = p; > int result, val, read_only; > - Sg_device *sdp; > - Sg_fd *sfp; > Sg_request *srp; > unsigned long iflags; > > - if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) > - return -ENXIO; > - > SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, > "sg_ioctl: cmd=0x%x\n", (int) cmd_in)); > read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); > @@ -1145,29 +1140,44 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) > cmd_in, filp->f_flags & O_NDELAY); > if (result) > return result; > + > + return -ENOIOCTLCMD; > +} > + > +static long > +sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) > +{ > + void __user *p = (void __user *)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_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; > - struct scsi_device *sdev; > + int ret; > > if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) > return -ENXIO; > > - sdev = sdp->device; > - if (sdev->host->hostt->compat_ioctl) { > - int ret; > - > - ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); > - > + ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p); > + if (ret != -ENOIOCTLCMD) > return ret; > - } > - > - return -ENOIOCTLCMD; > + > + return scsi_compat_ioctl(sdp->device, cmd_in, p); > } > #endif > > diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c > index 4664fdf75c0f..6033a886c42c 100644 > --- a/drivers/scsi/sr.c > +++ b/drivers/scsi/sr.c > @@ -38,6 +38,7 @@ > #include <linux/kernel.h> > #include <linux/mm.h> > #include <linux/bio.h> > +#include <linux/compat.h> > #include <linux/string.h> > #include <linux/errno.h> > #include <linux/cdrom.h> > @@ -598,6 +599,55 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, > 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(&sr_mutex); > + > + 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: > + ret = scsi_compat_ioctl(sdev, cmd, argp); > + goto put; > + } > + > + /* > + * CDROM ioctls are handled in the block layer, but > + * do the scsi blk ioctls here. > + */ > + ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); > + if (ret != -ENOTTY) > + return ret; > + > + ret = scsi_compat_ioctl(sdev, cmd, argp); > + > +put: > + scsi_autopm_put_device(sdev); > + > +out: > + mutex_unlock(&sr_mutex); > + return ret; > + > +} > +#endif > + > static unsigned int sr_block_check_events(struct gendisk *disk, > unsigned int clearing) > { > @@ -641,12 +691,11 @@ static const struct block_device_operations sr_bdops > .open = sr_block_open, > .release = sr_block_release, > .ioctl = sr_block_ioctl, > +#ifdef CONFIG_COMPAT > + .ioctl = sr_block_compat_ioctl, > +#endif > .check_events = sr_block_check_events, > .revalidate_disk = sr_block_revalidate_disk, > - /* > - * No compat_ioctl for now because sr_block_ioctl never > - * seems to pass arbitrary ioctls down to host drivers. > - */ > }; > > static int sr_open(struct cdrom_device_info *cdi, int purpose) > diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c > index 9e3fff2de83e..393f3019ccac 100644 > --- a/drivers/scsi/st.c > +++ b/drivers/scsi/st.c > @@ -3501,7 +3501,7 @@ static int partition_tape(struct scsi_tape *STp, int size) > > > /* The ioctl command */ > -static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) > +static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user *p) > { > int i, cmd_nr, cmd_type, bt; > int retval = 0; > @@ -3509,7 +3509,6 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) > struct scsi_tape *STp = file->private_data; > struct st_modedef *STm; > struct st_partstat *STps; > - void __user *p = (void __user *)arg; > > if (mutex_lock_interruptible(&STp->lock)) > return -ERESTARTSYS; > @@ -3824,9 +3823,19 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) > } > 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; > + } > + return retval; > + > case SCSI_IOCTL_GET_IDLUN: > case SCSI_IOCTL_GET_BUS_NUMBER: > break; > + > default: > if ((cmd_in == SG_IO || > cmd_in == SCSI_IOCTL_SEND_COMMAND || > @@ -3840,42 +3849,46 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) > 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 retval; > + return -ENOTTY; > > 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; > - struct scsi_device *sdev = STp->device; > - int ret = -ENOIOCTLCMD; > + int ret; > > /* argument conversion is handled using put_user_mtpos/put_user_mtget */ > switch (cmd_in) { > - case MTIOCTOP: > - return st_ioctl(file, MTIOCTOP, (unsigned long)p); > case MTIOCPOS32: > - return st_ioctl(file, MTIOCPOS, (unsigned long)p); > + return st_ioctl_common(file, MTIOCPOS, p); > case MTIOCGET32: > - return st_ioctl(file, MTIOCGET, (unsigned long)p); > + return st_ioctl_common(file, MTIOCGET, p); > } > > - if (sdev->host->hostt->compat_ioctl) { > + ret = st_ioctl_common(file, cmd_in, p); > + if (ret != -ENOTTY) > + return ret; > > - ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); > - > - } > - return ret; > + return scsi_compat_ioctl(STp->device, cmd_in, p); > } > #endif > > diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c > index 358ea2ecf36b..ab4471f469e6 100644 > --- a/fs/compat_ioctl.c > +++ b/fs/compat_ioctl.c > @@ -36,109 +36,11 @@ > > #include "internal.h" > > -#ifdef CONFIG_BLOCK > -#include <linux/cdrom.h> > -#include <linux/fd.h> > -#include <scsi/scsi.h> > -#include <scsi/scsi_ioctl.h> > -#include <scsi/sg.h> > -#endif > - > #include <linux/uaccess.h> > #include <linux/watchdog.h> > > #include <linux/hiddev.h> > > - > -#include <linux/sort.h> > - > -/* > - * simple reversible transform to make our table more evenly > - * distributed after sorting. > - */ > -#define XFORM(i) (((i) ^ ((i) << 27) ^ ((i) << 17)) & 0xffffffff) > - > -#define COMPATIBLE_IOCTL(cmd) XFORM((u32)cmd), > -static unsigned int ioctl_pointer[] = { > -#ifdef CONFIG_BLOCK > -/* Big S */ > -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) > -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) > -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) > -COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) > -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) > -COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) > -COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) > -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) > -#endif > -#ifdef CONFIG_BLOCK > -/* SG stuff */ > -COMPATIBLE_IOCTL(SG_IO) > -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) > -COMPATIBLE_IOCTL(SG_SET_TIMEOUT) > -COMPATIBLE_IOCTL(SG_GET_TIMEOUT) > -COMPATIBLE_IOCTL(SG_EMULATED_HOST) > -COMPATIBLE_IOCTL(SG_GET_TRANSFORM) > -COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) > -COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) > -COMPATIBLE_IOCTL(SG_GET_SCSI_ID) > -COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) > -COMPATIBLE_IOCTL(SG_GET_LOW_DMA) > -COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) > -COMPATIBLE_IOCTL(SG_GET_PACK_ID) > -COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) > -COMPATIBLE_IOCTL(SG_SET_DEBUG) > -COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) > -COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) > -COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) > -COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) > -COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) > -COMPATIBLE_IOCTL(SG_SCSI_RESET) > -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) > -COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) > -COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) > -#endif > -}; > - > -/* > - * Convert common ioctl arguments based on their command number > - * > - * Please do not add any code in here. Instead, implement > - * a compat_ioctl operation in the place that handle? the > - * ioctl for the native case. > - */ > -static long do_ioctl_trans(unsigned int cmd, > - unsigned long arg, struct file *file) > -{ > - return -ENOIOCTLCMD; > -} > - > -static int compat_ioctl_check_table(unsigned int xcmd) > -{ > -#ifdef CONFIG_BLOCK > - int i; > - const int max = ARRAY_SIZE(ioctl_pointer) - 1; > - > - BUILD_BUG_ON(max >= (1 << 16)); > - > - /* guess initial offset into table, assuming a > - normalized distribution */ > - i = ((xcmd >> 16) * max) >> 16; > - > - /* do linear search up first, until greater or equal */ > - while (ioctl_pointer[i] < xcmd && i < max) > - i++; > - > - /* then do linear search down */ > - while (ioctl_pointer[i] > xcmd && i > 0) > - i--; > - > - return ioctl_pointer[i] == xcmd; > -#else > - return 0; > -#endif > -} > - > COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, > compat_ulong_t, arg32) > { > @@ -216,19 +118,9 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, > goto out_fput; > } > > - if (!f.file->f_op->unlocked_ioctl) > - goto do_ioctl; > - break; > - } > - > - if (compat_ioctl_check_table(XFORM(cmd))) > - goto found_handler; > - > - error = do_ioctl_trans(cmd, arg, f.file); > - if (error == -ENOIOCTLCMD) > error = -ENOTTY; > - > - goto out_fput; > + goto out_fput; > + } > > found_handler: > arg = (unsigned long)compat_ptr(arg); > @@ -239,23 +131,3 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, > out: > return error; > } > - > -static int __init init_sys32_ioctl_cmp(const void *p, const void *q) > -{ > - unsigned int a, b; > - a = *(unsigned int *)p; > - b = *(unsigned int *)q; > - if (a > b) > - return 1; > - if (a < b) > - return -1; > - return 0; > -} > - > -static int __init init_sys32_ioctl(void) > -{ > - sort(ioctl_pointer, ARRAY_SIZE(ioctl_pointer), sizeof(*ioctl_pointer), > - init_sys32_ioctl_cmp, NULL); > - return 0; > -} > -__initcall(init_sys32_ioctl); > -- > 2.20.0
Reasonably Related Threads
- [PATCH v3 13/22] compat_ioctl: scsi: move ioctl handling into drivers
- [PATCH 00/24] block, scsi: final compat_ioctl cleanup
- [PATCH 15/24] compat_ioctl: scsi: move ioctl handling into drivers
- [PATCH 15/24] compat_ioctl: scsi: move ioctl handling into drivers
- [rfc][patch][linux] ioctl32() compat plumbing for xen calls