Skip to content

Commit c722180

Browse files
committed
Added vendor specific subsystem pause/resume
Signed-off-by: Susobhan Dey <susobhan.dey@gmail.com>
1 parent cc090cd commit c722180

6 files changed

Lines changed: 167 additions & 1 deletion

File tree

include/spdk/nvmf.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ extern "C" {
2727

2828
#define SPDK_TLS_PSK_MAX_LEN 200
2929

30+
#define SPDK_NVMF_SUBSYSTEM_PAUSE_KEEP_ADMINQ 0x1
31+
3032
struct spdk_nvmf_tgt;
3133
struct spdk_nvmf_subsystem;
3234
struct spdk_nvmf_ctrlr;
@@ -566,6 +568,21 @@ int spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem,
566568
spdk_nvmf_subsystem_state_change_done cb_fn,
567569
void *cb_arg);
568570

571+
/**
572+
* Vendor specific wrapper of subsystem pause
573+
* we need to keep allow some admin commands during subsystem pause
574+
*/
575+
int spdk_nvmf_subsystem_pause_ext(struct spdk_nvmf_subsystem *subsystem,
576+
uint32_t nsid,
577+
uint32_t flags,
578+
spdk_nvmf_subsystem_state_change_done cb_fn,
579+
void *cb_arg);
580+
581+
int spdk_nvmf_subsystem_set_pause_timeout(struct spdk_nvmf_subsystem *subsystem,
582+
uint32_t timeout_sec);
583+
584+
uint32_t spdk_nvmf_subsystem_get_pause_timeout(struct spdk_nvmf_subsystem *subsystem);
585+
569586
/**
570587
* Transition an NVMe-oF subsystem from Paused to Active state.
571588
*
@@ -582,6 +599,13 @@ int spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem,
582599
spdk_nvmf_subsystem_state_change_done cb_fn,
583600
void *cb_arg);
584601

602+
/**
603+
* Vendor specific wrapper of subsystem resume
604+
* We need to clear vendor specific flags during resume
605+
*/
606+
int spdk_nvmf_subsystem_resume_ext(struct spdk_nvmf_subsystem *subsystem,
607+
spdk_nvmf_subsystem_state_change_done cb_fn,
608+
void *cb_arg);
585609
/**
586610
* Search the target for a subsystem with the given NQN.
587611
*

lib/nvmf/ctrlr.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4859,6 +4859,7 @@ nvmf_check_subsystem_active(struct spdk_nvmf_request *req)
48594859
struct spdk_nvmf_subsystem_poll_group *sgroup = NULL;
48604860
struct spdk_nvmf_subsystem_pg_ns_info *ns_info;
48614861
uint32_t nsid;
4862+
struct spdk_nvmf_subsystem *subsystem = NULL;
48624863

48634864
if (spdk_likely(qpair->ctrlr)) {
48644865
sgroup = &qpair->group->sgroups[qpair->ctrlr->subsys->id];
@@ -4875,6 +4876,16 @@ nvmf_check_subsystem_active(struct spdk_nvmf_request *req)
48754876
if (spdk_unlikely(req->cmd->nvmf_cmd.opcode == SPDK_NVME_OPC_FABRIC ||
48764877
nvmf_qpair_is_admin_queue(qpair))) {
48774878
if (sgroup->state != SPDK_NVMF_SUBSYSTEM_ACTIVE) {
4879+
subsystem = qpair->ctrlr->subsys;
4880+
if (req->cmd->nvmf_cmd.opcode != SPDK_NVME_OPC_FABRIC &&
4881+
(subsystem->pause_flags & SPDK_NVMF_SUBSYSTEM_PAUSE_KEEP_ADMINQ)) {
4882+
/*
4883+
* Vendor maintenance pause
4884+
* allow normal admin queue commands while data IO is paused
4885+
*/
4886+
sgroup->mgmt_io_outstanding++;
4887+
return true;
4888+
}
48784889
/* The subsystem is not currently active. Queue this request. */
48794890
TAILQ_INSERT_TAIL(&sgroup->queued, req, link);
48804891
return false;

