forked from mirrors/linux
		
	scsi: scsi_ioctl: Call scsi_cmd_ioctl() from scsi_ioctl()
Ensure SCSI ULD only has 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. Link: https://lore.kernel.org/r/20210724072033.1284840-12-hch@lst.de Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									4f07bfc561
								
							
						
					
					
						commit
						2e27f576ab
					
				
					 7 changed files with 21 additions and 48 deletions
				
			
		|  | @ -877,7 +877,7 @@ static long ch_ioctl(struct file *file, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	default: | 	default: | ||||||
| 		return scsi_ioctl(ch->device, cmd, argp); | 		return scsi_ioctl(ch->device, NULL, file->f_mode, cmd, argp); | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -192,6 +192,8 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg) | ||||||
| /**
 | /**
 | ||||||
|  * scsi_ioctl - Dispatch ioctl to scsi device |  * scsi_ioctl - Dispatch ioctl to scsi device | ||||||
|  * @sdev: scsi device receiving ioctl |  * @sdev: scsi device receiving ioctl | ||||||
|  |  * @disk: disk receiving the ioctl | ||||||
|  |  * @mode: mode the block/char device is opened with | ||||||
|  * @cmd: which ioctl is it |  * @cmd: which ioctl is it | ||||||
|  * @arg: data associated with ioctl |  * @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 |  * does not take a major/minor number as the dev field.  Rather, it takes | ||||||
|  * a pointer to a &struct scsi_device. |  * 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]; | 	char scsi_cmd[MAX_COMMAND_SIZE]; | ||||||
| 	struct scsi_sense_hdr sense_hdr; | 	struct scsi_sense_hdr sense_hdr; | ||||||
|  | 	int error; | ||||||
| 
 | 
 | ||||||
| 	/* Check for deprecated ioctls ... all the ioctls which don't
 | 	/* Check for deprecated ioctls ... all the ioctls which don't
 | ||||||
| 	 * follow the new unique numbering scheme are deprecated */ | 	 * 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; | 		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) { | 	switch (cmd) { | ||||||
| 	case SCSI_IOCTL_GET_IDLUN: { | 	case SCSI_IOCTL_GET_IDLUN: { | ||||||
| 		struct scsi_idlun v = { | 		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); | 		return put_user(sdev->host->host_no, (int __user *)arg); | ||||||
| 	case SCSI_IOCTL_PROBE_HOST: | 	case SCSI_IOCTL_PROBE_HOST: | ||||||
| 		return ioctl_probe(sdev->host, arg); | 		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: | 	case SCSI_IOCTL_DOORLOCK: | ||||||
| 		return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); | 		return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); | ||||||
| 	case SCSI_IOCTL_DOORUNLOCK: | 	case SCSI_IOCTL_DOORUNLOCK: | ||||||
|  |  | ||||||
|  | @ -1571,23 +1571,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, | ||||||
| 
 | 
 | ||||||
| 	if (is_sed_ioctl(cmd)) | 	if (is_sed_ioctl(cmd)) | ||||||
| 		return sed_ioctl(sdkp->opal_dev, cmd, p); | 		return sed_ioctl(sdkp->opal_dev, cmd, p); | ||||||
| 
 | 	return scsi_ioctl(sdp, disk, mode, 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); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void set_media_not_present(struct scsi_disk *sdkp) | static void set_media_not_present(struct scsi_disk *sdkp) | ||||||
|  |  | ||||||
|  | @ -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); | 	ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p); | ||||||
| 	if (ret != -ENOIOCTLCMD) | 	if (ret != -ENOIOCTLCMD) | ||||||
| 		return ret; | 		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 | static __poll_t | ||||||
|  |  | ||||||
|  | @ -574,24 +574,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | ||||||
| 
 | 
 | ||||||
| 	scsi_autopm_get_device(sdev); | 	scsi_autopm_get_device(sdev); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	if (ret != CDROMCLOSETRAY && ret != CDROMEJECT) { | ||||||
| 	 * 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; |  | ||||||
| 		ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); | 		ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); | ||||||
| 		if (ret != -ENOSYS) | 		if (ret != -ENOSYS) | ||||||
| 			goto put; | 			goto put; | ||||||
| 	} | 	} | ||||||
| 
 | 	ret = scsi_ioctl(sdev, disk, mode, cmd, argp); | ||||||
| 	ret = scsi_ioctl(sdev, cmd, argp); |  | ||||||
| 
 | 
 | ||||||
| put: | put: | ||||||
| 	scsi_autopm_put_device(sdev); | 	scsi_autopm_put_device(sdev); | ||||||
|  |  | ||||||
|  | @ -3823,24 +3823,16 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) | ||||||
| 	mutex_unlock(&STp->lock); | 	mutex_unlock(&STp->lock); | ||||||
| 
 | 
 | ||||||
| 	switch (cmd_in) { | 	switch (cmd_in) { | ||||||
| 	case SCSI_IOCTL_GET_IDLUN: |  | ||||||
| 	case SCSI_IOCTL_GET_BUS_NUMBER: |  | ||||||
| 		break; |  | ||||||
| 	case SG_IO: | 	case SG_IO: | ||||||
| 	case SCSI_IOCTL_SEND_COMMAND: | 	case SCSI_IOCTL_SEND_COMMAND: | ||||||
| 	case CDROM_SEND_PACKET: | 	case CDROM_SEND_PACKET: | ||||||
| 		if (!capable(CAP_SYS_RAWIO)) | 		if (!capable(CAP_SYS_RAWIO)) | ||||||
| 			return -EPERM; | 			return -EPERM; | ||||||
| 		fallthrough; |  | ||||||
| 	default: | 	default: | ||||||
| 		retval = scsi_cmd_ioctl(STp->disk->queue, STp->disk, |  | ||||||
| 					file->f_mode, cmd_in, p); |  | ||||||
| 		if (retval != -ENOTTY) |  | ||||||
| 			return retval; |  | ||||||
| 		break; | 		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) { | 	if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { | ||||||
| 		/* unload */ | 		/* unload */ | ||||||
| 		STp->rew_at_close = 0; | 		STp->rew_at_close = 0; | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ | ||||||
| 
 | 
 | ||||||
| #ifdef __KERNEL__ | #ifdef __KERNEL__ | ||||||
| 
 | 
 | ||||||
|  | struct gendisk; | ||||||
| struct scsi_device; | struct scsi_device; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -43,7 +44,8 @@ typedef struct scsi_fctargaddress { | ||||||
| 
 | 
 | ||||||
| int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, | int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, | ||||||
| 		int cmd, bool ndelay); | 		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 /* __KERNEL__ */ | ||||||
| #endif /* _SCSI_IOCTL_H */ | #endif /* _SCSI_IOCTL_H */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Christoph Hellwig
						Christoph Hellwig