rpc/nvmf: add tgt_name options to relevant RPCs.

All of the RPCs in lib/nvmf/nvmf_rpc.c rely on knowing which nvmf_tgt
they should work with. They have historically relied on the assumption
that there will only be a single target in a given application. This is
true for the example application in the spdk repo, but it is not
necessarily true generally,

By adding an option tgt_name parameter to the RPCs we enable them for
multi-target NVMe-oF applications. We also further reduce the coupling
between the library and the example application.

Change-Id: I03b6695da05a42af3024842ed87d2ce2c296f33f
Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465442
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
This commit is contained in:
Seth Howell 2019-08-16 08:53:48 -07:00 committed by Jim Harris
parent a54a6a266c
commit f8433aad23
5 changed files with 244 additions and 57 deletions

View File

@ -13,6 +13,9 @@ retrieve a pointer to an `spdk_nvmf_tgt` object by supplying its name. In the sp
case where an RPC or application only creates a single target, this function can accept
a null name parameter and will return the only available target.
The majority of the NVMe-oF RPCs now accept an optional tgt_name parameter. This will
allow those RPCs to work with applications that create more than one target.
### nvme
Added `no_shn_notification` to NVMe controller initialization options, users can enable

View File

@ -3648,6 +3648,7 @@ Initialize an NVMe-oF transport with the given options.
Name | Optional | Type | Description
--------------------------- | -------- | --------| -----------
trtype | Required | string | Transport type (ex. RDMA)
tgt_name | Optional | string | Parent NVMe-oF target name.
max_queue_depth | Optional | number | Max number of outstanding I/O per queue
max_qpairs_per_ctrlr | Optional | number | Max number of SQ and CQ per controller
in_capsule_data_size | Optional | number | Max number of in-capsule data size
@ -3692,7 +3693,9 @@ Example response:
### Parameters
This method has no parameters.
Name | Optional | Type | Description
--------------------------- | -------- | ------------| -----------
tgt_name | Optional | string | Parent NVMe-oF target name.
### Example
@ -3755,6 +3758,7 @@ Construct an NVMe over Fabrics target subsystem.
Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN
tgt_name | Optional | string | Parent NVMe-oF target name.
serial_number | Optional | string | Serial number of virtual controller
model_number | Optional | string | Model number of virtual controller
max_namespaces | Optional | number | Maximum number of namespaces that can be attached to the subsystem. Default: 0 (Unlimited)
@ -3797,6 +3801,7 @@ Delete an existing NVMe-oF subsystem.
Parameter | Optional | Type | Description
---------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN to delete.
tgt_name | Optional | string | Parent NVMe-oF target name.
### Example
@ -3832,6 +3837,7 @@ Add a new listen address to an NVMe-oF subsystem.
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
### listen_address {#rpc_nvmf_listen_address}
@ -3884,6 +3890,7 @@ Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN
namespace | Required | object | @ref rpc_nvmf_namespace object
tgt_name | Optional | string | Parent NVMe-oF target name.
### namespace {#rpc_nvmf_namespace}
@ -3936,6 +3943,7 @@ Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN
nsid | Required | number | Namespace ID
tgt_name | Optional | string | Parent NVMe-oF target name.
### Example
@ -3973,6 +3981,7 @@ Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN
host | Required | string | Host NQN to add to the list of allowed host NQNs
tgt_name | Optional | string | Parent NVMe-oF target name.
### Example
@ -4010,6 +4019,7 @@ Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN
host | Required | string | Host NQN to remove from the list of allowed host NQNs
tgt_name | Optional | string | Parent NVMe-oF target name.
### Example
@ -4047,6 +4057,7 @@ Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN
allow_any_host | Required | boolean | Allow any host (`true`) or enforce allowed host whitelist (`false`).
tgt_name | Optional | string | Parent NVMe-oF target name.
### Example
@ -4150,7 +4161,9 @@ Example response:
### Parameters
This method has no parameters.
Name | Optional | Type | Description
--------------------------- | -------- | ------------| -----------
tgt_name | Optional | string | Parent NVMe-oF target name.
### Example
@ -4189,7 +4202,9 @@ Retrieve current statistics of the NVMf subsystem.
### Parameters
This method has no parameters.
Name | Optional | Type | Description
--------------------------- | -------- | ------------| -----------
tgt_name | Optional | string | Parent NVMe-oF target name.
### Response

