lib/nvmf: Add nvmf_subsystem_get_listeners RPC

Add an new RPC, nvmf_subsystem_get_listeners.

ANA state is per listener and per subsystem, and is stored in
subsystem listener. We can return ANA state by the existing
nvmf_get_subsystems RPC but it's confusing that listen addresses
have ANA states.

To change ANA state, we will provide a RPC to change ANA state of
only one selected subsystem listener.

To query ANA state, it will be convenient to get ANA states of all
listeners of one selected subsystem.

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Ic3baad6eac65d7af6e0cab2c4059e1458d41e6e2
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4059
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2020-09-03 16:26:38 +09:00 committed by Tomasz Zawadzki
parent a60865bff6
commit 9c1d648315
4 changed files with 156 additions and 0 deletions

View File

@ -4823,6 +4823,50 @@ Example response:
} }
~~~ ~~~
## nvmf_subsystem_get_listeners {#rpc_nvmf_subsystem_get_listeners}
### Parameters
Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN
tgt_name | Optional | string | Parent NVMe-oF target name.
### Example
Example request:
~~~
{
"jsonrpc": "2.0",
"id": 1,
"method": "nvmf_subsystem_get_listeners",
"params": {
"nqn": "nqn.2016-06.io.spdk:cnode1"
}
}
~~~
Example response:
~~~
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"address": {
"trtype": "RDMA",
"adrfam": "IPv4",
"traddr": "192.168.0.123",
"trsvcid": "4420"
},
"ana_state": "optimized"
}
]
}
~~~
## nvmf_set_max_subsystems {#rpc_nvmf_set_max_subsystems} ## nvmf_set_max_subsystems {#rpc_nvmf_set_max_subsystems}
Set the maximum allowed subsystems for the NVMe-oF target. This RPC may only be called Set the maximum allowed subsystems for the NVMe-oF target. This RPC may only be called

View File

@ -2136,6 +2136,51 @@ dump_nvmf_qpair(struct spdk_json_write_ctx *w, struct spdk_nvmf_qpair *qpair)
spdk_json_write_object_end(w); spdk_json_write_object_end(w);
} }
static const char *
nvme_ana_state_str(enum spdk_nvme_ana_state ana_state)
{
switch (ana_state) {
case SPDK_NVME_ANA_OPTIMIZED_STATE:
return "optimized";
case SPDK_NVME_ANA_NON_OPTIMIZED_STATE:
return "non_optimized";
case SPDK_NVME_ANA_INACCESSIBLE_STATE:
return "inaccessible";
case SPDK_NVME_ANA_PERSISTENT_LOSS_STATE:
return "persistent_loss";
case SPDK_NVME_ANA_CHANGE_STATE:
return "change";
default:
return NULL;
}
}
static void
dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w,
struct spdk_nvmf_subsystem_listener *listener)
{
const struct spdk_nvme_transport_id *trid = listener->trid;
const char *adrfam;
spdk_json_write_object_begin(w);
spdk_json_write_named_object_begin(w, "address");
adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam);
if (adrfam == NULL) {
adrfam = "unknown";
}
spdk_json_write_named_string(w, "trtype", trid->trstring);
spdk_json_write_named_string(w, "adrfam", adrfam);
spdk_json_write_named_string(w, "traddr", trid->traddr);
spdk_json_write_named_string(w, "trsvcid", trid->trsvcid);
spdk_json_write_object_end(w);
spdk_json_write_named_string(w, "ana_state",
nvme_ana_state_str(listener->ana_state));
spdk_json_write_object_end(w);
}
struct rpc_subsystem_query_ctx { struct rpc_subsystem_query_ctx {
char *nqn; char *nqn;
char *tgt_name; char *tgt_name;
@ -2235,6 +2280,35 @@ rpc_nvmf_get_qpairs_paused(struct spdk_nvmf_subsystem *subsystem,
rpc_nvmf_get_qpairs_done); rpc_nvmf_get_qpairs_done);
} }
static void
rpc_nvmf_get_listeners_paused(struct spdk_nvmf_subsystem *subsystem,
void *cb_arg, int status)
{
struct rpc_subsystem_query_ctx *ctx = cb_arg;
struct spdk_json_write_ctx *w;
struct spdk_nvmf_subsystem_listener *listener;
w = spdk_jsonrpc_begin_result(ctx->request);
spdk_json_write_array_begin(w);
for (listener = spdk_nvmf_subsystem_get_first_listener(ctx->subsystem);
listener != NULL;
listener = spdk_nvmf_subsystem_get_next_listener(ctx->subsystem, listener)) {
dump_nvmf_subsystem_listener(w, listener);
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(ctx->request, w);
if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) {
SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn);
/* FIXME: RPC should fail if resuming the subsystem failed. */
}
free_rpc_subsystem_query_ctx(ctx);
}
static void static void
_rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request, _rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params, const struct spdk_json_val *params,
@ -2307,3 +2381,12 @@ rpc_nvmf_subsystem_get_qpairs(struct spdk_jsonrpc_request *request,
_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused); _rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused);
} }
SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME); SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME);
static void
rpc_nvmf_subsystem_get_listeners(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_listeners_paused);
}
SPDK_RPC_REGISTER("nvmf_subsystem_get_listeners", rpc_nvmf_subsystem_get_listeners,
SPDK_RPC_RUNTIME);

View File

@ -2012,6 +2012,17 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str) p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=nvmf_subsystem_get_qpairs) p.set_defaults(func=nvmf_subsystem_get_qpairs)
def nvmf_subsystem_get_listeners(args):
print_dict(rpc.nvmf.nvmf_subsystem_get_listeners(args.client,
nqn=args.nqn,
tgt_name=args.tgt_name))
p = subparsers.add_parser('nvmf_subsystem_get_listeners',
help='Display listeners of an NVMe-oF subsystem.')
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=nvmf_subsystem_get_listeners)
def nvmf_get_stats(args): def nvmf_get_stats(args):
print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name)) print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name))

View File

@ -505,6 +505,24 @@ def nvmf_subsystem_get_qpairs(client, nqn, tgt_name=None):
return client.call('nvmf_subsystem_get_qpairs', params) return client.call('nvmf_subsystem_get_qpairs', params)
def nvmf_subsystem_get_listeners(client, nqn, tgt_name=None):
"""Get list of listeners of an NVMe-oF subsystem.
Args:
nqn: Subsystem NQN.
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
List of listener objects of an NVMe-oF subsystem.
"""
params = {'nqn': nqn}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_get_listeners', params)
def nvmf_get_stats(client, tgt_name=None): def nvmf_get_stats(client, tgt_name=None):
"""Query NVMf statistics. """Query NVMf statistics.