compat_ioctl: move tape handling into drivers
MTIOCPOS and MTIOCGET are incompatible between 32-bit and 64-bit user space, and traditionally have been translated in fs/compat_ioctl.c. To get rid of that translation handler, move a corresponding implementation into each of the four drivers implementing those commands. The interesting part of that is now in a new linux/mtio.h header that wraps the existing uapi/linux/mtio.h header and provides an abstraction to let drivers handle both cases easily. Using an in_compat_syscall() check, the caller does not have to keep track of whether this was called through .unlocked_ioctl() or .compat_ioctl(). Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: "Kai Mäkisara" <Kai.Makisara@kolumbus.fi> Cc: linux-scsi@vger.kernel.org Cc: "James E.J. Bottomley" <jejb@linux.ibm.com> Cc: "Martin K. Petersen" <martin.petersen@oracle.com> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
@@ -22,6 +22,7 @@ static const char *verstr = "20160209";
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched/signal.h>
|
||||
@@ -3800,14 +3801,11 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
|
||||
if (STp->cleaning_req)
|
||||
mt_status.mt_gstat |= GMT_CLN(0xffffffff);
|
||||
|
||||
i = copy_to_user(p, &mt_status, sizeof(struct mtget));
|
||||
if (i) {
|
||||
retval = (-EFAULT);
|
||||
retval = put_user_mtget(p, &mt_status);
|
||||
if (retval)
|
||||
goto out;
|
||||
}
|
||||
|
||||
STp->recover_reg = 0; /* Clear after read */
|
||||
retval = 0;
|
||||
goto out;
|
||||
} /* End of MTIOCGET */
|
||||
if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
|
||||
@@ -3821,9 +3819,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
|
||||
goto out;
|
||||
}
|
||||
mt_pos.mt_blkno = blk;
|
||||
i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
|
||||
if (i)
|
||||
retval = (-EFAULT);
|
||||
retval = put_user_mtpos(p, &mt_pos);
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&STp->lock);
|
||||
@@ -3857,14 +3853,26 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
case MTIOCGET32:
|
||||
return st_ioctl(file, MTIOCGET, (unsigned long)p);
|
||||
}
|
||||
|
||||
if (sdev->host->hostt->compat_ioctl) {
|
||||
|
||||
ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
|
||||
ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
|
||||
|
||||
}
|
||||
return ret;
|
||||
|
Reference in New Issue
Block a user