From: Bart Van Assche <bvanassche@acm.org>
To: "Martin K . Petersen" <martin.petersen@oracle.com>
Cc: linux-scsi@vger.kernel.org, Bart Van Assche <bvanassche@acm.org>,
Ming Lei <ming.lei@redhat.com>,
Mike Christie <michael.christie@oracle.com>,
John Garry <john.g.garry@oracle.com>,
Damien Le Moal <damien.lemoal@opensource.wdc.com>,
Hannes Reinecke <hare@suse.de>,
"James E.J. Bottomley" <jejb@linux.ibm.com>
Subject: [PATCH] scsi: core: Simplify the code for waking up the error handler
Date: Tue, 7 Mar 2023 13:51:51 -0800 [thread overview]
Message-ID: <20230307215151.3705164-1-bvanassche@acm.org> (raw)
scsi_dec_host_busy() is called from the hot path and hence must not
obtain the host lock if no commands have failed. scsi_dec_host_busy()
tests three different variables of which at least two are set if a
command failed. Commit 3bd6f43f5cb3 ("scsi: core: Ensure that the
SCSI error handler gets woken up") introduced a call_rcu() call to
ensure that all tasks observe the host state change before the
host_failed change. Simplify the approach for guaranteeing that the host
state and host_failed/host_eh_scheduled changes are observed in order by using
smp_store_release() to update host_failed or host_eh_scheduled after
having update the host state and smp_load_acquire() before reading the
host state.
Cc: Ming Lei <ming.lei@redhat.com>
Cc: Mike Christie <michael.christie@oracle.com>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/scsi/scsi_error.c | 22 ++++------------------
drivers/scsi/scsi_lib.c | 31 +++++++++----------------------
include/scsi/scsi_cmnd.h | 2 --
3 files changed, 13 insertions(+), 42 deletions(-)
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 2aa2c2aee6e7..2a809145da06 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -87,7 +87,8 @@ void scsi_schedule_eh(struct Scsi_Host *shost)
if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
- shost->host_eh_scheduled++;
+ smp_store_release(&shost->host_eh_scheduled,
+ shost->host_eh_scheduled + 1);
scsi_eh_wakeup(shost);
}
@@ -278,18 +279,6 @@ static void scsi_eh_reset(struct scsi_cmnd *scmd)
}
}
-static void scsi_eh_inc_host_failed(struct rcu_head *head)
-{
- struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
- struct Scsi_Host *shost = scmd->device->host;
- unsigned long flags;
-
- spin_lock_irqsave(shost->host_lock, flags);
- shost->host_failed++;
- scsi_eh_wakeup(shost);
- spin_unlock_irqrestore(shost->host_lock, flags);
-}
-
/**
* scsi_eh_scmd_add - add scsi cmd to error handling.
* @scmd: scmd to run eh on.
@@ -312,12 +301,9 @@ void scsi_eh_scmd_add(struct scsi_cmnd *scmd)
scsi_eh_reset(scmd);
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
+ smp_store_release(&shost->host_failed, shost->host_failed + 1);
+ scsi_eh_wakeup(shost);
spin_unlock_irqrestore(shost->host_lock, flags);
- /*
- * Ensure that all tasks observe the host state change before the
- * host_failed change.
- */
- call_rcu_hurry(&scmd->rcu, scsi_eh_inc_host_failed);
}
/**
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b7c569a42aa4..e59eb0cbfc83 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -263,28 +263,24 @@ int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd,
}
EXPORT_SYMBOL(scsi_execute_cmd);
-/*
- * Wake up the error handler if necessary. Avoid as follows that the error
- * handler is not woken up if host in-flight requests number ==
- * shost->host_failed: use call_rcu() in scsi_eh_scmd_add() in combination
- * with an RCU read lock in this function to ensure that this function in
- * its entirety either finishes before scsi_eh_scmd_add() increases the
- * host_failed counter or that it notices the shost state change made by
- * scsi_eh_scmd_add().
- */
+/* Wake up the error handler if necessary. */
static void scsi_dec_host_busy(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
{
unsigned long flags;
- rcu_read_lock();
__clear_bit(SCMD_STATE_INFLIGHT, &cmd->state);
- if (unlikely(scsi_host_in_recovery(shost))) {
+ /*
+ * Test host_failed and host_eh_scheduled before the host state to
+ * ensure that the host state update is observed if the host_failed
+ * and/or host_eh_scheduled updates are observed.
+ */
+ if (unlikely((smp_load_acquire(&shost->host_failed) ||
+ smp_load_acquire(&shost->host_eh_scheduled)))) {
spin_lock_irqsave(shost->host_lock, flags);
- if (shost->host_failed || shost->host_eh_scheduled)
+ if (scsi_host_in_recovery(shost))
scsi_eh_wakeup(shost);
spin_unlock_irqrestore(shost->host_lock, flags);
}
- rcu_read_unlock();
}
void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd)
@@ -547,14 +543,6 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
cmd->flags &= ~SCMD_INITIALIZED;
}
- /*
- * Calling rcu_barrier() is not necessary here because the
- * SCSI error handler guarantees that the function called by
- * call_rcu() has been called before scsi_end_request() is
- * called.
- */
- destroy_rcu_head(&cmd->rcu);
-
/*
* In the MQ case the command gets freed by __blk_mq_end_request,
* so we have to do all cleanup that depends on it earlier.
@@ -1124,7 +1112,6 @@ static void scsi_initialize_rq(struct request *rq)
memset(cmd->cmnd, 0, sizeof(cmd->cmnd));
cmd->cmd_len = MAX_COMMAND_SIZE;
cmd->sense_len = 0;
- init_rcu_head(&cmd->rcu);
cmd->jiffies_at_alloc = jiffies;
cmd->retries = 0;
}
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index c2cb5f69635c..7965f5114144 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -71,8 +71,6 @@ struct scsi_cmnd {
struct list_head eh_entry; /* entry for the host eh_abort_list/eh_cmd_q */
struct delayed_work abort_work;
- struct rcu_head rcu;
-
int eh_eflags; /* Used by error handlr */
int budget_token;
next reply other threads:[~2023-03-07 21:52 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-07 21:51 Bart Van Assche [this message]
2023-03-09 12:13 ` [PATCH] scsi: core: Simplify the code for waking up the error handler Benjamin Block
2023-03-09 17:20 ` Bart Van Assche
2023-03-10 12:30 ` Benjamin Block
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230307215151.3705164-1-bvanassche@acm.org \
--to=bvanassche@acm.org \
--cc=damien.lemoal@opensource.wdc.com \
--cc=hare@suse.de \
--cc=jejb@linux.ibm.com \
--cc=john.g.garry@oracle.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=michael.christie@oracle.com \
--cc=ming.lei@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox