nvmf: Place deprecated RPCs in a separate file
This is code movement only. The deprecated RPCs are actually quite complicated and are making the RPC file much larger than it needed to be. Move the old code to a separate file until it is eventually removed. Change-Id: I7c9bcdb0faa8496ef611d787dcc9a35c82dcc61a Signed-off-by: Ben Walker <benjamin.walker@intel.com> Reviewed-on: https://review.gerrithub.io/425178 Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
aedac1a878
commit
b67d175529
101
doc/jsonrpc.md
101
doc/jsonrpc.md
@ -2941,84 +2941,6 @@ Example response:
|
||||
}
|
||||
~~~
|
||||
|
||||
## construct_nvmf_subsystem method {#rpc_construct_nvmf_subsystem}
|
||||
|
||||
Construct an NVMe over Fabrics target subsystem.
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
nqn | Required | string | Subsystem NQN
|
||||
listen_addresses | Optional | array | Array of @ref rpc_construct_nvmf_subsystem_listen_address objects
|
||||
hosts | Optional | array | Array of strings containing allowed host NQNs. Default: No hosts allowed.
|
||||
allow_any_host | Optional | boolean | Allow any host (`true`) or enforce allowed host whitelist (`false`). Default: `false`.
|
||||
serial_number | Required | string | Serial number of virtual controller
|
||||
namespaces | Optional | array | Array of @ref rpc_construct_nvmf_subsystem_namespace objects. Default: No namespaces.
|
||||
max_namespaces | Optional | number | Maximum number of namespaces that can be attached to the subsystem. Default: 0 (Unlimited)
|
||||
|
||||
### listen_address {#rpc_construct_nvmf_subsystem_listen_address}
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
trtype | Required | string | Transport type ("RDMA")
|
||||
adrfam | Required | string | Address family ("IPv4", "IPv6", "IB", or "FC")
|
||||
traddr | Required | string | Transport address
|
||||
trsvcid | Required | string | Transport service ID
|
||||
|
||||
### namespace {#rpc_construct_nvmf_subsystem_namespace}
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
nsid | Optional | number | Namespace ID between 1 and 4294967294, inclusive. Default: Automatically assign NSID.
|
||||
bdev_name | Required | string | Name of bdev to expose as a namespace.
|
||||
nguid | Optional | string | 16-byte namespace globally unique identifier in hexadecimal (e.g. "ABCDEF0123456789ABCDEF0123456789")
|
||||
eui64 | Optional | string | 8-byte namespace EUI-64 in hexadecimal (e.g. "ABCDEF0123456789")
|
||||
uuid | Optional | string | RFC 4122 UUID (e.g. "ceccf520-691e-4b46-9546-34af789907c5")
|
||||
|
||||
### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "construct_nvmf_subsystem",
|
||||
"params": {
|
||||
"nqn": "nqn.2016-06.io.spdk:cnode1",
|
||||
"listen_addresses": [
|
||||
{
|
||||
"trtype": "RDMA",
|
||||
"adrfam": "IPv4",
|
||||
"traddr": "192.168.0.123",
|
||||
"trsvcid: "4420"
|
||||
}
|
||||
],
|
||||
"hosts": [
|
||||
"nqn.2016-06.io.spdk:host1",
|
||||
"nqn.2016-06.io.spdk:host2"
|
||||
],
|
||||
"allow_any_host": false,
|
||||
"serial_number": "abcdef",
|
||||
"namespaces": [
|
||||
{"nsid": 1, "bdev_name": "Malloc2"},
|
||||
{"nsid": 2, "bdev_name": "Nvme0n1"}
|
||||
]
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
## nvmf_subsystem_create method {#rpc_nvmf_subsystem_create}
|
||||
|
||||
Construct an NVMe over Fabrics target subsystem.
|
||||
@ -3103,7 +3025,16 @@ Add a new listen address to an NVMe-oF subsystem.
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
nqn | Required | string | Subsystem NQN
|
||||
listen_address | Required | object | @ref rpc_construct_nvmf_subsystem_listen_address object
|
||||
listen_address | Required | object | @ref rpc_nvmf_listen_address object
|
||||
|
||||
### listen_address {#rpc_nvmf_listen_address}
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
trtype | Required | string | Transport type ("RDMA")
|
||||
adrfam | Required | string | Address family ("IPv4", "IPv6", "IB", or "FC")
|
||||
traddr | Required | string | Transport address
|
||||
trsvcid | Required | string | Transport service ID
|
||||
|
||||
### Example
|
||||
|
||||
@ -3145,7 +3076,17 @@ Add a namespace to a subsystem. The namespace ID is returned as the result.
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
nqn | Required | string | Subsystem NQN
|
||||
namespace | Required | object | @ref rpc_construct_nvmf_subsystem_namespace object
|
||||
namespace | Required | object | @ref rpc_nvmf_namespace object
|
||||
|
||||
### namespace {#rpc_nvmf_namespace}
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
nsid | Optional | number | Namespace ID between 1 and 4294967294, inclusive. Default: Automatically assign NSID.
|
||||
bdev_name | Required | string | Name of bdev to expose as a namespace.
|
||||
nguid | Optional | string | 16-byte namespace globally unique identifier in hexadecimal (e.g. "ABCDEF0123456789ABCDEF0123456789")
|
||||
eui64 | Optional | string | 8-byte namespace EUI-64 in hexadecimal (e.g. "ABCDEF0123456789")
|
||||
uuid | Optional | string | RFC 4122 UUID (e.g. "ceccf520-691e-4b46-9546-34af789907c5")
|
||||
|
||||
### Example
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
C_SRCS = conf.c nvmf_rpc.c nvmf_tgt.c
|
||||
C_SRCS = conf.c nvmf_rpc.c nvmf_rpc_deprecated.c nvmf_tgt.c
|
||||
LIBNAME = event_nvmf
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
|
||||
|
@ -329,249 +329,19 @@ spdk_rpc_get_nvmf_subsystems(struct spdk_jsonrpc_request *request,
|
||||
}
|
||||
SPDK_RPC_REGISTER("get_nvmf_subsystems", spdk_rpc_get_nvmf_subsystems, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_listen_address {
|
||||
char *transport;
|
||||
char *adrfam;
|
||||
char *traddr;
|
||||
char *trsvcid;
|
||||
};
|
||||
|
||||
#define RPC_MAX_LISTEN_ADDRESSES 255
|
||||
#define RPC_MAX_HOSTS 255
|
||||
#define RPC_MAX_NAMESPACES 255
|
||||
|
||||
struct rpc_listen_addresses {
|
||||
size_t num_listen_address;
|
||||
struct rpc_listen_address addresses[RPC_MAX_LISTEN_ADDRESSES];
|
||||
};
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = {
|
||||
/* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
|
||||
{"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
|
||||
{"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
|
||||
{"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true},
|
||||
{"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string},
|
||||
{"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static int
|
||||
decode_rpc_listen_address(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_listen_address *req = (struct rpc_listen_address *)out;
|
||||
if (spdk_json_decode_object(val, rpc_listen_address_decoders,
|
||||
SPDK_COUNTOF(rpc_listen_address_decoders),
|
||||
req)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_listen_address(struct rpc_listen_address *r)
|
||||
{
|
||||
free(r->transport);
|
||||
free(r->adrfam);
|
||||
free(r->traddr);
|
||||
free(r->trsvcid);
|
||||
}
|
||||
|
||||
static int
|
||||
rpc_listen_address_to_trid(const struct rpc_listen_address *address,
|
||||
struct spdk_nvme_transport_id *trid)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
memset(trid, 0, sizeof(*trid));
|
||||
|
||||
if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) {
|
||||
SPDK_ERRLOG("Invalid transport type: %s\n", address->transport);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (address->adrfam) {
|
||||
if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) {
|
||||
SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
trid->adrfam = SPDK_NVMF_ADRFAM_IPV4;
|
||||
}
|
||||
|
||||
len = strlen(address->traddr);
|
||||
if (len > sizeof(trid->traddr) - 1) {
|
||||
SPDK_ERRLOG("Transport address longer than %zu characters: %s\n",
|
||||
sizeof(trid->traddr) - 1, address->traddr);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(trid->traddr, address->traddr, len + 1);
|
||||
|
||||
len = strlen(address->trsvcid);
|
||||
if (len > sizeof(trid->trsvcid) - 1) {
|
||||
SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n",
|
||||
sizeof(trid->trsvcid) - 1, address->trsvcid);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(trid->trsvcid, address->trsvcid, len + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_rpc_listen_addresses(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_listen_addresses *listen_addresses = out;
|
||||
return spdk_json_decode_array(val, decode_rpc_listen_address, &listen_addresses->addresses,
|
||||
RPC_MAX_LISTEN_ADDRESSES,
|
||||
&listen_addresses->num_listen_address, sizeof(struct rpc_listen_address));
|
||||
}
|
||||
|
||||
struct rpc_hosts {
|
||||
size_t num_hosts;
|
||||
char *hosts[RPC_MAX_HOSTS];
|
||||
};
|
||||
|
||||
static int
|
||||
decode_rpc_hosts(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_hosts *rpc_hosts = out;
|
||||
|
||||
return spdk_json_decode_array(val, spdk_json_decode_string, rpc_hosts->hosts, RPC_MAX_HOSTS,
|
||||
&rpc_hosts->num_hosts, sizeof(char *));
|
||||
}
|
||||
|
||||
|
||||
struct spdk_nvmf_ns_params {
|
||||
char *bdev_name;
|
||||
uint32_t nsid;
|
||||
char nguid[16];
|
||||
char eui64[8];
|
||||
struct spdk_uuid uuid;
|
||||
};
|
||||
|
||||
struct rpc_namespaces {
|
||||
size_t num_ns;
|
||||
struct spdk_nvmf_ns_params ns_params[RPC_MAX_NAMESPACES];
|
||||
};
|
||||
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = {
|
||||
{"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true},
|
||||
{"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string},
|
||||
{"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true},
|
||||
{"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true},
|
||||
{"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true},
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_ns_params(struct spdk_nvmf_ns_params *ns_params)
|
||||
{
|
||||
free(ns_params->bdev_name);
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_namespaces(struct rpc_namespaces *r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < r->num_ns; i++) {
|
||||
free_rpc_ns_params(&r->ns_params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
decode_rpc_ns_params(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct spdk_nvmf_ns_params *ns_params = out;
|
||||
|
||||
return spdk_json_decode_object(val, rpc_ns_params_decoders,
|
||||
SPDK_COUNTOF(rpc_ns_params_decoders),
|
||||
ns_params);
|
||||
}
|
||||
|
||||
static int
|
||||
decode_rpc_namespaces(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_namespaces *namespaces = out;
|
||||
char *names[RPC_MAX_NAMESPACES] = {0}; /* old format - array of strings (bdev names) */
|
||||
size_t i;
|
||||
int rc;
|
||||
|
||||
/* First try to decode namespaces as an array of objects (new format) */
|
||||
if (spdk_json_decode_array(val, decode_rpc_ns_params, namespaces->ns_params,
|
||||
SPDK_COUNTOF(namespaces->ns_params),
|
||||
&namespaces->num_ns, sizeof(*namespaces->ns_params)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If that fails, try to decode namespaces as an array of strings (old format) */
|
||||
free_rpc_namespaces(namespaces);
|
||||
memset(namespaces, 0, sizeof(*namespaces));
|
||||
rc = spdk_json_decode_array(val, spdk_json_decode_string, names,
|
||||
SPDK_COUNTOF(names),
|
||||
&namespaces->num_ns, sizeof(char *));
|
||||
if (rc == 0) {
|
||||
/* Decoded old format - copy to ns_params (new format) */
|
||||
for (i = 0; i < namespaces->num_ns; i++) {
|
||||
namespaces->ns_params[i].bdev_name = names[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Failed to decode - don't leave dangling string pointers around */
|
||||
for (i = 0; i < namespaces->num_ns; i++) {
|
||||
free(names[i]);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_listen_addresses(struct rpc_listen_addresses *r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < r->num_listen_address; i++) {
|
||||
free_rpc_listen_address(&r->addresses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_hosts(struct rpc_hosts *r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < r->num_hosts; i++) {
|
||||
free(r->hosts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
struct rpc_subsystem {
|
||||
int32_t core;
|
||||
char *mode;
|
||||
struct rpc_subsystem_create {
|
||||
char *nqn;
|
||||
struct rpc_listen_addresses listen_addresses;
|
||||
struct rpc_hosts hosts;
|
||||
bool allow_any_host;
|
||||
char *pci_address;
|
||||
char *serial_number;
|
||||
struct rpc_namespaces namespaces;
|
||||
uint32_t num_ns;
|
||||
uint32_t max_namespaces;
|
||||
bool allow_any_host;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_subsystem(struct rpc_subsystem *req)
|
||||
{
|
||||
if (req) {
|
||||
free(req->mode);
|
||||
free(req->nqn);
|
||||
free(req->serial_number);
|
||||
free_rpc_namespaces(&req->namespaces);
|
||||
free_rpc_listen_addresses(&req->listen_addresses);
|
||||
free_rpc_hosts(&req->hosts);
|
||||
}
|
||||
free(req);
|
||||
}
|
||||
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},
|
||||
{"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},
|
||||
};
|
||||
|
||||
static void
|
||||
spdk_rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
|
||||
@ -589,226 +359,6 @@ spdk_rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_subsystem_decoders[] = {
|
||||
{"core", offsetof(struct rpc_subsystem, core), spdk_json_decode_int32, true},
|
||||
{"mode", offsetof(struct rpc_subsystem, mode), spdk_json_decode_string, true},
|
||||
{"nqn", offsetof(struct rpc_subsystem, nqn), spdk_json_decode_string},
|
||||
{"listen_addresses", offsetof(struct rpc_subsystem, listen_addresses), decode_rpc_listen_addresses, true},
|
||||
{"hosts", offsetof(struct rpc_subsystem, hosts), decode_rpc_hosts, true},
|
||||
{"allow_any_host", offsetof(struct rpc_subsystem, allow_any_host), spdk_json_decode_bool, true},
|
||||
{"serial_number", offsetof(struct rpc_subsystem, serial_number), spdk_json_decode_string, true},
|
||||
{"namespaces", offsetof(struct rpc_subsystem, namespaces), decode_rpc_namespaces, true},
|
||||
{"max_namespaces", offsetof(struct rpc_subsystem, num_ns), spdk_json_decode_uint32, true},
|
||||
};
|
||||
|
||||
struct subsystem_listen_ctx {
|
||||
struct rpc_subsystem *req;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
struct spdk_jsonrpc_request *request;
|
||||
|
||||
uint32_t idx;
|
||||
};
|
||||
|
||||
static void
|
||||
spdk_rpc_construct_subsystem_listen_done(void *cb_arg, int status)
|
||||
{
|
||||
struct subsystem_listen_ctx *ctx = cb_arg;
|
||||
struct rpc_listen_address *addr;
|
||||
struct spdk_nvme_transport_id trid = {0};
|
||||
|
||||
if (status) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
addr = &ctx->req->listen_addresses.addresses[ctx->idx];
|
||||
if (rpc_listen_address_to_trid(addr, &trid)) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_nvmf_subsystem_add_listener(ctx->subsystem, &trid);
|
||||
|
||||
ctx->idx++;
|
||||
|
||||
if (ctx->idx < ctx->req->listen_addresses.num_listen_address) {
|
||||
addr = &ctx->req->listen_addresses.addresses[ctx->idx];
|
||||
|
||||
if (rpc_listen_address_to_trid(addr, &trid)) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_nvmf_tgt_listen(g_spdk_nvmf_tgt, &trid, spdk_rpc_construct_subsystem_listen_done, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_nvmf_subsystem_start(ctx->subsystem,
|
||||
spdk_rpc_nvmf_subsystem_started,
|
||||
ctx->request);
|
||||
|
||||
free_rpc_subsystem(ctx->req);
|
||||
free(ctx);
|
||||
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_nvmf_subsystem_destroy(ctx->subsystem);
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid parameters");
|
||||
free_rpc_subsystem(ctx->req);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_construct_nvmf_subsystem(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_subsystem *req;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
size_t i;
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
req->core = -1; /* Explicitly set the core as the uninitialized value */
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_subsystem_decoders,
|
||||
SPDK_COUNTOF(rpc_subsystem_decoders),
|
||||
req)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* Mode is no longer a valid parameter, but print out a nice
|
||||
* message if it exists to inform users.
|
||||
*/
|
||||
if (req->mode) {
|
||||
SPDK_NOTICELOG("Mode present in the construct NVMe-oF subsystem RPC.\n"
|
||||
"Mode was removed as a valid parameter.\n");
|
||||
if (strcasecmp(req->mode, "Virtual") == 0) {
|
||||
SPDK_NOTICELOG("Your mode value is 'Virtual' which is now the only possible mode.\n"
|
||||
"Your RPC will work as expected.\n");
|
||||
} else {
|
||||
SPDK_NOTICELOG("Please remove 'mode' from the RPC.\n");
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Core is no longer a valid parameter, but print out a nice
|
||||
* message if it exists to inform users.
|
||||
*/
|
||||
if (req->core != -1) {
|
||||
SPDK_NOTICELOG("Core present in the construct NVMe-oF subsystem RPC.\n"
|
||||
"Core was removed as an option. Subsystems can now run on all available cores.\n");
|
||||
SPDK_NOTICELOG("Ignoring it and continuing.\n");
|
||||
}
|
||||
|
||||
subsystem = spdk_nvmf_subsystem_create(g_spdk_nvmf_tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME,
|
||||
req->num_ns);
|
||||
if (!subsystem) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) {
|
||||
SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->hosts.num_hosts; i++) {
|
||||
spdk_nvmf_subsystem_add_host(subsystem, req->hosts.hosts[i]);
|
||||
}
|
||||
|
||||
spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host);
|
||||
|
||||
for (i = 0; i < req->namespaces.num_ns; i++) {
|
||||
struct spdk_nvmf_ns_params *ns_params = &req->namespaces.ns_params[i];
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_nvmf_ns_opts ns_opts;
|
||||
|
||||
bdev = spdk_bdev_get_by_name(ns_params->bdev_name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("Could not find namespace bdev '%s'\n", ns_params->bdev_name);
|
||||
spdk_nvmf_subsystem_destroy(subsystem);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
|
||||
ns_opts.nsid = ns_params->nsid;
|
||||
|
||||
SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ns_params->nguid), "size mismatch");
|
||||
memcpy(ns_opts.nguid, ns_params->nguid, sizeof(ns_opts.nguid));
|
||||
|
||||
SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ns_params->eui64), "size mismatch");
|
||||
memcpy(ns_opts.eui64, ns_params->eui64, sizeof(ns_opts.eui64));
|
||||
|
||||
if (!spdk_mem_all_zero(&ns_params->uuid, sizeof(ns_params->uuid))) {
|
||||
ns_opts.uuid = ns_params->uuid;
|
||||
}
|
||||
|
||||
if (spdk_nvmf_subsystem_add_ns(subsystem, bdev, &ns_opts, sizeof(ns_opts)) == 0) {
|
||||
SPDK_ERRLOG("Unable to add namespace\n");
|
||||
spdk_nvmf_subsystem_destroy(subsystem);
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
|
||||
if (req->listen_addresses.num_listen_address > 0) {
|
||||
struct rpc_listen_address *addr;
|
||||
struct spdk_nvme_transport_id trid = {0};
|
||||
struct subsystem_listen_ctx *ctx;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
spdk_nvmf_subsystem_destroy(subsystem);
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "No Memory");
|
||||
free_rpc_subsystem(req);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->req = req;
|
||||
ctx->subsystem = subsystem;
|
||||
ctx->request = request;
|
||||
ctx->idx = 0;
|
||||
|
||||
addr = &req->listen_addresses.addresses[0];
|
||||
|
||||
if (rpc_listen_address_to_trid(addr, &trid)) {
|
||||
free(ctx);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_nvmf_tgt_listen(g_spdk_nvmf_tgt, &trid, spdk_rpc_construct_subsystem_listen_done, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
free_rpc_subsystem(req);
|
||||
|
||||
spdk_nvmf_subsystem_start(subsystem,
|
||||
spdk_rpc_nvmf_subsystem_started,
|
||||
request);
|
||||
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
||||
free_rpc_subsystem(req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("construct_nvmf_subsystem", spdk_rpc_construct_nvmf_subsystem, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_subsystem_create {
|
||||
char *nqn;
|
||||
char *serial_number;
|
||||
uint32_t max_namespaces;
|
||||
bool allow_any_host;
|
||||
};
|
||||
|
||||
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},
|
||||
{"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},
|
||||
};
|
||||
|
||||
static void
|
||||
spdk_rpc_nvmf_subsystem_create(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
@ -933,6 +483,52 @@ invalid:
|
||||
}
|
||||
SPDK_RPC_REGISTER("delete_nvmf_subsystem", spdk_rpc_delete_nvmf_subsystem, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_listen_address {
|
||||
char *transport;
|
||||
char *adrfam;
|
||||
char *traddr;
|
||||
char *trsvcid;
|
||||
};
|
||||
|
||||
#define RPC_MAX_LISTEN_ADDRESSES 255
|
||||
#define RPC_MAX_NAMESPACES 255
|
||||
|
||||
struct rpc_listen_addresses {
|
||||
size_t num_listen_address;
|
||||
struct rpc_listen_address addresses[RPC_MAX_LISTEN_ADDRESSES];
|
||||
};
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = {
|
||||
/* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
|
||||
{"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
|
||||
{"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
|
||||
{"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true},
|
||||
{"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string},
|
||||
{"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static int
|
||||
decode_rpc_listen_address(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_listen_address *req = (struct rpc_listen_address *)out;
|
||||
if (spdk_json_decode_object(val, rpc_listen_address_decoders,
|
||||
SPDK_COUNTOF(rpc_listen_address_decoders),
|
||||
req)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_listen_address(struct rpc_listen_address *r)
|
||||
{
|
||||
free(r->transport);
|
||||
free(r->adrfam);
|
||||
free(r->traddr);
|
||||
free(r->trsvcid);
|
||||
}
|
||||
|
||||
enum nvmf_rpc_listen_op {
|
||||
NVMF_RPC_LISTEN_ADD,
|
||||
NVMF_RPC_LISTEN_REMOVE,
|
||||
@ -1045,6 +641,47 @@ nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem,
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
rpc_listen_address_to_trid(const struct rpc_listen_address *address,
|
||||
struct spdk_nvme_transport_id *trid)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
memset(trid, 0, sizeof(*trid));
|
||||
|
||||
if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) {
|
||||
SPDK_ERRLOG("Invalid transport type: %s\n", address->transport);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (address->adrfam) {
|
||||
if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) {
|
||||
SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
trid->adrfam = SPDK_NVMF_ADRFAM_IPV4;
|
||||
}
|
||||
|
||||
len = strlen(address->traddr);
|
||||
if (len > sizeof(trid->traddr) - 1) {
|
||||
SPDK_ERRLOG("Transport address longer than %zu characters: %s\n",
|
||||
sizeof(trid->traddr) - 1, address->traddr);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(trid->traddr, address->traddr, len + 1);
|
||||
|
||||
len = strlen(address->trsvcid);
|
||||
if (len > sizeof(trid->trsvcid) - 1) {
|
||||
SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n",
|
||||
sizeof(trid->trsvcid) - 1, address->trsvcid);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(trid->trsvcid, address->trsvcid, len + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvmf_rpc_subsystem_add_listener(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
@ -1149,6 +786,38 @@ nvmf_rpc_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
|
||||
SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", nvmf_rpc_subsystem_remove_listener,
|
||||
SPDK_RPC_RUNTIME);
|
||||
|
||||
struct spdk_nvmf_ns_params {
|
||||
char *bdev_name;
|
||||
uint32_t nsid;
|
||||
char nguid[16];
|
||||
char eui64[8];
|
||||
struct spdk_uuid uuid;
|
||||
};
|
||||
|
||||
struct rpc_namespaces {
|
||||
size_t num_ns;
|
||||
struct spdk_nvmf_ns_params ns_params[RPC_MAX_NAMESPACES];
|
||||
};
|
||||
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = {
|
||||
{"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true},
|
||||
{"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string},
|
||||
{"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true},
|
||||
{"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true},
|
||||
{"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true},
|
||||
};
|
||||
|
||||
static int
|
||||
decode_rpc_ns_params(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct spdk_nvmf_ns_params *ns_params = out;
|
||||
|
||||
return spdk_json_decode_object(val, rpc_ns_params_decoders,
|
||||
SPDK_COUNTOF(rpc_ns_params_decoders),
|
||||
ns_params);
|
||||
}
|
||||
|
||||
struct nvmf_rpc_ns_ctx {
|
||||
char *nqn;
|
||||
struct spdk_nvmf_ns_params ns_params;
|
||||
@ -1166,11 +835,10 @@ static void
|
||||
nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx)
|
||||
{
|
||||
free(ctx->nqn);
|
||||
free_rpc_ns_params(&ctx->ns_params);
|
||||
free(ctx->ns_params.bdev_name);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
|
||||
void *cb_arg, int status)
|
||||
|
620
lib/event/subsystems/nvmf/nvmf_rpc_deprecated.c
Normal file
620
lib/event/subsystems/nvmf/nvmf_rpc_deprecated.c
Normal file
@ -0,0 +1,620 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "event_nvmf.h"
|
||||
|
||||
#include "spdk/bdev.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/rpc.h"
|
||||
#include "spdk/env.h"
|
||||
#include "spdk/nvme.h"
|
||||
#include "spdk/nvmf.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/util.h"
|
||||
|
||||
static int
|
||||
hex_nybble_to_num(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
}
|
||||
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return c - 'a' + 0xA;
|
||||
}
|
||||
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return c - 'A' + 0xA;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
hex_byte_to_num(const char *str)
|
||||
{
|
||||
int hi, lo;
|
||||
|
||||
hi = hex_nybble_to_num(str[0]);
|
||||
if (hi < 0) {
|
||||
return hi;
|
||||
}
|
||||
|
||||
lo = hex_nybble_to_num(str[1]);
|
||||
if (lo < 0) {
|
||||
return lo;
|
||||
}
|
||||
|
||||
return hi * 16 + lo;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_hex_string_be(const char *str, uint8_t *out, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Decode a string in "ABCDEF012345" format to its binary representation */
|
||||
for (i = 0; i < size; i++) {
|
||||
int num = hex_byte_to_num(str);
|
||||
|
||||
if (num < 0) {
|
||||
/* Invalid hex byte or end of string */
|
||||
return -1;
|
||||
}
|
||||
|
||||
out[i] = (uint8_t)num;
|
||||
str += 2;
|
||||
}
|
||||
|
||||
if (i != size || *str != '\0') {
|
||||
/* Length mismatch */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_ns_nguid(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
char *str = NULL;
|
||||
int rc;
|
||||
|
||||
rc = spdk_json_decode_string(val, &str);
|
||||
if (rc == 0) {
|
||||
/* 16-byte NGUID */
|
||||
rc = decode_hex_string_be(str, out, 16);
|
||||
}
|
||||
|
||||
free(str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_ns_eui64(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
char *str = NULL;
|
||||
int rc;
|
||||
|
||||
rc = spdk_json_decode_string(val, &str);
|
||||
if (rc == 0) {
|
||||
/* 8-byte EUI-64 */
|
||||
rc = decode_hex_string_be(str, out, 8);
|
||||
}
|
||||
|
||||
free(str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_ns_uuid(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
char *str = NULL;
|
||||
int rc;
|
||||
|
||||
rc = spdk_json_decode_string(val, &str);
|
||||
if (rc == 0) {
|
||||
rc = spdk_uuid_parse(out, str);
|
||||
}
|
||||
|
||||
free(str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct rpc_listen_address {
|
||||
char *transport;
|
||||
char *adrfam;
|
||||
char *traddr;
|
||||
char *trsvcid;
|
||||
};
|
||||
|
||||
#define RPC_MAX_LISTEN_ADDRESSES 255
|
||||
#define RPC_MAX_HOSTS 255
|
||||
#define RPC_MAX_NAMESPACES 255
|
||||
|
||||
struct rpc_listen_addresses {
|
||||
size_t num_listen_address;
|
||||
struct rpc_listen_address addresses[RPC_MAX_LISTEN_ADDRESSES];
|
||||
};
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = {
|
||||
/* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
|
||||
{"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
|
||||
{"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
|
||||
{"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true},
|
||||
{"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string},
|
||||
{"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static int
|
||||
decode_rpc_listen_address(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_listen_address *req = (struct rpc_listen_address *)out;
|
||||
if (spdk_json_decode_object(val, rpc_listen_address_decoders,
|
||||
SPDK_COUNTOF(rpc_listen_address_decoders),
|
||||
req)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_listen_address(struct rpc_listen_address *r)
|
||||
{
|
||||
free(r->transport);
|
||||
free(r->adrfam);
|
||||
free(r->traddr);
|
||||
free(r->trsvcid);
|
||||
}
|
||||
|
||||
static int
|
||||
rpc_listen_address_to_trid(const struct rpc_listen_address *address,
|
||||
struct spdk_nvme_transport_id *trid)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
memset(trid, 0, sizeof(*trid));
|
||||
|
||||
if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) {
|
||||
SPDK_ERRLOG("Invalid transport type: %s\n", address->transport);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (address->adrfam) {
|
||||
if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) {
|
||||
SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
trid->adrfam = SPDK_NVMF_ADRFAM_IPV4;
|
||||
}
|
||||
|
||||
len = strlen(address->traddr);
|
||||
if (len > sizeof(trid->traddr) - 1) {
|
||||
SPDK_ERRLOG("Transport address longer than %zu characters: %s\n",
|
||||
sizeof(trid->traddr) - 1, address->traddr);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(trid->traddr, address->traddr, len + 1);
|
||||
|
||||
len = strlen(address->trsvcid);
|
||||
if (len > sizeof(trid->trsvcid) - 1) {
|
||||
SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n",
|
||||
sizeof(trid->trsvcid) - 1, address->trsvcid);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(trid->trsvcid, address->trsvcid, len + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_rpc_listen_addresses(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_listen_addresses *listen_addresses = out;
|
||||
return spdk_json_decode_array(val, decode_rpc_listen_address, &listen_addresses->addresses,
|
||||
RPC_MAX_LISTEN_ADDRESSES,
|
||||
&listen_addresses->num_listen_address, sizeof(struct rpc_listen_address));
|
||||
}
|
||||
|
||||
struct rpc_hosts {
|
||||
size_t num_hosts;
|
||||
char *hosts[RPC_MAX_HOSTS];
|
||||
};
|
||||
|
||||
static int
|
||||
decode_rpc_hosts(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_hosts *rpc_hosts = out;
|
||||
|
||||
return spdk_json_decode_array(val, spdk_json_decode_string, rpc_hosts->hosts, RPC_MAX_HOSTS,
|
||||
&rpc_hosts->num_hosts, sizeof(char *));
|
||||
}
|
||||
|
||||
|
||||
struct spdk_nvmf_ns_params {
|
||||
char *bdev_name;
|
||||
uint32_t nsid;
|
||||
char nguid[16];
|
||||
char eui64[8];
|
||||
struct spdk_uuid uuid;
|
||||
};
|
||||
|
||||
struct rpc_namespaces {
|
||||
size_t num_ns;
|
||||
struct spdk_nvmf_ns_params ns_params[RPC_MAX_NAMESPACES];
|
||||
};
|
||||
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = {
|
||||
{"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true},
|
||||
{"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string},
|
||||
{"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true},
|
||||
{"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true},
|
||||
{"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true},
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_ns_params(struct spdk_nvmf_ns_params *ns_params)
|
||||
{
|
||||
free(ns_params->bdev_name);
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_namespaces(struct rpc_namespaces *r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < r->num_ns; i++) {
|
||||
free_rpc_ns_params(&r->ns_params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
decode_rpc_ns_params(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct spdk_nvmf_ns_params *ns_params = out;
|
||||
|
||||
return spdk_json_decode_object(val, rpc_ns_params_decoders,
|
||||
SPDK_COUNTOF(rpc_ns_params_decoders),
|
||||
ns_params);
|
||||
}
|
||||
|
||||
static int
|
||||
decode_rpc_namespaces(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct rpc_namespaces *namespaces = out;
|
||||
char *names[RPC_MAX_NAMESPACES] = {0}; /* old format - array of strings (bdev names) */
|
||||
size_t i;
|
||||
int rc;
|
||||
|
||||
/* First try to decode namespaces as an array of objects (new format) */
|
||||
if (spdk_json_decode_array(val, decode_rpc_ns_params, namespaces->ns_params,
|
||||
SPDK_COUNTOF(namespaces->ns_params),
|
||||
&namespaces->num_ns, sizeof(*namespaces->ns_params)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If that fails, try to decode namespaces as an array of strings (old format) */
|
||||
free_rpc_namespaces(namespaces);
|
||||
memset(namespaces, 0, sizeof(*namespaces));
|
||||
rc = spdk_json_decode_array(val, spdk_json_decode_string, names,
|
||||
SPDK_COUNTOF(names),
|
||||
&namespaces->num_ns, sizeof(char *));
|
||||
if (rc == 0) {
|
||||
/* Decoded old format - copy to ns_params (new format) */
|
||||
for (i = 0; i < namespaces->num_ns; i++) {
|
||||
namespaces->ns_params[i].bdev_name = names[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Failed to decode - don't leave dangling string pointers around */
|
||||
for (i = 0; i < namespaces->num_ns; i++) {
|
||||
free(names[i]);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_listen_addresses(struct rpc_listen_addresses *r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < r->num_listen_address; i++) {
|
||||
free_rpc_listen_address(&r->addresses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_rpc_hosts(struct rpc_hosts *r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < r->num_hosts; i++) {
|
||||
free(r->hosts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
struct rpc_subsystem {
|
||||
int32_t core;
|
||||
char *mode;
|
||||
char *nqn;
|
||||
struct rpc_listen_addresses listen_addresses;
|
||||
struct rpc_hosts hosts;
|
||||
bool allow_any_host;
|
||||
char *pci_address;
|
||||
char *serial_number;
|
||||
struct rpc_namespaces namespaces;
|
||||
uint32_t num_ns;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_subsystem(struct rpc_subsystem *req)
|
||||
{
|
||||
if (req) {
|
||||
free(req->mode);
|
||||
free(req->nqn);
|
||||
free(req->serial_number);
|
||||
free_rpc_namespaces(&req->namespaces);
|
||||
free_rpc_listen_addresses(&req->listen_addresses);
|
||||
free_rpc_hosts(&req->hosts);
|
||||
}
|
||||
free(req);
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
|
||||
void *cb_arg, int status)
|
||||
{
|
||||
struct spdk_jsonrpc_request *request = cb_arg;
|
||||
struct spdk_json_write_ctx *w;
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
if (w == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_bool(w, true);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_subsystem_decoders[] = {
|
||||
{"core", offsetof(struct rpc_subsystem, core), spdk_json_decode_int32, true},
|
||||
{"mode", offsetof(struct rpc_subsystem, mode), spdk_json_decode_string, true},
|
||||
{"nqn", offsetof(struct rpc_subsystem, nqn), spdk_json_decode_string},
|
||||
{"listen_addresses", offsetof(struct rpc_subsystem, listen_addresses), decode_rpc_listen_addresses, true},
|
||||
{"hosts", offsetof(struct rpc_subsystem, hosts), decode_rpc_hosts, true},
|
||||
{"allow_any_host", offsetof(struct rpc_subsystem, allow_any_host), spdk_json_decode_bool, true},
|
||||
{"serial_number", offsetof(struct rpc_subsystem, serial_number), spdk_json_decode_string, true},
|
||||
{"namespaces", offsetof(struct rpc_subsystem, namespaces), decode_rpc_namespaces, true},
|
||||
{"max_namespaces", offsetof(struct rpc_subsystem, num_ns), spdk_json_decode_uint32, true},
|
||||
};
|
||||
|
||||
struct subsystem_listen_ctx {
|
||||
struct rpc_subsystem *req;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
struct spdk_jsonrpc_request *request;
|
||||
|
||||
uint32_t idx;
|
||||
};
|
||||
|
||||
static void
|
||||
spdk_rpc_construct_subsystem_listen_done(void *cb_arg, int status)
|
||||
{
|
||||
struct subsystem_listen_ctx *ctx = cb_arg;
|
||||
struct rpc_listen_address *addr;
|
||||
struct spdk_nvme_transport_id trid = {0};
|
||||
|
||||
if (status) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
addr = &ctx->req->listen_addresses.addresses[ctx->idx];
|
||||
if (rpc_listen_address_to_trid(addr, &trid)) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_nvmf_subsystem_add_listener(ctx->subsystem, &trid);
|
||||
|
||||
ctx->idx++;
|
||||
|
||||
if (ctx->idx < ctx->req->listen_addresses.num_listen_address) {
|
||||
addr = &ctx->req->listen_addresses.addresses[ctx->idx];
|
||||
|
||||
if (rpc_listen_address_to_trid(addr, &trid)) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_nvmf_tgt_listen(g_spdk_nvmf_tgt, &trid, spdk_rpc_construct_subsystem_listen_done, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_nvmf_subsystem_start(ctx->subsystem,
|
||||
spdk_rpc_nvmf_subsystem_started,
|
||||
ctx->request);
|
||||
|
||||
free_rpc_subsystem(ctx->req);
|
||||
free(ctx);
|
||||
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_nvmf_subsystem_destroy(ctx->subsystem);
|
||||
spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid parameters");
|
||||
free_rpc_subsystem(ctx->req);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_rpc_construct_nvmf_subsystem(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_subsystem *req;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
size_t i;
|
||||
|
||||
SPDK_WARNLOG("The construct_nvmf_subsystem RPC is deprecated. Use nvmf_subsystem_create instead.\n");
|
||||
|
||||
req = calloc(1, sizeof(*req));
|
||||
if (!req) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
req->core = -1; /* Explicitly set the core as the uninitialized value */
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_subsystem_decoders,
|
||||
SPDK_COUNTOF(rpc_subsystem_decoders),
|
||||
req)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* Mode is no longer a valid parameter, but print out a nice
|
||||
* message if it exists to inform users.
|
||||
*/
|
||||
if (req->mode) {
|
||||
SPDK_NOTICELOG("Mode present in the construct NVMe-oF subsystem RPC.\n"
|
||||
"Mode was removed as a valid parameter.\n");
|
||||
if (strcasecmp(req->mode, "Virtual") == 0) {
|
||||
SPDK_NOTICELOG("Your mode value is 'Virtual' which is now the only possible mode.\n"
|
||||
"Your RPC will work as expected.\n");
|
||||
} else {
|
||||
SPDK_NOTICELOG("Please remove 'mode' from the RPC.\n");
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Core is no longer a valid parameter, but print out a nice
|
||||
* message if it exists to inform users.
|
||||
*/
|
||||
if (req->core != -1) {
|
||||
SPDK_NOTICELOG("Core present in the construct NVMe-oF subsystem RPC.\n"
|
||||
"Core was removed as an option. Subsystems can now run on all available cores.\n");
|
||||
SPDK_NOTICELOG("Ignoring it and continuing.\n");
|
||||
}
|
||||
|
||||
subsystem = spdk_nvmf_subsystem_create(g_spdk_nvmf_tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME,
|
||||
req->num_ns);
|
||||
if (!subsystem) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) {
|
||||
SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->hosts.num_hosts; i++) {
|
||||
spdk_nvmf_subsystem_add_host(subsystem, req->hosts.hosts[i]);
|
||||
}
|
||||
|
||||
spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host);
|
||||
|
||||
for (i = 0; i < req->namespaces.num_ns; i++) {
|
||||
struct spdk_nvmf_ns_params *ns_params = &req->namespaces.ns_params[i];
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_nvmf_ns_opts ns_opts;
|
||||
|
||||
bdev = spdk_bdev_get_by_name(ns_params->bdev_name);
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("Could not find namespace bdev '%s'\n", ns_params->bdev_name);
|
||||
spdk_nvmf_subsystem_destroy(subsystem);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
|
||||
ns_opts.nsid = ns_params->nsid;
|
||||
|
||||
SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ns_params->nguid), "size mismatch");
|
||||
memcpy(ns_opts.nguid, ns_params->nguid, sizeof(ns_opts.nguid));
|
||||
|
||||
SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ns_params->eui64), "size mismatch");
|
||||
memcpy(ns_opts.eui64, ns_params->eui64, sizeof(ns_opts.eui64));
|
||||
|
||||
if (!spdk_mem_all_zero(&ns_params->uuid, sizeof(ns_params->uuid))) {
|
||||
ns_opts.uuid = ns_params->uuid;
|
||||
}
|
||||
|
||||
if (spdk_nvmf_subsystem_add_ns(subsystem, bdev, &ns_opts, sizeof(ns_opts)) == 0) {
|
||||
SPDK_ERRLOG("Unable to add namespace\n");
|
||||
spdk_nvmf_subsystem_destroy(subsystem);
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
|
||||
if (req->listen_addresses.num_listen_address > 0) {
|
||||
struct rpc_listen_address *addr;
|
||||
struct spdk_nvme_transport_id trid = {0};
|
||||
struct subsystem_listen_ctx *ctx;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
spdk_nvmf_subsystem_destroy(subsystem);
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "No Memory");
|
||||
free_rpc_subsystem(req);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->req = req;
|
||||
ctx->subsystem = subsystem;
|
||||
ctx->request = request;
|
||||
ctx->idx = 0;
|
||||
|
||||
addr = &req->listen_addresses.addresses[0];
|
||||
|
||||
if (rpc_listen_address_to_trid(addr, &trid)) {
|
||||
free(ctx);
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_nvmf_tgt_listen(g_spdk_nvmf_tgt, &trid, spdk_rpc_construct_subsystem_listen_done, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
free_rpc_subsystem(req);
|
||||
|
||||
spdk_nvmf_subsystem_start(subsystem,
|
||||
spdk_rpc_nvmf_subsystem_started,
|
||||
request);
|
||||
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
||||
free_rpc_subsystem(req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("construct_nvmf_subsystem", spdk_rpc_construct_nvmf_subsystem, SPDK_RPC_RUNTIME)
|
Loading…
x
Reference in New Issue
Block a user