Re: [PATCH 46/47] scsi: Move eh_device_reset_handler() to use scsi_device as argument

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



sparse review comments below...

On 06/28/2017 10:33 AM, Hannes Reinecke wrote:
When resetting a device we shouldn't depend on an existing SCSI
device, so use 'struct scsi_device' as argument for
eh_device_reset_handler().

Signed-off-by: Hannes Reinecke <hare@xxxxxxxx>
---
  Documentation/scsi/scsi_eh.txt                  |  2 +-
  Documentation/scsi/scsi_mid_low_api.txt         |  4 +--

  drivers/s390/scsi/zfcp_scsi.c                   |  4 +--

  drivers/scsi/scsi_debug.c                       | 18 ++++++-------
  drivers/scsi/scsi_error.c                       | 35 +++++++++++++++++--------

  include/scsi/scsi_host.h                        |  2 +-
  60 files changed, 287 insertions(+), 307 deletions(-)

diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index cb9f4bc22..f8a6566 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -206,7 +206,7 @@ hostt EH callbacks.  Callbacks may be omitted and omitted ones are
  considered to fail always.

  int (* eh_abort_handler)(struct scsi_cmnd *);
-int (* eh_device_reset_handler)(struct scsi_cmnd *);
+int (* eh_device_reset_handler)(struct scsi_device *);
  int (* eh_bus_reset_handler)(struct Scsi_Host *, int);
  int (* eh_host_reset_handler)(struct Scsi_Host *);

diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index e2609a63..28dc029 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -874,7 +874,7 @@ Details:

  /**
   *      eh_device_reset_handler - issue SCSI device reset
- *      @scp: identifies SCSI device to be reset
+ *      @sdev: identifies SCSI device to be reset
   *
   *      Returns SUCCESS if command aborted else FAILED
   *
@@ -887,7 +887,7 @@ Details:
   *
   *      Optionally defined in: LLD
   **/
-     int eh_device_reset_handler(struct scsi_cmnd * scp)
+     int eh_device_reset_handler(struct scsi_device * sdev)


  /**


diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 92a3902..23b5a7d 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -304,9 +304,9 @@ static int zfcp_task_mgmt_function(struct scsi_device *sdev, u8 tm_flags)
  	return retval;
  }

-static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
+static int zfcp_scsi_eh_device_reset_handler(struct scsi_device *sdev)
  {
-	return zfcp_task_mgmt_function(scpnt->device, FCP_TMF_LUN_RESET);
+	return zfcp_task_mgmt_function(sdev, FCP_TMF_LUN_RESET);
  }

  /*


diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 37e511f..9029500 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3793,19 +3793,17 @@ static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
  	return SUCCESS;
  }

-static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
+static int scsi_debug_device_reset(struct scsi_device * sdp)
  {
+	struct sdebug_dev_info *devip =
+		(struct sdebug_dev_info *)sdp->hostdata;
+
  	++num_dev_resets;
-	if (SCpnt && SCpnt->device) {
-		struct scsi_device *sdp = SCpnt->device;
-		struct sdebug_dev_info *devip =
-				(struct sdebug_dev_info *)sdp->hostdata;

-		if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
-			sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
-		if (devip)
-			set_bit(SDEBUG_UA_POR, devip->uas_bm);
-	}
+	if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
+		sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+	if (devip)
+		set_bit(SDEBUG_UA_POR, devip->uas_bm);
  	return SUCCESS;
  }

diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 368a961..4a7fe97f 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -844,7 +844,7 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
  	if (!hostt->eh_device_reset_handler)
  		return FAILED;

-	rtn = hostt->eh_device_reset_handler(scmd);
+	rtn = hostt->eh_device_reset_handler(scmd->device);
  	if (rtn == SUCCESS)
  		__scsi_report_device_reset(scmd->device, NULL);
  	return rtn;

up to here it looks good,
however ...

@@ -1106,6 +1106,7 @@ static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
   * scsi_eh_finish_cmd - Handle a cmd that eh is finished with.

__scsi_eh_finish_cmd  ?

   * @scmd:	Original SCSI cmd that eh has finished.
   * @done_q:	Queue for processed commands.
+ * @result:	Final command status to be set
   *
   * Notes:
   *    We don't want to use the normal command completion while we are are

Did this hunk slip in accidentally?
I don't see a new additional argument result being introduced with either the new __scsi_eh_finish_cmd() nor the old scsi_eh_finish_cmd(). However, the former __scsi_eh_finish_cmd() seems to have an additional argument @host_byte:. Maybe that should go where @result: is above, because the old kernel doc now belongs to the new __scsi_eh_finish_cmd().

But then you'd also need to change the function name in the kernel doc?!

@@ -1114,10 +1115,18 @@ static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
   *    keep a list of pending commands for final completion, and once we
   *    are ready to leave error handling we handle completion for real.
   */
-void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
+void __scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q,
+			int host_byte)

Should new internal helper function be declared static?

  {
+	if (host_byte)
+		set_host_byte(scmd, host_byte);
  	list_move_tail(&scmd->eh_entry, done_q);
  }