View File

@ -182,6 +182,14 @@ decode_ns_uuid(const struct spdk_json_val *val, void *out)
return rc;
}
struct rpc_get_subsystem {
char *tgt_name;
};
static const struct spdk_json_object_decoder rpc_get_subsystem_decoders[] = {
{"tgt_name", offsetof(struct rpc_get_subsystem, tgt_name), spdk_json_decode_string, true},
};
static void
dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *subsystem)
{
@ -294,20 +302,26 @@ static void
spdk_rpc_get_nvmf_subsystems(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_get_subsystem req = { 0 };
struct spdk_json_write_ctx *w;
struct spdk_nvmf_subsystem *subsystem;
struct spdk_nvmf_tgt *tgt;
if (params != NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"get_nvmf_subsystems requires no parameters");
return;
if (params) {
if (spdk_json_decode_object(params, rpc_get_subsystem_decoders,
SPDK_COUNTOF(rpc_get_subsystem_decoders),
&req)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
return;
}
}
tgt = spdk_nvmf_get_tgt(NULL);
tgt = spdk_nvmf_get_tgt(req.tgt_name);
if (!tgt) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"Unable to find a target.");
free(req.tgt_name);
return;
}
@ -320,6 +334,7 @@ spdk_rpc_get_nvmf_subsystems(struct spdk_jsonrpc_request *request,
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(request, w);
free(req.tgt_name);
}
SPDK_RPC_REGISTER("get_nvmf_subsystems", spdk_rpc_get_nvmf_subsystems, SPDK_RPC_RUNTIME)
@ -327,6 +342,7 @@ struct rpc_subsystem_create {
char *nqn;
char *serial_number;
char *model_number;
char *tgt_name;
uint32_t max_namespaces;
bool allow_any_host;
};
@ -335,6 +351,7 @@ static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = {
{"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string},
{"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true},
{"model_number", offsetof(struct rpc_subsystem_create, model_number), spdk_json_decode_string, true},
{"tgt_name", offsetof(struct rpc_subsystem_create, tgt_name), spdk_json_decode_string, true},
{"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true},
{"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true},
};
@ -371,7 +388,7 @@ spdk_rpc_nvmf_subsystem_create(struct spdk_jsonrpc_request *request,
goto invalid;
}
tgt = spdk_nvmf_get_tgt(NULL);
tgt = spdk_nvmf_get_tgt(req->tgt_name);
if (!tgt) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"Unable to find a target.");
@ -401,6 +418,7 @@ spdk_rpc_nvmf_subsystem_create(struct spdk_jsonrpc_request *request,
spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host);
free(req->nqn);
free(req->tgt_name);
free(req->serial_number);
free(req->model_number);
free(req);
@ -416,6 +434,7 @@ invalid:
invalid_custom_response:
if (req) {
free(req->nqn);
free(req->tgt_name);
free(req->serial_number);
free(req->model_number);
}
@ -425,12 +444,14 @@ SPDK_RPC_REGISTER("nvmf_subsystem_create", spdk_rpc_nvmf_subsystem_create, SPDK_
struct rpc_delete_subsystem {
char *nqn;
char *tgt_name;
};
static void
free_rpc_delete_subsystem(struct rpc_delete_subsystem *r)
{
free(r->nqn);
free(r->tgt_name);
}
static void
@ -449,13 +470,14 @@ spdk_rpc_nvmf_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem,
static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = {
{"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string},
{"tgt_name", offsetof(struct rpc_delete_subsystem, tgt_name), spdk_json_decode_string, true},
};
static void
spdk_rpc_delete_nvmf_subsystem(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_delete_subsystem req = {};
struct rpc_delete_subsystem req = { 0 };
struct spdk_nvmf_subsystem *subsystem;
struct spdk_nvmf_tgt *tgt;
@ -471,7 +493,7 @@ spdk_rpc_delete_nvmf_subsystem(struct spdk_jsonrpc_request *request,
goto invalid;
}
tgt = spdk_nvmf_get_tgt(NULL);
tgt = spdk_nvmf_get_tgt(req.tgt_name);
if (!tgt) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"Unable to find a target.");
@ -551,6 +573,7 @@ enum nvmf_rpc_listen_op {
struct nvmf_rpc_listener_ctx {
char *nqn;
char *tgt_name;
struct spdk_nvmf_tgt *tgt;
struct spdk_nvmf_subsystem *subsystem;
struct rpc_listen_address address;
@ -564,12 +587,14 @@ struct nvmf_rpc_listener_ctx {
static const struct spdk_json_object_decoder nvmf_rpc_listener_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},
{"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true},
};
static void
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);
}
@ -719,7 +744,7 @@ spdk_rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request,
return;
}
tgt = spdk_nvmf_get_tgt(NULL);
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,
@ -782,7 +807,7 @@ spdk_rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
return;
}
tgt = spdk_nvmf_get_tgt(NULL);
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,
@ -857,6 +882,7 @@ decode_rpc_ns_params(const struct spdk_json_val *val, void *out)
struct nvmf_rpc_ns_ctx {
char *nqn;
char *tgt_name;
struct spdk_nvmf_ns_params ns_params;
struct spdk_jsonrpc_request *request;
@ -866,12 +892,14 @@ struct nvmf_rpc_ns_ctx {
static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = {
{"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string},
{"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params},
{"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true},
};
static void
nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx)
{
free(ctx->nqn);
free(ctx->tgt_name);
free(ctx->ns_params.bdev_name);
free(ctx->ns_params.ptpl_file);
free(ctx);
@ -972,7 +1000,7 @@ spdk_rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request,
ctx->request = request;
ctx->response_sent = false;
tgt = spdk_nvmf_get_tgt(NULL);
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,
@ -999,6 +1027,7 @@ SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", spdk_rpc_nvmf_subsystem_add_ns, SPDK_
struct nvmf_rpc_remove_ns_ctx {
char *nqn;
char *tgt_name;
uint32_t nsid;
struct spdk_jsonrpc_request *request;
@ -1008,12 +1037,14 @@ struct nvmf_rpc_remove_ns_ctx {
static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = {
{"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string},
{"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32},
{"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true},
};
static void
nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx)
{
free(ctx->nqn);
free(ctx->tgt_name);
free(ctx);
}
@ -1084,7 +1115,7 @@ spdk_rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request,
return;
}
tgt = spdk_nvmf_get_tgt(NULL);
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,
@ -1123,6 +1154,7 @@ struct nvmf_rpc_host_ctx {
char *nqn;
char *host;
char *tgt_name;
enum nvmf_rpc_host_op op;
@ -1134,6 +1166,7 @@ struct nvmf_rpc_host_ctx {
static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = {
{"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
{"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string},
{"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true},
};
static void
@ -1141,6 +1174,7 @@ nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx)
{
free(ctx->nqn);
free(ctx->host);
free(ctx->tgt_name);
free(ctx);
}
@ -1221,7 +1255,7 @@ spdk_rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request,
return;
}
tgt = spdk_nvmf_get_tgt(NULL);
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,
@ -1273,7 +1307,7 @@ spdk_rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request,
return;
}
tgt = spdk_nvmf_get_tgt(NULL);
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,
@ -1307,6 +1341,7 @@ SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", spdk_rpc_nvmf_subsystem_remove_h
static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = {
{"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
{"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool},
{"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true},
};
static void
@ -1332,7 +1367,7 @@ spdk_rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request,
return;
}
tgt = spdk_nvmf_get_tgt(NULL);
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,
@ -1364,7 +1399,8 @@ SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", spdk_rpc_nvmf_subsystem_allow
struct nvmf_rpc_create_transport_ctx {
char *trtype;
struct spdk_nvmf_transport_opts opts;
char *tgt_name;
struct spdk_nvmf_transport_opts opts;
struct spdk_jsonrpc_request *request;
};
@ -1422,12 +1458,17 @@ static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[]
"sock_priority", offsetof(struct nvmf_rpc_create_transport_ctx, opts.sock_priority),
spdk_json_decode_uint32, true
},
{
"tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name),
spdk_json_decode_string, true
},
};
static void
nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx)
{
free(ctx->trtype);
free(ctx->tgt_name);
free(ctx);
}
@ -1479,7 +1520,7 @@ spdk_rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request,
return;
}
tgt = spdk_nvmf_get_tgt(NULL);
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,
@ -1573,24 +1614,38 @@ dump_nvmf_transport(struct spdk_json_write_ctx *w, struct spdk_nvmf_transport *t
spdk_json_write_object_end(w);
}
struct rpc_get_transport {
char *tgt_name;
};
static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = {
{"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true},
};
static void
spdk_rpc_get_nvmf_transports(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_get_transport req = { 0 };
struct spdk_json_write_ctx *w;
struct spdk_nvmf_transport *transport;
struct spdk_nvmf_tgt *tgt;
if (params != NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"get_nvmf_transports requires no parameters");
return;
if (params) {
if (spdk_json_decode_object(params, rpc_get_transport_decoders,
SPDK_COUNTOF(rpc_get_transport_decoders),
&req)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
return;
}
}
tgt = spdk_nvmf_get_tgt(NULL);
tgt = spdk_nvmf_get_tgt(req.tgt_name);
if (!tgt) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"Unable to find a target.");
free(req.tgt_name);
return;
}
@ -1603,15 +1658,28 @@ spdk_rpc_get_nvmf_transports(struct spdk_jsonrpc_request *request,
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(request, w);
free(req.tgt_name);
}
SPDK_RPC_REGISTER("get_nvmf_transports", spdk_rpc_get_nvmf_transports, SPDK_RPC_RUNTIME)
struct rpc_nvmf_get_stats_ctx {
char *tgt_name;
struct spdk_nvmf_tgt *tgt;
struct spdk_jsonrpc_request *request;
struct spdk_json_write_ctx *w;
};
static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = {
{"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true},
};
static void
free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx)
{
free(ctx->tgt_name);
free(ctx);
}
static void
rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status)
{
@ -1620,7 +1688,7 @@ rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status)
spdk_json_write_array_end(ctx->w);
spdk_json_write_object_end(ctx->w);
spdk_jsonrpc_end_result(ctx->request, ctx->w);
free(ctx);
free_get_stats_ctx(ctx);
}
static void
@ -1705,12 +1773,6 @@ spdk_rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request,
{
struct rpc_nvmf_get_stats_ctx *ctx;
if (params) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"'nvmf_get_stats' requires no arguments");
return;
}
ctx = calloc(1, sizeof(*ctx));
if (!ctx) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
@ -1719,17 +1781,28 @@ spdk_rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request,
}
ctx->request = request;
ctx->tgt = spdk_nvmf_get_tgt(NULL);
if (params) {
if (spdk_json_decode_object(params, rpc_get_stats_decoders,
SPDK_COUNTOF(rpc_get_stats_decoders),
ctx)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
free_get_stats_ctx(ctx);
return;
}
}
ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
if (!ctx->tgt) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"Unable to find a target.");
free(ctx);
free_get_stats_ctx(ctx);
return;
}
ctx->w = spdk_jsonrpc_begin_result(ctx->request);
if (NULL == ctx->w) {
free(ctx);
free_get_stats_ctx(ctx);
return;
}

View File

@ -1462,6 +1462,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
def nvmf_create_transport(args):
rpc.nvmf.nvmf_create_transport(args.client,
trtype=args.trtype,
tgt_name=args.tgt_name,
max_queue_depth=args.max_queue_depth,
max_qpairs_per_ctrlr=args.max_qpairs_per_ctrlr,
in_capsule_data_size=args.in_capsule_data_size,
@ -1478,6 +1479,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p = subparsers.add_parser('nvmf_create_transport', help='Create NVMf transport')
p.add_argument('-t', '--trtype', help='Transport type (ex. RDMA)', type=str, required=True)
p.add_argument('-g', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.add_argument('-q', '--max-queue-depth', help='Max number of outstanding I/O per queue', type=int)
p.add_argument('-p', '--max-qpairs-per-ctrlr', help='Max number of SQ and CQ per controller', type=int)
p.add_argument('-c', '--in-capsule-data-size', help='Max number of in-capsule data size', type=int)
@ -1494,22 +1496,25 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p.set_defaults(func=nvmf_create_transport)
def get_nvmf_transports(args):
print_dict(rpc.nvmf.get_nvmf_transports(args.client))
print_dict(rpc.nvmf.get_nvmf_transports(args.client, tgt_name=args.tgt_name))
p = subparsers.add_parser('get_nvmf_transports',
help='Display nvmf transports')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=get_nvmf_transports)
def get_nvmf_subsystems(args):
print_dict(rpc.nvmf.get_nvmf_subsystems(args.client))
print_dict(rpc.nvmf.get_nvmf_subsystems(args.client, tgt_name=args.tgt_name))
p = subparsers.add_parser('get_nvmf_subsystems',
help='Display nvmf subsystems')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=get_nvmf_subsystems)
def nvmf_subsystem_create(args):
rpc.nvmf.nvmf_subsystem_create(args.client,
nqn=args.nqn,
tgt_name=args.tgt_name,
serial_number=args.serial_number,
model_number=args.model_number,
allow_any_host=args.allow_any_host,
@ -1517,6 +1522,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p = subparsers.add_parser('nvmf_subsystem_create', help='Create an NVMe-oF subsystem')
p.add_argument('nqn', help='Subsystem NQN (ASCII)')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.add_argument("-s", "--serial-number", help="""
Format: 'sn' etc
Example: 'SPDK00000000000001'""", default='00000000000000000000')
@ -1530,12 +1536,14 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
def delete_nvmf_subsystem(args):
rpc.nvmf.delete_nvmf_subsystem(args.client,
nqn=args.subsystem_nqn)
nqn=args.subsystem_nqn,
tgt_name=args.tgt_name)
p = subparsers.add_parser('delete_nvmf_subsystem',
help='Delete a nvmf subsystem')
p.add_argument('subsystem_nqn',
help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=delete_nvmf_subsystem)
def nvmf_subsystem_add_listener(args):
@ -1543,6 +1551,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
nqn=args.nqn,
trtype=args.trtype,
traddr=args.traddr,
tgt_name=args.tgt_name,
adrfam=args.adrfam,
trsvcid=args.trsvcid)
@ -1550,6 +1559,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
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_add_listener)
@ -1559,6 +1569,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
nqn=args.nqn,
trtype=args.trtype,
traddr=args.traddr,
tgt_name=args.tgt_name,
adrfam=args.adrfam,
trsvcid=args.trsvcid)
@ -1566,6 +1577,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
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_remove_listener)
@ -1574,6 +1586,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
rpc.nvmf.nvmf_subsystem_add_ns(args.client,
nqn=args.nqn,
bdev_name=args.bdev_name,
tgt_name=args.tgt_name,
ptpl_file=args.ptpl_file,
nsid=args.nsid,
nguid=args.nguid,
@ -1583,6 +1596,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p = subparsers.add_parser('nvmf_subsystem_add_ns', help='Add a namespace to an NVMe-oF subsystem')
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
p.add_argument('bdev_name', help='The name of the bdev that will back this namespace')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.add_argument('-p', '--ptpl-file', help='The persistent reservation storage location (optional)', type=str)
p.add_argument('-n', '--nsid', help='The requested NSID (optional)', type=int)
p.add_argument('-g', '--nguid', help='Namespace globally unique identifier (optional)')
@ -1593,49 +1607,58 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
def nvmf_subsystem_remove_ns(args):
rpc.nvmf.nvmf_subsystem_remove_ns(args.client,
nqn=args.nqn,
nsid=args.nsid)
nsid=args.nsid,
tgt_name=args.tgt_name)
p = subparsers.add_parser('nvmf_subsystem_remove_ns', help='Remove a namespace to an NVMe-oF subsystem')
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
p.add_argument('nsid', help='The requested NSID', type=int)
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=nvmf_subsystem_remove_ns)
def nvmf_subsystem_add_host(args):
rpc.nvmf.nvmf_subsystem_add_host(args.client,
nqn=args.nqn,
host=args.host)
host=args.host,
tgt_name=args.tgt_name)
p = subparsers.add_parser('nvmf_subsystem_add_host', help='Add a host to an NVMe-oF subsystem')
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
p.add_argument('host', help='Host NQN to allow')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=nvmf_subsystem_add_host)
def nvmf_subsystem_remove_host(args):
rpc.nvmf.nvmf_subsystem_remove_host(args.client,
nqn=args.nqn,
host=args.host)
host=args.host,
tgt_name=args.tgt_name)
p = subparsers.add_parser('nvmf_subsystem_remove_host', help='Remove a host from an NVMe-oF subsystem')
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
p.add_argument('host', help='Host NQN to remove')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=nvmf_subsystem_remove_host)
def nvmf_subsystem_allow_any_host(args):
rpc.nvmf.nvmf_subsystem_allow_any_host(args.client,
nqn=args.nqn,
disable=args.disable)
disable=args.disable,
tgt_name=args.tgt_name)
p = subparsers.add_parser('nvmf_subsystem_allow_any_host', help='Allow any host to connect to the subsystem')
p.add_argument('nqn', help='NVMe-oF subsystem NQN')
p.add_argument('-e', '--enable', action='store_true', help='Enable allowing any host')
p.add_argument('-d', '--disable', action='store_true', help='Disable allowing any host')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=nvmf_subsystem_allow_any_host)
def nvmf_get_stats(args):
print_dict(rpc.nvmf.nvmf_get_stats(args.client))
print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name))
p = subparsers.add_parser(
'nvmf_get_stats', help='Display current statistics for NVMf subsystem')
p.add_argument('-t', '--tgt_name', help='The name of the parent NVMe-oF target (optional)', type=str)
p.set_defaults(func=nvmf_get_stats)
# pmem

