From 26cf591e6dfc0d07495b7bcf20a557b316811f00 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Sat, 18 Oct 2014 22:11:21 +0200 Subject: scsi: add SG_SCSI_RESET_NO_ESCALATE flag to SG_SCSI_RESET ioctl Further to a January 2013 thread titled: "[PATCH] SG_SCSI_RESET ioctl should only perform requested operation" by Jeremy Linton a patch (v3) is presented that expands the existing ioctl to include "no_escalate" versions to the existing resets. This requires no changes to SCSI low level drivers (LLDs); it adds several more finely tuned reset options to the user space. For example: /* This call remains the same, with the same escalating semantics * if the device (LU) reset fail. That is: on failure to try a * target reset and if that fails, try a bus reset, and if that fails * try a host (i.e. LLD) reset. */ val = SG_SCSI_RESET_DEVICE; res = ioctl(, SG_SCSI_RESET, &val); /* What follows is a new option introduced by this patch series. Only * a device reset is attempted. If that fails then an appropriate * error code is provided. N.B. There is no reset escalation. */ val = SG_SCSI_RESET_DEVICE | SG_SCSI_RESET_NO_ESCALATE; res = ioctl(, SG_SCSI_RESET, &val); Signed-off-by: Douglas Gilbert Reviewed-by: Jeremy Linton Reviewed-by: Hannes Reinecke Signed-off-by: Christoph Hellwig --- drivers/scsi/sg.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/sg.c') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 60354449d9ed..fe44c14f551e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -847,7 +847,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) { void __user *p = (void __user *)arg; int __user *ip = p; - int result, val, read_only; + int result, val, val2, read_only; Sg_device *sdp; Sg_fd *sfp; Sg_request *srp; @@ -1082,27 +1082,32 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) result = get_user(val, ip); if (result) return result; + if (val & SG_SCSI_RESET_NO_ESCALATE) { + val &= ~SG_SCSI_RESET_NO_ESCALATE; + val2 = SCSI_TRY_RESET_NO_ESCALATE; + } else + val2 = 0; if (SG_SCSI_RESET_NOTHING == val) return 0; switch (val) { case SG_SCSI_RESET_DEVICE: - val = SCSI_TRY_RESET_DEVICE; + val2 |= SCSI_TRY_RESET_DEVICE; break; case SG_SCSI_RESET_TARGET: - val = SCSI_TRY_RESET_TARGET; + val2 |= SCSI_TRY_RESET_TARGET; break; case SG_SCSI_RESET_BUS: - val = SCSI_TRY_RESET_BUS; + val2 |= SCSI_TRY_RESET_BUS; break; case SG_SCSI_RESET_HOST: - val = SCSI_TRY_RESET_HOST; + val2 |= SCSI_TRY_RESET_HOST; break; default: return -EINVAL; } if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - return (scsi_reset_provider(sdp->device, val) == + return (scsi_reset_provider(sdp->device, val2) == SUCCESS) ? 0 : -EIO; case SCSI_IOCTL_SEND_COMMAND: if (atomic_read(&sdp->detaching)) -- cgit v1.2.1 From 22e0d994151c3eac183625f8c1400c0c83ac414f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 24 Oct 2014 14:26:44 +0200 Subject: scsi: introduce sdev_prefix_printk() Like scmd_printk(), but the device name is passed in as a string. Can be used by eg ULDs which do not have access to the scsi_cmnd structure. Signed-off-by: Hannes Reinecke Reviewed-by: Robert Elliott Signed-off-by: Christoph Hellwig --- drivers/scsi/sg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/sg.c') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index fe44c14f551e..55cbc6689d27 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -219,8 +219,8 @@ static void sg_device_destroy(struct kref *kref); #define SZ_SG_REQ_INFO sizeof(sg_req_info_t) #define sg_printk(prefix, sdp, fmt, a...) \ - sdev_printk(prefix, (sdp)->device, "[%s] " fmt, \ - (sdp)->disk->disk_name, ##a) + sdev_prefix_printk(prefix, (sdp)->device, \ + (sdp)->disk->disk_name, fmt, ##a) static int sg_allow_access(struct file *filp, unsigned char *cmd) { -- cgit v1.2.1 From d811b848ebb78a1135658aa20a80e31994df47f7 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 24 Oct 2014 14:26:45 +0200 Subject: scsi: use sdev as argument for sense code printing We should be using the standard dev_printk() variants for sense code printing. [hch: remove __scsi_print_sense call in xen-scsiback, Acked by Juergen] [hch: folded bracing fix from Dan Carpenter] Signed-off-by: Hannes Reinecke Reviewed-by: Robert Elliott Signed-off-by: Christoph Hellwig --- drivers/scsi/sg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/sg.c') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 55cbc6689d27..2fe2701d86db 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1365,7 +1365,7 @@ sg_rq_end_io(struct request *rq, int uptodate) if ((sdp->sgdebug > 0) && ((CHECK_CONDITION == srp->header.masked_status) || (COMMAND_TERMINATED == srp->header.masked_status))) - __scsi_print_sense(__func__, sense, + __scsi_print_sense(sdp->device, __func__, sense, SCSI_SENSE_BUFFERSIZE); /* Following if statement is a patch supplied by Eric Youngdale */ -- cgit v1.2.1 From 176aa9d6ee2db582e7e856dbe1983004a82869b4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 11 Oct 2014 12:06:47 +0200 Subject: scsi: refactor scsi_reset_provider handling Pull the common code from the two callers into the function, and rename it to scsi_ioctl_reset. Signed-off-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Reviewed-by: Hannes Reinecke --- drivers/scsi/sg.c | 34 +++------------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) (limited to 'drivers/scsi/sg.c') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2fe2701d86db..7c55cacceb7c 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -847,7 +847,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) { void __user *p = (void __user *)arg; int __user *ip = p; - int result, val, val2, read_only; + int result, val, read_only; Sg_device *sdp; Sg_fd *sfp; Sg_request *srp; @@ -1079,36 +1079,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) return -EBUSY; } else if (!scsi_block_when_processing_errors(sdp->device)) return -EBUSY; - result = get_user(val, ip); - if (result) - return result; - if (val & SG_SCSI_RESET_NO_ESCALATE) { - val &= ~SG_SCSI_RESET_NO_ESCALATE; - val2 = SCSI_TRY_RESET_NO_ESCALATE; - } else - val2 = 0; - if (SG_SCSI_RESET_NOTHING == val) - return 0; - switch (val) { - case SG_SCSI_RESET_DEVICE: - val2 |= SCSI_TRY_RESET_DEVICE; - break; - case SG_SCSI_RESET_TARGET: - val2 |= SCSI_TRY_RESET_TARGET; - break; - case SG_SCSI_RESET_BUS: - val2 |= SCSI_TRY_RESET_BUS; - break; - case SG_SCSI_RESET_HOST: - val2 |= SCSI_TRY_RESET_HOST; - break; - default: - return -EINVAL; - } - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - return (scsi_reset_provider(sdp->device, val2) == - SUCCESS) ? 0 : -EIO; + + return scsi_ioctl_reset(sdp->device, ip); case SCSI_IOCTL_SEND_COMMAND: if (atomic_read(&sdp->detaching)) return -ENODEV; -- cgit v1.2.1 From 906d15fbd23c1267addab361063c1c8119992215 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 11 Oct 2014 16:25:31 +0200 Subject: 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 Signed-off-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Reviewed-by: Hannes Reinecke --- drivers/scsi/sg.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers/scsi/sg.c') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 7c55cacceb7c..b14f64cb9724 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -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 -- cgit v1.2.1