+
+void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
+{
+	__scsi_eh_finish_cmd(scmd, done_q, 0);
+}
  EXPORT_SYMBOL(scsi_eh_finish_cmd);

  /**
@@ -1284,7 +1293,8 @@ static int scsi_eh_test_devices(struct list_head *cmd_list,
  				if (finish_cmds &&
  				    (try_stu ||
  				     scsi_eh_action(scmd, SUCCESS) == SUCCESS))
-					scsi_eh_finish_cmd(scmd, done_q);
+					__scsi_eh_finish_cmd(scmd, done_q,
+							     DID_RESET);
  				else
  					list_move_tail(&scmd->eh_entry, work_q);
  			}
@@ -1429,8 +1439,9 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
  							 work_q, eh_entry) {
  					if (scmd->device == sdev &&
  					    scsi_eh_action(scmd, rtn) != FAILED)
-						scsi_eh_finish_cmd(scmd,
-								   done_q);
+						__scsi_eh_finish_cmd(scmd,
+								     done_q,
+								     DID_RESET);
  				}
  			}
  		} else {
@@ -1498,7 +1509,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
  			if (rtn == SUCCESS)
  				list_move_tail(&scmd->eh_entry, &check_list);
  			else if (rtn == FAST_IO_FAIL)
-				scsi_eh_finish_cmd(scmd, done_q);
+				__scsi_eh_finish_cmd(scmd, done_q,
+						     DID_TRANSPORT_DISRUPTED);
  			else
  				/* push back on work queue for further processing */
  				list_move(&scmd->eh_entry, work_q);
@@ -1563,8 +1575,9 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
  			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
  				if (channel == scmd_channel(scmd)) {
  					if (rtn == FAST_IO_FAIL)
-						scsi_eh_finish_cmd(scmd,
-								   done_q);
+						__scsi_eh_finish_cmd(scmd,
+								     done_q,
+								     DID_TRANSPORT_DISRUPTED);
  					else
  						list_move_tail(&scmd->eh_entry,
  							       &check_list);
@@ -1607,9 +1620,9 @@ static int scsi_eh_host_reset(struct Scsi_Host *shost,
  		if (rtn == SUCCESS) {
  			list_splice_init(work_q, &check_list);
  		} else if (rtn == FAST_IO_FAIL) {
-			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
-					scsi_eh_finish_cmd(scmd, done_q);
-			}
+			list_for_each_entry_safe(scmd, next, work_q, eh_entry)
+				__scsi_eh_finish_cmd(scmd, done_q,
+						     DID_TRANSPORT_DISRUPTED);

I can somewhat imagine why you set DID_TRANSPORT_DISRUPTED for the cases above where the eh callback told us FAST_IO_FAIL. However, here you (now) seem to do it unconditionally. As a result this seems to render all attempts to return either a proper FAST_IO_FAIL or SUCCESS from a host_reset_handler() futile?

  		} else {
  			SCSI_LOG_ERROR_RECOVERY(3,
  				shost_printk(KERN_INFO, shost,

How is this related to just changing the callback argument?

Haven't we previously set the host_byte to anything?

Is the above part rather an independent change or even fix which should live in a separate topical commit explaining why and what it does?

(I don't understand especially the DID_RESET cases.)


diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 8b93197..bc97e41 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -681,26 +681,26 @@ static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd)
  	return ret;
  }

-static int virtscsi_device_reset(struct scsi_cmnd *sc)
+static int virtscsi_device_reset(struct scsi_device *sdev)
  {
-	struct virtio_scsi *vscsi = shost_priv(sc->device->host);
+	struct virtio_scsi *vscsi = shost_priv(sdev->host);
  	struct virtio_scsi_cmd *cmd;

-	sdev_printk(KERN_INFO, sc->device, "device reset\n");
+	sdev_printk(KERN_INFO, sdev, "device reset\n");
  	cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO);
  	if (!cmd)
  		return FAILED;

  	memset(cmd, 0, sizeof(*cmd));
-	cmd->sc = sc;
+	cmd->sc = NULL;

I hope we are protected to never land in virtscsi_complete_cmd() with cmd->sc==NULL, not even e.g. if the virtio queue gets hot unplugged the hard way in parallel (forcing some completion to drain).
I'm thinking of commit 773c7220e22d193e5667c352fcbf8d47eefc817f
("scsi: virtio_scsi: Reject commands when virtqueue is broken").

  	cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){
  		.type = VIRTIO_SCSI_T_TMF,
  		.subtype = cpu_to_virtio32(vscsi->vdev,
  					     VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET),
  		.lun[0] = 1,
-		.lun[1] = sc->device->id,
-		.lun[2] = (sc->device->lun >> 8) | 0x40,
-		.lun[3] = sc->device->lun & 0xff,
+		.lun[1] = sdev->id,
+		.lun[2] = (sdev->lun >> 8) | 0x40,
+		.lun[3] = sdev->lun & 0xff,
  	};
  	return virtscsi_tmf(vscsi, cmd);
  }


diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 33bc523..7095076 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -145,7 +145,7 @@ struct scsi_host_template {
  	 * Status: REQUIRED	(at least one of them)
  	 */
  	int (* eh_abort_handler)(struct scsi_cmnd *);
-	int (* eh_device_reset_handler)(struct scsi_cmnd *);
+	int (* eh_device_reset_handler)(struct scsi_device *);
  	int (* eh_target_reset_handler)(struct scsi_target *);
  	int (* eh_bus_reset_handler)(struct Scsi_Host *, int);
  	int (* eh_host_reset_handler)(struct Scsi_Host *);


anything else, that I quoted but did not comment, looks good


--
Mit freundlichen Grüßen / Kind regards
Steffen Maier

Linux on z Systems Development

IBM Deutschland Research & Development GmbH
Vorsitzende des Aufsichtsrats: Martina Koederitz
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux