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}
|
## nvmf_subsystem_add_ns method {#rpc_nvmf_subsystem_add_ns}
|
||||||
|
|
||||||
Add a namespace to a subsystem. The namespace ID is returned as the result.
|
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 {
|
enum nvmf_rpc_listen_op {
|
||||||
NVMF_RPC_LISTEN_ADD,
|
NVMF_RPC_LISTEN_ADD,
|
||||||
NVMF_RPC_LISTEN_REMOVE,
|
NVMF_RPC_LISTEN_REMOVE,
|
||||||
|
NVMF_RPC_LISTEN_SET_ANA_STATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nvmf_rpc_listener_ctx {
|
struct nvmf_rpc_listener_ctx {
|
||||||
@ -597,6 +598,8 @@ struct nvmf_rpc_listener_ctx {
|
|||||||
struct spdk_nvmf_transport *transport;
|
struct spdk_nvmf_transport *transport;
|
||||||
struct spdk_nvmf_subsystem *subsystem;
|
struct spdk_nvmf_subsystem *subsystem;
|
||||||
struct rpc_listen_address address;
|
struct rpc_listen_address address;
|
||||||
|
char *ana_state_str;
|
||||||
|
enum spdk_nvme_ana_state ana_state;
|
||||||
|
|
||||||
struct spdk_jsonrpc_request *request;
|
struct spdk_jsonrpc_request *request;
|
||||||
struct spdk_nvme_transport_id trid;
|
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->nqn);
|
||||||
free(ctx->tgt_name);
|
free(ctx->tgt_name);
|
||||||
free_rpc_listen_address(&ctx->address);
|
free_rpc_listen_address(&ctx->address);
|
||||||
|
free(ctx->ana_state_str);
|
||||||
free(ctx);
|
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 (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
||||||
if (!ctx->response_sent) {
|
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);
|
nvmf_rpc_listener_ctx_free(ctx);
|
||||||
/* Can't really do anything to recover here - subsystem will remain paused. */
|
/* 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;
|
struct nvmf_rpc_listener_ctx *ctx = cb_arg;
|
||||||
|
|
||||||
if (status) {
|
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,
|
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;
|
ctx->response_sent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
||||||
if (!ctx->response_sent) {
|
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);
|
nvmf_rpc_listener_ctx_free(ctx);
|
||||||
/* Can't really do anything to recover here - subsystem will remain paused. */
|
/* 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,
|
spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, nvmf_rpc_stop_listen_async_done,
|
||||||
ctx);
|
ctx);
|
||||||
return;
|
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 {
|
} else {
|
||||||
SPDK_UNREACHABLE();
|
SPDK_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) {
|
||||||
if (!ctx->response_sent) {
|
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);
|
nvmf_rpc_listener_ctx_free(ctx);
|
||||||
/* Can't really do anything to recover here - subsystem will remain paused. */
|
/* 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_REGISTER("nvmf_subsystem_remove_listener", rpc_nvmf_subsystem_remove_listener,
|
||||||
SPDK_RPC_RUNTIME);
|
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 {
|
struct spdk_nvmf_ns_params {
|
||||||
char *bdev_name;
|
char *bdev_name;
|
||||||
char *ptpl_file;
|
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.add_argument('-s', '--trsvcid', help='NVMe-oF transport service id: e.g., a port number')
|
||||||
p.set_defaults(func=nvmf_subsystem_remove_listener)
|
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):
|
def nvmf_subsystem_add_ns(args):
|
||||||
rpc.nvmf.nvmf_subsystem_add_ns(args.client,
|
rpc.nvmf.nvmf_subsystem_add_ns(args.client,
|
||||||
nqn=args.nqn,
|
nqn=args.nqn,
|
||||||
|
@ -330,6 +330,46 @@ def nvmf_subsystem_remove_listener(
|
|||||||
return client.call('nvmf_subsystem_remove_listener', params)
|
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):
|
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.
|
"""Add a namespace to a subsystem.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user