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. Reviewed-by: Ben Hutchings <ben.hutchings@codethink.co.uk> Acked-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
@@ -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;
|
||||
int ret;
|
||||
|
||||
error = scsi_verify_blk_ioctl(bdev, cmd);
|
||||
if (error < 0)
|
||||
return error;
|
||||
ret = sd_ioctl_common(bdev, mode, cmd, p);
|
||||
if (ret != -ENOTTY)
|
||||
return ret;
|
||||
|
||||
error = scsi_ioctl_block_when_processing_errors(sdev, cmd,
|
||||
(mode & FMODE_NDELAY) != 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
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
|
||||
|
||||
|
Reference in New Issue
Block a user