lib/nvmf: Add nvmf_subsystem_listener_set_ana_state RPC
Add an new RPC, nvmf_subsystem_listener_set_ana_state. Find the specified subsystem listener, and then set the ANA state of the listener by calling nvmf_subsystem_listener_set_ana_state(). By adding a string and an enum to the existing context structure, nvmf_rpc_listener_ctx, and adding an operation type to the existng enum, nvmf_rpc_listen_op, reuse the existing code and data as much as possible. Besides, insert line break into a few long lines and fix wrong error log. Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: I6fb2dfbb1f9c5f56848eba21d2a733fbed802614 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4080 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Broadcom CI Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
071d80f37b
commit
c8cb51d4bc
@ -4659,6 +4659,51 @@ Example response:
|
||||
}
|
||||
~~~
|
||||
|
||||
## nvmf_subsystem_listener_set_ana_state method {#rpc_nvmf_subsystem_listener_set_ana_state}
|
||||
|
||||
Set ANA state of a listener for an NVMe-oF subsystem.
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
nqn | Required | string | Subsystem NQN
|
||||
tgt_name | Optional | string | Parent NVMe-oF target name.
|
||||
listen_address | Required | object | @ref rpc_nvmf_listen_address object
|
||||
ana_state | Required | string | ANA state to set ("optimized", "non_optimized", or "inaccessible")
|
||||
|
||||
### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "nvmf_subsystem_listener_set_ana_state",
|
||||
"params": {
|
||||
"nqn": "nqn.2016-06.io.spdk:cnode1",
|
||||
"listen_address": {
|
||||
"trtype": "RDMA",
|
||||
"adrfam": "IPv4",
|
||||
"traddr": "192.168.0.123",
|
||||
"trsvcid": "4420"
|
||||
},
|
||||
"ana_state", "inaccessible"
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
## nvmf_subsystem_add_ns method {#rpc_nvmf_subsystem_add_ns}
|
||||
|
||||
Add a namespace to a subsystem. The namespace ID is returned as the result.
|
||||
|
@ -588,6 +588,7 @@ free_rpc_listen_address(struct rpc_listen_address *r)
|
||||
enum nvmf_rpc_listen_op {
|
||||
NVMF_RPC_LISTEN_ADD,
|
||||
NVMF_RPC_LISTEN_REMOVE,
|
||||
NVMF_RPC_LISTEN_SET_ANA_STATE,
|
||||
};
|
||||
|
||||
struct nvmf_rpc_listener_ctx {
|
||||
@ -597,6 +598,8 @@ struct nvmf_rpc_listener_ctx {
|
||||
struct spdk_nvmf_transport *transport;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
struct rpc_listen_address address;
|
||||
char *ana_state_str;
|
||||
enum spdk_nvme_ana_state ana_state;
|
||||
|
||||
struct spdk_jsonrpc_request *request;
|
||||
struct spdk_nvme_transport_id trid;
|
||||
@ -616,6 +619,7 @@ nvmf_rpc_listener_ctx_free(struct nvmf_rpc_listener_ctx *ctx)
|
||||
free(ctx->nqn);
|
||||
free(ctx->tgt_name);
|
||||
free_rpc_listen_address(&ctx->address);
|
||||
free(ctx->ana_state_str);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
@ -658,7 +662,8 @@ nvmf_rpc_subsystem_listen(void *cb_arg, int status)
|
||||
|
||||
if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
||||
if (!ctx->response_sent) {
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Internal error");
|
||||
}
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
/* Can't really do anything to recover here - subsystem will remain paused. */
|
||||
@ -670,15 +675,38 @@ nvmf_rpc_stop_listen_async_done(void *cb_arg, int status)
|
||||
struct nvmf_rpc_listener_ctx *ctx = cb_arg;
|
||||
|
||||
if (status) {
|
||||
SPDK_ERRLOG("Unable to remove listener.\n");
|
||||
SPDK_ERRLOG("Unable to stop listener.\n");
|
||||
spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"error stopping listener: %d\n", status);
|
||||
"error stopping listener: %d", status);
|
||||
ctx->response_sent = true;
|
||||
}
|
||||
|
||||
if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
||||
if (!ctx->response_sent) {
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Internal error");
|
||||
}
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
/* Can't really do anything to recover here - subsystem will remain paused. */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nvmf_rpc_set_ana_state_done(void *cb_arg, int status)
|
||||
{
|
||||
struct nvmf_rpc_listener_ctx *ctx = cb_arg;
|
||||
|
||||
if (status) {
|
||||
SPDK_ERRLOG("Unable to set ANA state.\n");
|
||||
spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"error setting ANA state: %d", status);
|
||||
ctx->response_sent = true;
|
||||
}
|
||||
|
||||
if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
||||
if (!ctx->response_sent) {
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Internal error");
|
||||
}
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
/* Can't really do anything to recover here - subsystem will remain paused. */
|
||||
@ -714,13 +742,18 @@ nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem,
|
||||
spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, nvmf_rpc_stop_listen_async_done,
|
||||
ctx);
|
||||
return;
|
||||
} else if (ctx->op == NVMF_RPC_LISTEN_SET_ANA_STATE) {
|
||||
nvmf_subsystem_set_ana_state(subsystem, &ctx->trid, ctx->ana_state,
|
||||
nvmf_rpc_set_ana_state_done, ctx);
|
||||
return;
|
||||
} else {
|
||||
SPDK_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
||||
if (!ctx->response_sent) {
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Internal error");
|
||||
}
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
/* Can't really do anything to recover here - subsystem will remain paused. */
|
||||
@ -919,6 +952,108 @@ rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
|
||||
SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", rpc_nvmf_subsystem_remove_listener,
|
||||
SPDK_RPC_RUNTIME);
|
||||
|
||||
static const struct spdk_json_object_decoder nvmf_rpc_set_ana_state_decoder[] = {
|
||||
{"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string},
|
||||
{"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address},
|
||||
{"ana_state", offsetof(struct nvmf_rpc_listener_ctx, ana_state_str), spdk_json_decode_string},
|
||||
{"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true},
|
||||
};
|
||||
|
||||
static int
|
||||
rpc_ana_state_parse(const char *str, enum spdk_nvme_ana_state *ana_state)
|
||||
{
|
||||
if (ana_state == NULL || str == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strcasecmp(str, "optimized") == 0) {
|
||||
*ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
|
||||
} else if (strcasecmp(str, "non_optimized") == 0) {
|
||||
*ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
|
||||
} else if (strcasecmp(str, "inaccessible") == 0) {
|
||||
*ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
|
||||
} else {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_nvmf_subsystem_listener_set_ana_state(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct nvmf_rpc_listener_ctx *ctx;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
struct spdk_nvmf_tgt *tgt;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->request = request;
|
||||
|
||||
if (spdk_json_decode_object(params, nvmf_rpc_set_ana_state_decoder,
|
||||
SPDK_COUNTOF(nvmf_rpc_set_ana_state_decoder),
|
||||
ctx)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid parameters");
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
|
||||
if (!tgt) {
|
||||
SPDK_ERRLOG("Unable to find a target object.\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Unable to find a target.\n");
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->tgt = tgt;
|
||||
|
||||
subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
|
||||
if (!subsystem) {
|
||||
SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Unable to find subsystem with NQN %s",
|
||||
ctx->nqn);
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->subsystem = subsystem;
|
||||
|
||||
if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid parameters");
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rpc_ana_state_parse(ctx->ana_state_str, &ctx->ana_state)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid parameters");
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->op = NVMF_RPC_LISTEN_SET_ANA_STATE;
|
||||
|
||||
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Internal error");
|
||||
nvmf_rpc_listener_ctx_free(ctx);
|
||||
}
|
||||
}
|
||||
SPDK_RPC_REGISTER("nvmf_subsystem_listener_set_ana_state",
|
||||
rpc_nvmf_subsystem_listener_set_ana_state, SPDK_RPC_RUNTIME);
|
||||
|
||||
struct spdk_nvmf_ns_params {
|
||||
char *bdev_name;
|
||||
char *ptpl_file;
|
||||
|
@ -1919,6 +1919,26 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number')
|
||||
p.set_defaults(func=nvmf_subsystem_remove_listener)
|
||||
|
||||
def nvmf_subsystem_listener_set_ana_state(args):
|
||||
rpc.nvmf.nvmf_subsystem_listener_set_ana_state(args.client,
|
||||
nqn=args.nqn,
|
||||
ana_state=args.ana_state,
|
||||
trtype=args.trtype,
|
||||
traddr=args.traddr,
|
||||
tgt_name=args.tgt_name,
|
||||
adrfam=args.adrfam,
|
||||
trsvcid=args.trsvcid)
|
||||
|
||||
p = subparsers.add_parser('nvmf_subsystem_listener_set_ana_state', help='Set ANA state of a listener for an NVMe-oF subsystem')
|
||||
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
|
||||
p.add_argument('-n', '--ana-state', help='ANA state to set: optimized, non-optimized, or inaccessible', required=True)
|
||||
p.add_argument('-t', '--trtype', help='NVMe-oF transport type: e.g., rdma', required=True)
|
||||
p.add_argument('-a', '--traddr', help='NVMe-oF transport address: e.g., an ip address', required=True)
|
||||
p.add_argument('-p', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
|
||||
p.add_argument('-f', '--adrfam', help='NVMe-oF transport adrfam: e.g., ipv4, ipv6, ib, fc, intra_host')
|
||||
p.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number')
|
||||
p.set_defaults(func=nvmf_subsystem_listener_set_ana_state)
|
||||
|
||||
def nvmf_subsystem_add_ns(args):
|
||||
rpc.nvmf.nvmf_subsystem_add_ns(args.client,
|
||||
nqn=args.nqn,
|
||||
|
@ -330,6 +330,46 @@ def nvmf_subsystem_remove_listener(
|
||||
return client.call('nvmf_subsystem_remove_listener', params)
|
||||
|
||||
|
||||
def nvmf_subsystem_listener_set_ana_state(
|
||||
client,
|
||||
nqn,
|
||||
ana_state,
|
||||
trtype,
|
||||
traddr,
|
||||
trsvcid,
|
||||
adrfam,
|
||||
tgt_name=None):
|
||||
"""Set ANA state of a listener for an NVMe-oF subsystem.
|
||||
|
||||
Args:
|
||||
nqn: Subsystem NQN.
|
||||
ana_state: ANA state to set ("optimized", "non_optimized", or "inaccessible").
|
||||
trtype: Transport type ("RDMA").
|
||||
traddr: Transport address.
|
||||
trsvcid: Transport service ID.
|
||||
tgt_name: name of the parent NVMe-oF target (optional).
|
||||
adrfam: Address family ("IPv4", "IPv6", "IB", or "FC").
|
||||
|
||||
Returns:
|
||||
True or False
|
||||
"""
|
||||
listen_address = {'trtype': trtype,
|
||||
'traddr': traddr,
|
||||
'trsvcid': trsvcid}
|
||||
|
||||
if adrfam:
|
||||
listen_address['adrfam'] = adrfam
|
||||
|
||||
params = {'nqn': nqn,
|
||||
'listen_address': listen_address,
|
||||
'ana_state': ana_state}
|
||||
|
||||
if tgt_name:
|
||||
params['tgt_name'] = tgt_name
|
||||
|
||||
return client.call('nvmf_subsystem_listener_set_ana_state', params)
|
||||
|
||||
|
||||
def nvmf_subsystem_add_ns(client, nqn, bdev_name, tgt_name=None, ptpl_file=None, nsid=None, nguid=None, eui64=None, uuid=None):
|
||||
"""Add a namespace to a subsystem.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user