lib/nvmf/nvmf_internal.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
2727
#define NVMF_MIN_CNTLID 1
2828
#define NVMF_MAX_CNTLID 0xFFEF
29-
29+
#define SPDK_NVMF_DEFAULT_PAUSE_TIMEOUT_SEC 120
3030
#define NVMF_DISC_KATO_IN_MS 120000
3131
#define NVMF_KAS_TIME_UNIT_IN_MS 100
3232
#define NVMF_DEFAULT_KAS 100
@@ -365,6 +365,10 @@ struct spdk_nvmf_subsystem {
365365
/* Subsystem event callback and its argument. */
366366
spdk_nvmf_subsystem_event_cb event_cb_fn;
367367
void *event_cb_arg;
368+
/* Vendor specific flags for maintainance work */
369+
uint32_t pause_flags;
370+
struct spdk_poller *pause_timer;
371+
uint32_t pause_timeout_sec;
368372
};
369373

370374
static int

lib/nvmf/subsystem.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
265265
subsystem->next_cntlid = 1;
266266
subsystem->min_cntlid = NVMF_MIN_CNTLID;
267267
subsystem->max_cntlid = NVMF_MAX_CNTLID;
268+
subsystem->pause_timeout_sec = SPDK_NVMF_DEFAULT_PAUSE_TIMEOUT_SEC;
269+
subsystem->pause_flags = 0;
270+
subsystem->pause_timer = NULL;
268271
snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn);
269272
pthread_mutex_init(&subsystem->mutex, NULL);
270273
TAILQ_INIT(&subsystem->listeners);
@@ -400,6 +403,11 @@ _nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem)
400403
return -EINPROGRESS;
401404
}
402405

406+
if (subsystem->pause_timer) {
407+
spdk_poller_unregister(&subsystem->pause_timer);
408+
subsystem->pause_timer = NULL;
409+
}
410+
403411
ns = spdk_nvmf_subsystem_get_first_ns(subsystem);
404412
while (ns != NULL) {
405413
struct spdk_nvmf_ns *next_ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns);
@@ -813,6 +821,50 @@ spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem,
813821
return nvmf_subsystem_state_change(subsystem, 0, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg);
814822
}
815823

824+
static
825+
int nvmf_subsys_pause_timer_cb(void *arg)
826+
{
827+
struct spdk_nvmf_subsystem *subsystem = arg;
828+
subsystem->pause_flags = 0;
829+
if (subsystem->pause_timer) {
830+
spdk_poller_unregister(&subsystem->pause_timer);
831+
subsystem->pause_timer = NULL;
832+
}
833+
return SPDK_POLLER_BUSY;
834+
}
835+
836+
int
837+
spdk_nvmf_subsystem_pause_ext(struct spdk_nvmf_subsystem *subsystem,
838+
uint32_t nsid,
839+
uint32_t flags,
840+
spdk_nvmf_subsystem_state_change_done cb_fn,
841+
void *cb_arg)
842+
{
843+
subsystem->pause_flags = flags;
844+
if (subsystem->pause_timer == NULL) {
845+
subsystem->pause_timer = spdk_poller_register(
846+
nvmf_subsys_pause_timer_cb,
847+
subsystem,
848+
subsystem->pause_timeout_sec * 1000000ULL
849+
);
850+
}
851+
return spdk_nvmf_subsystem_pause(subsystem, nsid, cb_fn, cb_arg);
852+
}
853+
854+
int
855+
spdk_nvmf_subsystem_set_pause_timeout(struct spdk_nvmf_subsystem *subsystem,
856+
uint32_t timeout_sec)
857+
{
858+
subsystem->pause_timeout_sec = timeout_sec;
859+
return 0;
860+
}
861+
862+
uint32_t
863+
spdk_nvmf_subsystem_get_pause_timeout(struct spdk_nvmf_subsystem *subsystem)
864+
{
865+
return subsystem->pause_timeout_sec;
866+
}
867+
816868
int
817869
spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem,
818870
uint32_t nsid,
@@ -822,6 +874,19 @@ spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem,
822874
return nvmf_subsystem_state_change(subsystem, nsid, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg);
823875
}
824876

