nvmf: Allow configurable controller ID range
Add {min,max}_cntlid to spdk_nvmf_subsystem, defaulting to 1 and 0xFFEF, respectively, and add nvmf_subsystem_set_cntlid_range() to allow the controller range to be configured in the range [min_cntlid, max_cntlid]. Also add {min,max}_cntlid to the nvmf_create_subsystem RPC to allow the controller ID range to be specified when creating an nvmf subsystem. Signed-off-by: Jonathan Teh <jonathan.teh@mayadata.io> Change-Id: I936db3bb0c9a38569063a6fd3c11df262dfad776 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7322 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
acca0749df
commit
be6a01efb3
@ -7,6 +7,10 @@
|
||||
Remove the probe_cb parameter in spdk_idxd_probe function. And remove the definition
|
||||
of spdk_idxd_probe_cb function pointer. It should be implemented in idxd_user.c.
|
||||
|
||||
### nvmf
|
||||
|
||||
Added `min_cntlid` and `max_cntlid` to `nvmf_create_subsystem` to limit the controller ID range.
|
||||
|
||||
## v21.04:
|
||||
|
||||
### accel
|
||||
|
@ -5911,6 +5911,8 @@ model_number | Optional | string | Model number of virtual contr
|
||||
max_namespaces | Optional | number | Maximum number of namespaces that can be attached to the subsystem. Default: 0 (Unlimited)
|
||||
allow_any_host | Optional | boolean | Allow any host (`true`) or enforce allowed host list (`false`). Default: `false`.
|
||||
ana_reporting | Optional | boolean | Enable ANA reporting feature (default: `false`).
|
||||
min_cntlid | Optional | number | Minimum controller ID. Default: 1
|
||||
max_cntlid | Optional | number | Maximum controller ID. Default: 0xffef
|
||||
|
||||
### Example
|
||||
|
||||
|
@ -844,6 +844,24 @@ struct spdk_nvmf_ns *spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subs
|
||||
*/
|
||||
uint32_t spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem);
|
||||
|
||||
/**
|
||||
* Get the minimum controller ID allowed in a subsystem.
|
||||
*
|
||||
* \param subsystem Subsystem to query.
|
||||
*
|
||||
* \return Minimum controller ID allowed in the subsystem.
|
||||
*/
|
||||
uint16_t spdk_nvmf_subsystem_get_min_cntlid(const struct spdk_nvmf_subsystem *subsystem);
|
||||
|
||||
/**
|
||||
* Get the maximum controller ID allowed in a subsystem.
|
||||
*
|
||||
* \param subsystem Subsystem to query.
|
||||
*
|
||||
* \return Maximum controller ID allowed in the subsystem.
|
||||
*/
|
||||
uint16_t spdk_nvmf_subsystem_get_max_cntlid(const struct spdk_nvmf_subsystem *subsystem);
|
||||
|
||||
/**
|
||||
* Get a namespace's NSID.
|
||||
*
|
||||
|
@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
SO_VER := 8
|
||||
SO_MINOR := 0
|
||||
SO_MINOR := 1
|
||||
|
||||
C_SRCS = ctrlr.c ctrlr_discovery.c ctrlr_bdev.c \
|
||||
subsystem.c nvmf.c nvmf_rpc.c transport.c tcp.c
|
||||
|
@ -450,6 +450,9 @@ nvmf_write_subsystem_config_json(struct spdk_json_write_ctx *w,
|
||||
spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces);
|
||||
}
|
||||
|
||||
spdk_json_write_named_uint32(w, "min_cntlid", spdk_nvmf_subsystem_get_min_cntlid(subsystem));
|
||||
spdk_json_write_named_uint32(w, "max_cntlid", spdk_nvmf_subsystem_get_max_cntlid(subsystem));
|
||||
|
||||
/* } "params" */
|
||||
spdk_json_write_object_end(w);
|
||||
|
||||
|
@ -49,6 +49,10 @@
|
||||
|
||||
#define NVMF_MAX_ASYNC_EVENTS (4)
|
||||
|
||||
/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
|
||||
#define NVMF_MIN_CNTLID 1
|
||||
#define NVMF_MAX_CNTLID 0xFFEF
|
||||
|
||||
enum spdk_nvmf_subsystem_state {
|
||||
SPDK_NVMF_SUBSYSTEM_INACTIVE = 0,
|
||||
SPDK_NVMF_SUBSYSTEM_ACTIVATING,
|
||||
@ -286,6 +290,9 @@ struct spdk_nvmf_subsystem {
|
||||
struct spdk_nvmf_ns **ns;
|
||||
uint32_t max_nsid;
|
||||
|
||||
uint16_t min_cntlid;
|
||||
uint16_t max_cntlid;
|
||||
|
||||
TAILQ_HEAD(, spdk_nvmf_ctrlr) ctrlrs;
|
||||
|
||||
/* A mutex used to protect the hosts list and allow_any_host flag. Unlike the namespace
|
||||
@ -372,6 +379,21 @@ void nvmf_subsystem_set_ana_state(struct spdk_nvmf_subsystem *subsystem,
|
||||
enum spdk_nvme_ana_state ana_state,
|
||||
spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Sets the controller ID range for a subsystem.
|
||||
* Valid range is [1, 0xFFEF].
|
||||
*
|
||||
* May only be performed on subsystems in the INACTIVE state.
|
||||
*
|
||||
* \param subsystem Subsystem to modify.
|
||||
* \param min_cntlid Minimum controller ID.
|
||||
* \param max_cntlid Maximum controller ID.
|
||||
*
|
||||
* \return 0 on success, or negated errno value on failure.
|
||||
*/
|
||||
int nvmf_subsystem_set_cntlid_range(struct spdk_nvmf_subsystem *subsystem,
|
||||
uint16_t min_cntlid, uint16_t max_cntlid);
|
||||
|
||||
int nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr);
|
||||
int nvmf_ctrlr_async_event_ana_change_notice(struct spdk_nvmf_ctrlr *ctrlr);
|
||||
int nvmf_ctrlr_async_event_discovery_log_change_notice(struct spdk_nvmf_ctrlr *ctrlr);
|
||||
|
@ -259,6 +259,9 @@ dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *s
|
||||
spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces);
|
||||
}
|
||||
|
||||
spdk_json_write_named_uint32(w, "min_cntlid", spdk_nvmf_subsystem_get_min_cntlid(subsystem));
|
||||
spdk_json_write_named_uint32(w, "max_cntlid", spdk_nvmf_subsystem_get_max_cntlid(subsystem));
|
||||
|
||||
spdk_json_write_named_array_begin(w, "namespaces");
|
||||
for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
|
||||
ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
|
||||
@ -344,6 +347,8 @@ struct rpc_subsystem_create {
|
||||
uint32_t max_namespaces;
|
||||
bool allow_any_host;
|
||||
bool ana_reporting;
|
||||
uint16_t min_cntlid;
|
||||
uint16_t max_cntlid;
|
||||
};
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = {
|
||||
@ -354,6 +359,8 @@ static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = {
|
||||
{"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},
|
||||
{"ana_reporting", offsetof(struct rpc_subsystem_create, ana_reporting), spdk_json_decode_bool, true},
|
||||
{"min_cntlid", offsetof(struct rpc_subsystem_create, min_cntlid), spdk_json_decode_uint16, true},
|
||||
{"max_cntlid", offsetof(struct rpc_subsystem_create, max_cntlid), spdk_json_decode_uint16, true},
|
||||
};
|
||||
|
||||
static void
|
||||
@ -388,6 +395,8 @@ rpc_nvmf_create_subsystem(struct spdk_jsonrpc_request *request,
|
||||
"Memory allocation failed");
|
||||
return;
|
||||
}
|
||||
req->min_cntlid = NVMF_MIN_CNTLID;
|
||||
req->max_cntlid = NVMF_MAX_CNTLID;
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_subsystem_create_decoders,
|
||||
SPDK_COUNTOF(rpc_subsystem_create_decoders),
|
||||
@ -436,6 +445,14 @@ rpc_nvmf_create_subsystem(struct spdk_jsonrpc_request *request,
|
||||
|
||||
spdk_nvmf_subsystem_set_ana_reporting(subsystem, req->ana_reporting);
|
||||
|
||||
if (nvmf_subsystem_set_cntlid_range(subsystem, req->min_cntlid, req->max_cntlid)) {
|
||||
SPDK_ERRLOG("Subsystem %s: invalid cntlid range [%u-%u]\n", req->nqn, req->min_cntlid,
|
||||
req->max_cntlid);
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid cntlid range [%u-%u]", req->min_cntlid, req->max_cntlid);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rc = spdk_nvmf_subsystem_start(subsystem,
|
||||
rpc_nvmf_subsystem_started,
|
||||
request);
|
||||
|
@ -53,6 +53,8 @@
|
||||
spdk_nvmf_subsystem_get_first_ns;
|
||||
spdk_nvmf_subsystem_get_next_ns;
|
||||
spdk_nvmf_subsystem_get_ns;
|
||||
spdk_nvmf_subsystem_get_min_cntlid;
|
||||
spdk_nvmf_subsystem_get_max_cntlid;
|
||||
spdk_nvmf_subsystem_get_max_namespaces;
|
||||
spdk_nvmf_ns_get_id;
|
||||
spdk_nvmf_ns_get_bdev;
|
||||
|
@ -285,6 +285,8 @@ spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
|
||||
subsystem->subtype = type;
|
||||
subsystem->max_nsid = num_ns;
|
||||
subsystem->next_cntlid = 0;
|
||||
subsystem->min_cntlid = NVMF_MIN_CNTLID;
|
||||
subsystem->max_cntlid = NVMF_MAX_CNTLID;
|
||||
snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn);
|
||||
pthread_mutex_init(&subsystem->mutex, NULL);
|
||||
TAILQ_INIT(&subsystem->listeners);
|
||||
@ -1632,20 +1634,44 @@ spdk_nvmf_subsystem_get_max_nsid(struct spdk_nvmf_subsystem *subsystem)
|
||||
return subsystem->max_nsid;
|
||||
}
|
||||
|
||||
int
|
||||
nvmf_subsystem_set_cntlid_range(struct spdk_nvmf_subsystem *subsystem,
|
||||
uint16_t min_cntlid, uint16_t max_cntlid)
|
||||
{
|
||||
if (subsystem->state != SPDK_NVMF_SUBSYSTEM_INACTIVE) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (min_cntlid > max_cntlid) {
|
||||
return -EINVAL;
|
||||
}
|
||||
/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
|
||||
if (min_cntlid < NVMF_MIN_CNTLID || min_cntlid > NVMF_MAX_CNTLID ||
|
||||
max_cntlid < NVMF_MIN_CNTLID || max_cntlid > NVMF_MAX_CNTLID) {
|
||||
return -EINVAL;
|
||||
}
|
||||
subsystem->min_cntlid = min_cntlid;
|
||||
subsystem->max_cntlid = max_cntlid;
|
||||
if (subsystem->next_cntlid < min_cntlid || subsystem->next_cntlid > max_cntlid - 1) {
|
||||
subsystem->next_cntlid = min_cntlid - 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem)
|
||||
{
|
||||
int count;
|
||||
|
||||
/*
|
||||
* In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1
|
||||
* In the worst case, we might have to try all CNTLID values between min_cntlid and max_cntlid
|
||||
* before we find one that is unused (or find that all values are in use).
|
||||
*/
|
||||
for (count = 0; count < 0xFFF0 - 1; count++) {
|
||||
for (count = 0; count < subsystem->max_cntlid - subsystem->min_cntlid + 1; count++) {
|
||||
subsystem->next_cntlid++;
|
||||
if (subsystem->next_cntlid >= 0xFFF0) {
|
||||
/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
|
||||
subsystem->next_cntlid = 1;
|
||||
if (subsystem->next_cntlid > subsystem->max_cntlid) {
|
||||
subsystem->next_cntlid = subsystem->min_cntlid;
|
||||
}
|
||||
|
||||
/* Check if a controller with this cntlid currently exists. */
|
||||
@ -1702,6 +1728,18 @@ spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsyst
|
||||
return subsystem->max_nsid;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
spdk_nvmf_subsystem_get_min_cntlid(const struct spdk_nvmf_subsystem *subsystem)
|
||||
{
|
||||
return subsystem->min_cntlid;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
spdk_nvmf_subsystem_get_max_cntlid(const struct spdk_nvmf_subsystem *subsystem)
|
||||
{
|
||||
return subsystem->max_cntlid;
|
||||
}
|
||||
|
||||
struct _nvmf_ns_registrant {
|
||||
uint64_t rkey;
|
||||
char *host_uuid;
|
||||
|
@ -1917,7 +1917,9 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
model_number=args.model_number,
|
||||
allow_any_host=args.allow_any_host,
|
||||
max_namespaces=args.max_namespaces,
|
||||
ana_reporting=args.ana_reporting)
|
||||
ana_reporting=args.ana_reporting,
|
||||
min_cntlid=args.min_cntlid,
|
||||
max_cntlid=args.max_cntlid)
|
||||
|
||||
p = subparsers.add_parser('nvmf_create_subsystem', aliases=['nvmf_subsystem_create'],
|
||||
help='Create an NVMe-oF subsystem')
|
||||
@ -1933,6 +1935,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed",
|
||||
type=int, default=0)
|
||||
p.add_argument("-r", "--ana-reporting", action='store_true', help="Enable ANA reporting feature")
|
||||
p.add_argument("-i", "--min_cntlid", help="Minimum controller ID", type=int, default=1)
|
||||
p.add_argument("-I", "--max_cntlid", help="Maximum controller ID", type=int, default=0xffef)
|
||||
p.set_defaults(func=nvmf_create_subsystem)
|
||||
|
||||
def nvmf_delete_subsystem(args):
|
||||
|
@ -177,7 +177,9 @@ def nvmf_create_subsystem(client,
|
||||
model_number='SPDK bdev Controller',
|
||||
allow_any_host=False,
|
||||
max_namespaces=0,
|
||||
ana_reporting=False):
|
||||
ana_reporting=False,
|
||||
min_cntlid=1,
|
||||
max_cntlid=0xffef):
|
||||
"""Construct an NVMe over Fabrics target subsystem.
|
||||
|
||||
Args:
|
||||
@ -188,6 +190,8 @@ def nvmf_create_subsystem(client,
|
||||
allow_any_host: Allow any host (True) or enforce allowed host list (False). Default: False.
|
||||
max_namespaces: Maximum number of namespaces that can be attached to the subsystem (optional). Default: 0 (Unlimited).
|
||||
ana_reporting: Enable ANA reporting feature. Default: False.
|
||||
min_cntlid: Minimum controller ID. Default: 1
|
||||
max_cntlid: Maximum controller ID. Default: 0xffef
|
||||
|
||||
|
||||
Returns:
|
||||
@ -215,6 +219,12 @@ def nvmf_create_subsystem(client,
|
||||
if ana_reporting:
|
||||
params['ana_reporting'] = ana_reporting
|
||||
|
||||
if min_cntlid is not None:
|
||||
params['min_cntlid'] = min_cntlid
|
||||
|
||||
if max_cntlid is not None:
|
||||
params['max_cntlid'] = max_cntlid
|
||||
|
||||
return client.call('nvmf_create_subsystem', params)
|
||||
|
||||
|
||||
|
@ -66,6 +66,20 @@ fi
|
||||
out=$("$rpc" nvmf_subsystem_remove_listener "$nqn" -t "$TEST_TRANSPORT" -a "$IP" -s 4421 2>&1) && false
|
||||
[[ $out != *"Unable to stop listener."* ]]
|
||||
|
||||
# Attempt to create subsystem with invalid controller ID range - outside [1, 0xffef]
|
||||
out=$("$rpc" nvmf_create_subsystem "$nqn$RANDOM" -i 0 2>&1) && false
|
||||
[[ $out == *"Invalid cntlid range"* ]]
|
||||
out=$("$rpc" nvmf_create_subsystem "$nqn$RANDOM" -i 65520 2>&1) && false
|
||||
[[ $out == *"Invalid cntlid range"* ]]
|
||||
out=$("$rpc" nvmf_create_subsystem "$nqn$RANDOM" -I 0 2>&1) && false
|
||||
[[ $out == *"Invalid cntlid range"* ]]
|
||||
out=$("$rpc" nvmf_create_subsystem "$nqn$RANDOM" -I 65520 2>&1) && false
|
||||
[[ $out == *"Invalid cntlid range"* ]]
|
||||
|
||||
# Attempt to create subsystem with invalid controller ID range - [x, y] where x>y
|
||||
out=$("$rpc" nvmf_create_subsystem "$nqn$RANDOM" -i 6 -I 5 2>&1) && false
|
||||
[[ $out == *"Invalid cntlid range"* ]]
|
||||
|
||||
# Attempt to delete non-existing target
|
||||
out=$("$multi_target_rpc" nvmf_delete_target --name "$target" 2>&1) && false
|
||||
[[ $out == *"The specified target doesn't exist, cannot delete it."* ]]
|
||||
|
@ -23,7 +23,7 @@ $rpc_py nvmf_create_transport $NVMF_TRANSPORT_OPTS -u 8192
|
||||
$rpc_py bdev_malloc_create $MALLOC_BDEV_SIZE $MALLOC_BLOCK_SIZE -b Malloc0
|
||||
$rpc_py bdev_malloc_create $MALLOC_BDEV_SIZE $MALLOC_BLOCK_SIZE -b Malloc1
|
||||
|
||||
$rpc_py nvmf_create_subsystem nqn.2016-06.io.spdk:cnode1 -a -s $NVMF_SERIAL -d SPDK_Controller1
|
||||
$rpc_py nvmf_create_subsystem nqn.2016-06.io.spdk:cnode1 -a -s $NVMF_SERIAL -d SPDK_Controller1 -i 291
|
||||
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 Malloc0
|
||||
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 Malloc1
|
||||
$rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t $TEST_TRANSPORT -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT
|
||||
@ -46,6 +46,11 @@ for ctrl in "${nvmes[@]}"; do
|
||||
echo "Wrong model number for controller" $nvme_model
|
||||
exit 1
|
||||
fi
|
||||
nvme_cntlid=$(nvme id-ctrl $ctrl | grep -w cntlid | sed 's/^.*: //' | sed 's/ *$//')
|
||||
if [ "$nvme_cntlid" != "0x123" ]; then
|
||||
echo "Wrong controller ID for controller" $nvme_model
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for ns in "${nvmes[@]}"; do
|
||||
|
Loading…
Reference in New Issue
Block a user