View File

@ -37,6 +37,7 @@ def set_nvmf_target_config(client,
def nvmf_create_transport(client,
trtype,
tgt_name=None,
max_queue_depth=None,
max_qpairs_per_ctrlr=None,
in_capsule_data_size=None,
@ -73,6 +74,8 @@ def nvmf_create_transport(client,
params = {}
params['trtype'] = trtype
if tgt_name:
params['tgt_name'] = tgt_name
if max_queue_depth:
params['max_queue_depth'] = max_queue_depth
if max_qpairs_per_ctrlr:
@ -102,27 +105,48 @@ def nvmf_create_transport(client,
return client.call('nvmf_create_transport', params)
def get_nvmf_transports(client):
def get_nvmf_transports(client, tgt_name=None):
"""Get list of NVMe-oF transports.
Args:
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
List of NVMe-oF transport objects.
"""
return client.call('get_nvmf_transports')
params = {}
if tgt_name:
params = {
'tgt_name': tgt_name,
}
return client.call('get_nvmf_transports', params)
def get_nvmf_subsystems(client):
def get_nvmf_subsystems(client, tgt_name=None):
"""Get list of NVMe-oF subsystems.
Args:
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
List of NVMe-oF subsystem objects.
"""
return client.call('get_nvmf_subsystems')
params = {}
if tgt_name:
params = {
'tgt_name': tgt_name,
}
return client.call('get_nvmf_subsystems', params)
def nvmf_subsystem_create(client,
nqn,
serial_number,
tgt_name=None,
model_number='SPDK bdev Controller',
allow_any_host=False,
max_namespaces=0):
@ -130,6 +154,7 @@ def nvmf_subsystem_create(client,
Args:
nqn: Subsystem NQN.
tgt_name: name of the parent NVMe-oF target (optional).
serial_number: Serial number of virtual controller.
model_number: Model number of virtual controller.
allow_any_host: Allow any host (True) or enforce allowed host whitelist (False). Default: False.
@ -154,10 +179,13 @@ def nvmf_subsystem_create(client,
if max_namespaces:
params['max_namespaces'] = max_namespaces
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_create', params)
def nvmf_subsystem_add_listener(client, nqn, trtype, traddr, trsvcid, adrfam):
def nvmf_subsystem_add_listener(client, nqn, trtype, traddr, trsvcid, adrfam, tgt_name=None):
"""Add a new listen address to an NVMe-oF subsystem.
Args:
@ -165,6 +193,7 @@ def nvmf_subsystem_add_listener(client, nqn, trtype, traddr, trsvcid, adrfam):
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:
@ -180,6 +209,9 @@ def nvmf_subsystem_add_listener(client, nqn, trtype, traddr, trsvcid, adrfam):
params = {'nqn': nqn,
'listen_address': listen_address}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_add_listener', params)
@ -189,7 +221,8 @@ def nvmf_subsystem_remove_listener(
trtype,
traddr,
trsvcid,
adrfam):
adrfam,
tgt_name=None):
"""Remove existing listen address from an NVMe-oF subsystem.
Args:
@ -197,6 +230,7 @@ def nvmf_subsystem_remove_listener(
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:
@ -212,15 +246,19 @@ def nvmf_subsystem_remove_listener(
params = {'nqn': nqn,
'listen_address': listen_address}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_remove_listener', params)
def nvmf_subsystem_add_ns(client, nqn, bdev_name, 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.
Args:
nqn: Subsystem NQN.
bdev_name: Name of bdev to expose as a namespace.
tgt_name: name of the parent NVMe-oF target (optional).
nsid: Namespace ID (optional).
nguid: 16-byte namespace globally unique identifier in hexadecimal (optional).
eui64: 8-byte namespace EUI-64 in hexadecimal (e.g. "ABCDEF0123456789") (optional).
@ -249,15 +287,19 @@ def nvmf_subsystem_add_ns(client, nqn, bdev_name, ptpl_file=None, nsid=None, ngu
params = {'nqn': nqn,
'namespace': ns}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_add_ns', params)
def nvmf_subsystem_remove_ns(client, nqn, nsid):
def nvmf_subsystem_remove_ns(client, nqn, nsid, tgt_name=None):
"""Remove a existing namespace from a subsystem.
Args:
nqn: Subsystem NQN.
nsid: Namespace ID.
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
True or False
@ -265,15 +307,19 @@ def nvmf_subsystem_remove_ns(client, nqn, nsid):
params = {'nqn': nqn,
'nsid': nsid}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_remove_ns', params)
def nvmf_subsystem_add_host(client, nqn, host):
def nvmf_subsystem_add_host(client, nqn, host, tgt_name=None):
"""Add a host NQN to the whitelist of allowed hosts.
Args:
nqn: Subsystem NQN.
host: Host NQN to add to the list of allowed host NQNs
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
True or False
@ -281,15 +327,19 @@ def nvmf_subsystem_add_host(client, nqn, host):
params = {'nqn': nqn,
'host': host}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_add_host', params)
def nvmf_subsystem_remove_host(client, nqn, host):
def nvmf_subsystem_remove_host(client, nqn, host, tgt_name=None):
"""Remove a host NQN from the whitelist of allowed hosts.
Args:
nqn: Subsystem NQN.
host: Host NQN to remove to the list of allowed host NQNs
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
True or False
@ -297,41 +347,64 @@ def nvmf_subsystem_remove_host(client, nqn, host):
params = {'nqn': nqn,
'host': host}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_remove_host', params)
def nvmf_subsystem_allow_any_host(client, nqn, disable):
def nvmf_subsystem_allow_any_host(client, nqn, disable, tgt_name=None):
"""Configure a subsystem to allow any host to connect or to enforce the host NQN whitelist.
Args:
nqn: Subsystem NQN.
disable: Allow any host (true) or enforce allowed host whitelist (false).
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
True or False
"""
params = {'nqn': nqn, 'allow_any_host': False if disable else True}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('nvmf_subsystem_allow_any_host', params)
def delete_nvmf_subsystem(client, nqn):
def delete_nvmf_subsystem(client, nqn, tgt_name=None):
"""Delete an existing NVMe-oF subsystem.
Args:
nqn: Subsystem NQN.
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
True or False
"""
params = {'nqn': nqn}
if tgt_name:
params['tgt_name'] = tgt_name
return client.call('delete_nvmf_subsystem', params)
def nvmf_get_stats(client):
def nvmf_get_stats(client, tgt_name=None):
"""Query NVMf statistics.
Args:
tgt_name: name of the parent NVMe-oF target (optional).
Returns:
Current NVMf statistics.
"""
return client.call('nvmf_get_stats')
params = {}
if tgt_name:
params = {
'tgt_name': tgt_name,
}
return client.call('nvmf_get_stats', params)