877+
int
878+
spdk_nvmf_subsystem_resume_ext(struct spdk_nvmf_subsystem *subsystem,
879+
spdk_nvmf_subsystem_state_change_done cb_fn,
880+
void *cb_arg)
881+
{
882+
subsystem->pause_flags = 0;
883+
if (subsystem->pause_timer) {
884+
spdk_poller_unregister(&subsystem->pause_timer);
885+
subsystem->pause_timer = NULL;
886+
}
887+
return spdk_nvmf_subsystem_resume(subsystem, cb_fn, cb_arg);
888+
}
889+
825890
int
826891
spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem,
827892
spdk_nvmf_subsystem_state_change_done cb_fn,

module/event/subsystems/nvmf/nvmf_rpc.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,56 @@ static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_opts_decoder
1414
{"max_subsystems", 0, spdk_json_decode_uint32, true}
1515
};
1616

17+
struct rpc_nvmf_subsystem_set_pause_timeout {
18+
char *nqn;
19+
uint32_t pause_timeout_sec;
20+
};
21+
22+
static const struct spdk_json_object_decoder rpc_nvmf_subsystem_set_pause_timeout_decoders[] = {
23+
{"nqn", offsetof(struct rpc_nvmf_subsystem_set_pause_timeout, nqn), spdk_json_decode_string},
24+
{"pause_timeout_sec", offsetof(struct rpc_nvmf_subsystem_set_pause_timeout, pause_timeout_sec), spdk_json_decode_uint32}
25+
};
26+
27+
static void
28+
rpc_nvmf_subsystem_set_pause_timeout(struct spdk_jsonrpc_request *request,
29+
const struct spdk_json_val *params)
30+
{
31+
struct rpc_nvmf_subsystem_set_pause_timeout req = {};
32+
struct spdk_nvmf_subsystem *subsystem;
33+
int rc;
34+
35+
if (spdk_json_decode_object(params,
36+
rpc_nvmf_subsystem_set_pause_timeout_decoders,
37+
SPDK_COUNTOF(rpc_nvmf_subsystem_set_pause_timeout_decoders),
38+
&req)) {
39+
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
40+
"Invalid parameters");
41+
goto cleanup;
42+
}
43+
44+
subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, req.nqn);
45+
if (subsystem == NULL) {
46+
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Invalid nqn");
47+
goto cleanup;
48+
}
49+
50+
rc = spdk_nvmf_subsystem_set_pause_timeout(subsystem, req.pause_timeout_sec);
51+
if (rc != 0) {
52+
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
53+
"Failed to set timeout");
54+
goto cleanup;
55+
}
56+
57+
spdk_jsonrpc_send_bool_response(request, true);
58+
59+
cleanup:
60+
free(req.nqn);
61+
}
62+
63+
SPDK_RPC_REGISTER("nvmf_subsystem_set_pause_timeout",
64+
rpc_nvmf_subsystem_set_pause_timeout,
65+
SPDK_RPC_RUNTIME)
66+
1767
static void
1868
rpc_nvmf_set_max_subsystems(struct spdk_jsonrpc_request *request,
1969
const struct spdk_json_val *params)

scripts/rpc.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2573,6 +2573,18 @@ def nvmf_set_max_subsystems(args):
25732573
p.add_argument('-x', '--max-subsystems', help='Max number of NVMf subsystems', type=int, required=True)
25742574
p.set_defaults(func=nvmf_set_max_subsystems)
25752575

2576+
def nvmf_subsystem_set_pause_timeout(args):
2577+
print_json(args.client.nvmf_subsystem_set_pause_timeout(
2578+
nqn=args.nqn,
2579+
pause_timeout_sec=args.pause_timeout_sec))
2580+
2581+
2582+
p = subparsers.add_parser('nvmf_subsystem_set_pause_timeout',
2583+
help='Set NVMf subsystem pause timeout')
2584+
p.add_argument('nqn', help='Subsystem NQN')
2585+
p.add_argument('pause_timeout_sec', help='Pause timeout in seconds', type=int)
2586+
p.set_defaults(func=nvmf_subsystem_set_pause_timeout)
2587+
25762588
def nvmf_set_config(args):
25772589
rpc.nvmf.nvmf_set_config(args.client,
25782590
passthru_identify_ctrlr=args.passthru_identify_ctrlr,

0 commit comments

Comments
 (0)