nvmet: support for traffic based keep-alive
authorSagi Grimberg <sagi@grimberg.me>
Fri, 2 Nov 2018 17:28:13 +0000 (10:28 -0700)
committerJens Axboe <axboe@kernel.dk>
Sat, 8 Dec 2018 05:26:56 +0000 (22:26 -0700)
A controller that supports traffic based keep-alive can restart the keep
alive timer even when no keep-alive was not received in the kato period
as long as other admin or I/O commands were received.  For each command
set ctrl->cmd_seen to true, and when keep-alive timer expires, if any
commands were seen, resched ka_work instead of escalating to a fatal
error.

Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/nvme/target/admin-cmd.c
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h

index 30778ffc46f528763de84ba95f933349072bd635..c9c6d25a3ec29f12800fabc5bb9585a09e88e6e8 100644 (file)
@@ -304,7 +304,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
 
        /* XXX: figure out what to do about RTD3R/RTD3 */
        id->oaes = cpu_to_le32(NVMET_AEN_CFG_OPTIONAL);
-       id->ctratt = cpu_to_le32(NVME_CTRL_ATTR_HID_128_BIT);
+       id->ctratt = cpu_to_le32(NVME_CTRL_ATTR_HID_128_BIT |
+               NVME_CTRL_ATTR_TBKAS);
 
        id->oacs = 0;
 
index a5f9bbce863f42dcff6c23759801fa9c48d0b210..05d8d9bc058fb3ed8864c3ec227b8ef3756bab7f 100644 (file)
@@ -299,6 +299,15 @@ static void nvmet_keep_alive_timer(struct work_struct *work)
 {
        struct nvmet_ctrl *ctrl = container_of(to_delayed_work(work),
                        struct nvmet_ctrl, ka_work);
+       bool cmd_seen = ctrl->cmd_seen;
+
+       ctrl->cmd_seen = false;
+       if (cmd_seen) {
+               pr_debug("ctrl %d reschedule traffic based keep-alive timer\n",
+                       ctrl->cntlid);
+               schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
+               return;
+       }
 
        pr_err("ctrl %d keep-alive timer (%d seconds) expired!\n",
                ctrl->cntlid, ctrl->kato);
@@ -801,6 +810,9 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
                goto fail;
        }
 
+       if (sq->ctrl)
+               sq->ctrl->cmd_seen = true;
+
        return true;
 
 fail:
index c2b4d9ee63916f50818ecaccf0a2b66365d4511a..860218edeb6c7e466fec2d80a5258c6ccc56d078 100644 (file)
@@ -163,6 +163,8 @@ struct nvmet_ctrl {
        struct nvmet_cq         **cqs;
        struct nvmet_sq         **sqs;
 
+       bool                    cmd_seen;
+
        struct mutex            lock;
        u64                     cap;
        u32                     cc;