scsi: split scsi_nonblockable_ioctl
The calling conventions for this function are bad as it could return -ENODEV both for a device not currently online and a not recognized ioctl. Add a new scsi_ioctl_block_when_processing_errors function that wraps scsi_block_when_processing_errors with the a special case for the SG_SCSI_RESET ioctl command, and handle the SG_SCSI_RESET case itself in scsi_ioctl. All callers of scsi_ioctl now must call the above helper to check for the EH state, so that the ioctl handler itself doesn't have to. Reported-by: Robert Elliott <Elliott@hp.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Hannes Reinecke <hare@suse.de>
This commit is contained in:
@@ -1071,16 +1071,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
|
||||
if (atomic_read(&sdp->detaching))
|
||||
return -ENODEV;
|
||||
return put_user(sdp->device->host->hostt->emulated, ip);
|
||||
case SG_SCSI_RESET:
|
||||
if (atomic_read(&sdp->detaching))
|
||||
return -ENODEV;
|
||||
if (filp->f_flags & O_NONBLOCK) {
|
||||
if (scsi_host_in_recovery(sdp->device->host))
|
||||
return -EBUSY;
|
||||
} else if (!scsi_block_when_processing_errors(sdp->device))
|
||||
return -EBUSY;
|
||||
|
||||
return scsi_ioctl_reset(sdp->device, ip);
|
||||
case SCSI_IOCTL_SEND_COMMAND:
|
||||
if (atomic_read(&sdp->detaching))
|
||||
return -ENODEV;
|
||||
@@ -1100,13 +1090,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
|
||||
return result;
|
||||
sdp->sgdebug = (char) val;
|
||||
return 0;
|
||||
case SCSI_IOCTL_GET_IDLUN:
|
||||
case SCSI_IOCTL_GET_BUS_NUMBER:
|
||||
case SCSI_IOCTL_PROBE_HOST:
|
||||
case SG_GET_TRANSFORM:
|
||||
if (atomic_read(&sdp->detaching))
|
||||
return -ENODEV;
|
||||
return scsi_ioctl(sdp->device, cmd_in, p);
|
||||
case BLKSECTGET:
|
||||
return put_user(max_sectors_bytes(sdp->device->request_queue),
|
||||
ip);
|
||||
@@ -1122,11 +1105,25 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
|
||||
return blk_trace_startstop(sdp->device->request_queue, 0);
|
||||
case BLKTRACETEARDOWN:
|
||||
return blk_trace_remove(sdp->device->request_queue);
|
||||
case SCSI_IOCTL_GET_IDLUN:
|
||||
case SCSI_IOCTL_GET_BUS_NUMBER:
|
||||
case SCSI_IOCTL_PROBE_HOST:
|
||||
case SG_GET_TRANSFORM:
|
||||
case SG_SCSI_RESET:
|
||||
if (atomic_read(&sdp->detaching))
|
||||
return -ENODEV;
|
||||
break;
|
||||
default:
|
||||
if (read_only)
|
||||
return -EPERM; /* don't know so take safe approach */
|
||||
return scsi_ioctl(sdp->device, cmd_in, p);
|
||||
break;
|
||||
}
|
||||
|
||||
result = scsi_ioctl_block_when_processing_errors(sdp->device,
|
||||
cmd_in, filp->f_flags & O_NDELAY);
|
||||
if (result)
|
||||
return result;
|
||||
return scsi_ioctl(sdp->device, cmd_in, p);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
Reference in New Issue
Block a user