Patch "nvme: check IO start time when deciding to defer KA" has been added to the 6.1-stable tree

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

 



This is a note to let you know that I've just added the patch titled

    nvme: check IO start time when deciding to defer KA

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     nvme-check-io-start-time-when-deciding-to-defer-ka.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 10de1efa98ae7cab47aea4f8e51bc0f98507f1a3
Author: Uday Shankar <ushankar@xxxxxxxxxxxxxxx>
Date:   Thu May 25 12:22:03 2023 -0600

    nvme: check IO start time when deciding to defer KA
    
    [ Upstream commit 774a9636514764ddc0d072ae0d1d1c01a47e6ddd ]
    
    When a command completes, we set a flag which will skip sending a
    keep alive at the next run of nvme_keep_alive_work when TBKAS is on.
    However, if the command was submitted long ago, it's possible that
    the controller may have also restarted its keep alive timer (as a
    result of receiving the command) long ago. The following trace
    demonstrates the issue, assuming TBKAS is on and KATO = 8 for
    simplicity:
    
    1. t = 0: submit I/O commands A, B, C, D, E
    2. t = 0.5: commands A, B, C, D, E reach controller, restart its keep
                alive timer
    3. t = 1: A completes
    4. t = 2: run nvme_keep_alive_work, see recent completion, do nothing
    5. t = 3: B completes
    6. t = 4: run nvme_keep_alive_work, see recent completion, do nothing
    7. t = 5: C completes
    8. t = 6: run nvme_keep_alive_work, see recent completion, do nothing
    9. t = 7: D completes
    10. t = 8: run nvme_keep_alive_work, see recent completion, do nothing
    11. t = 9: E completes
    
    At this point, 8.5 seconds have passed without restarting the
    controller's keep alive timer, so the controller will detect a keep
    alive timeout.
    
    Fix this by checking the IO start time when deciding to defer sending a
    keep alive command. Only set comp_seen if the command started after the
    most recent run of nvme_keep_alive_work. With this change, the
    completions of B, C, and D will not set comp_seen and the run of
    nvme_keep_alive_work at t = 4 will send a keep alive.
    
    Reported-by: Costa Sapuntzakis <costa@xxxxxxxxxxxxxxx>
    Reported-by: Randy Jennings <randyj@xxxxxxxxxxxxxxx>
    Signed-off-by: Uday Shankar <ushankar@xxxxxxxxxxxxxxx>
    Reviewed-by: Hannes Reinecke <hare@xxxxxxx>
    Reviewed-by: Sagi Grimberg <sagi@xxxxxxxxxxx>
    Reviewed-by: Christoph Hellwig <hch@xxxxxx>
    Signed-off-by: Keith Busch <kbusch@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index a97f2f21c5321..15eb2ee1be66e 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -395,7 +395,16 @@ void nvme_complete_rq(struct request *req)
 	trace_nvme_complete_rq(req);
 	nvme_cleanup_cmd(req);
 
-	if (ctrl->kas)
+	/*
+	 * Completions of long-running commands should not be able to
+	 * defer sending of periodic keep alives, since the controller
+	 * may have completed processing such commands a long time ago
+	 * (arbitrarily close to command submission time).
+	 * req->deadline - req->timeout is the command submission time
+	 * in jiffies.
+	 */
+	if (ctrl->kas &&
+	    req->deadline - req->timeout >= ctrl->ka_last_check_time)
 		ctrl->comp_seen = true;
 
 	switch (nvme_decide_disposition(req)) {
@@ -1235,6 +1244,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
 		return RQ_END_IO_NONE;
 	}
 
+	ctrl->ka_last_check_time = jiffies;
 	ctrl->comp_seen = false;
 	spin_lock_irqsave(&ctrl->lock, flags);
 	if (ctrl->state == NVME_CTRL_LIVE ||
@@ -1253,6 +1263,8 @@ static void nvme_keep_alive_work(struct work_struct *work)
 	bool comp_seen = ctrl->comp_seen;
 	struct request *rq;
 
+	ctrl->ka_last_check_time = jiffies;
+
 	if ((ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) && comp_seen) {
 		dev_dbg(ctrl->device,
 			"reschedule traffic based keep-alive timer\n");
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 3f82de6060ef7..2aa514c3dfa17 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -323,6 +323,7 @@ struct nvme_ctrl {
 	struct delayed_work ka_work;
 	struct delayed_work failfast_work;
 	struct nvme_command ka_cmd;
+	unsigned long ka_last_check_time;
 	struct work_struct fw_act_work;
 	unsigned long events;
 



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux