Commit 7eafd137 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

compat_ioctl: add scsi_compat_ioctl



In order to move the compat handling for SCSI ioctl commands out of
fs/compat_ioctl.c into the individual drivers, we need a helper function
first to match the native ioctl handler called by sd, sr, st, etc.

Reviewed-by: default avatarBen Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parent 9452b1a3
Loading
Loading
Loading
Loading
+40 −14
Original line number Diff line number Diff line
@@ -189,17 +189,7 @@ 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
 * @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)
static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg)
{
	char scsi_cmd[MAX_COMMAND_SIZE];
	struct scsi_sense_hdr sense_hdr;
@@ -266,14 +256,50 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
                return scsi_ioctl_get_pci(sdev, arg);
	case SG_SCSI_RESET:
		return scsi_ioctl_reset(sdev, arg);
	default:
	}
	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)
		return sdev->host->hostt->compat_ioctl(sdev, cmd, arg);

	return ret;
}
EXPORT_SYMBOL(scsi_compat_ioctl);
#endif

/*
 * We can process a reset even when a device isn't fully operable.
 */
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ 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 */