nvmf: add Namespace attribute notice support

Users can use RPC to add/remove a namespace to/from
existing NVMe controller, SPDK NVMeoF target will
generate an asynchronous event as an indication to
host when asynchronous event request is available.

While here, we also set the event with invalid log
identifier, so that the host doesn't need to clear
the event. Users can use Set Feature to disable
such event.

Change-Id: I93c4d752f552d3c86c53e80877aa61c093e167cc
Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/398759
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Changpeng Liu 2018-02-06 00:16:08 -05:00 committed by Jim Harris
parent 22b8b92275
commit 763ab88884
7 changed files with 137 additions and 19 deletions

View File

@ -151,7 +151,7 @@ spdk_nvmf_ctrlr_create(struct spdk_nvmf_subsystem *subsystem,
ctrlr->max_qpairs_allowed = tgt->opts.max_qpairs_per_ctrlr; ctrlr->max_qpairs_allowed = tgt->opts.max_qpairs_per_ctrlr;
ctrlr->feat.keep_alive_timer.bits.kato = connect_cmd->kato; ctrlr->feat.keep_alive_timer.bits.kato = connect_cmd->kato;
ctrlr->feat.async_event_configuration.bits.ns_attr_notice = 1;
ctrlr->feat.volatile_write_cache.bits.wce = 1; ctrlr->feat.volatile_write_cache.bits.wce = 1;
/* Subtract 1 for admin queue, 1 for 0's based */ /* Subtract 1 for admin queue, 1 for 0's based */
@ -958,6 +958,13 @@ spdk_nvmf_ctrlr_async_event_request(struct spdk_nvmf_request *req)
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
if (ctrlr->notice_event.bits.async_event_type ==
SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE) {
rsp->cdw0 = ctrlr->notice_event.raw;
ctrlr->notice_event.raw = 0;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
ctrlr->aer_req = req; ctrlr->aer_req = req;
return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
} }
@ -1546,3 +1553,49 @@ spdk_nvmf_ctrlr_process_fabrics_cmd(struct spdk_nvmf_request *req)
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
} }
} }
int
spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr)
{
struct spdk_nvmf_request *req;
struct spdk_nvme_cpl *rsp;
union spdk_nvme_async_event_completion event = {0};
/* Users may disable the event notification */
if (!ctrlr->feat.async_event_configuration.bits.ns_attr_notice) {
return 0;
}
event.bits.async_event_type = SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE;
event.bits.async_event_info = SPDK_NVME_ASYNC_EVENT_NS_ATTR_CHANGED;
/* Alternatively, host may request Changed Namespace List log(04h)
* to determine which namespaces have changed. While here, we
* set invalid log page identifier to indicate that host doesn't
* need to send such log page.
*/
event.bits.log_page_identifier = 0;
/* If there is no outstanding AER request, queue the event. Then
* if an AER is later submitted, this event can be sent as a
* response.
*/
if (!ctrlr->aer_req) {
if (ctrlr->notice_event.bits.async_event_type ==
SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE) {
return 0;
}
ctrlr->notice_event.raw = event.raw;
return 0;
}
req = ctrlr->aer_req;
rsp = &req->rsp->nvme_cpl;
rsp->cdw0 = event.raw;
spdk_nvmf_request_complete(req);
ctrlr->aer_req = NULL;
return 0;
}

View File

@ -186,6 +186,7 @@ struct spdk_nvmf_ctrlr {
int num_qpairs; int num_qpairs;
int max_qpairs_allowed; int max_qpairs_allowed;
struct spdk_nvmf_request *aer_req; struct spdk_nvmf_request *aer_req;
union spdk_nvme_async_event_completion notice_event;
uint8_t hostid[16]; uint8_t hostid[16];
TAILQ_ENTRY(spdk_nvmf_ctrlr) link; TAILQ_ENTRY(spdk_nvmf_ctrlr) link;
@ -260,6 +261,7 @@ void spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem,
struct spdk_nvmf_ctrlr *ctrlr); struct spdk_nvmf_ctrlr *ctrlr);
struct spdk_nvmf_ctrlr *spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem,
uint16_t cntlid); uint16_t cntlid);
int spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr);
static inline struct spdk_nvmf_ns * static inline struct spdk_nvmf_ns *
_spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) _spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)

View File

@ -814,6 +814,7 @@ int
spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid) spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
{ {
struct spdk_nvmf_ns *ns; struct spdk_nvmf_ns *ns;
struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED || assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED ||
subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE); subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
@ -838,6 +839,10 @@ spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t ns
free(ns); free(ns);
subsystem->num_allocated_nsid--; subsystem->num_allocated_nsid--;
TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) {
spdk_nvmf_ctrlr_async_event_ns_notice(ctrlr);
}
return 0; return 0;
} }
@ -877,6 +882,7 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
{ {
struct spdk_nvmf_ns_opts opts; struct spdk_nvmf_ns_opts opts;
struct spdk_nvmf_ns *ns; struct spdk_nvmf_ns *ns;
struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
uint32_t i; uint32_t i;
int rc; int rc;
@ -915,11 +921,6 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
new_max_nsid = subsystem->max_nsid + 1; new_max_nsid = subsystem->max_nsid + 1;
} }
if (!TAILQ_EMPTY(&subsystem->ctrlrs)) {
SPDK_ERRLOG("Can't extend NSID range with active connections\n");
return 0;
}
new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * new_max_nsid); new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * new_max_nsid);
if (new_ns_array == NULL) { if (new_ns_array == NULL) {
SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n"); SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n");
@ -970,6 +971,10 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
} }
subsystem->ns[opts.nsid - 1] = ns; subsystem->ns[opts.nsid - 1] = ns;
TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) {
spdk_nvmf_ctrlr_async_event_ns_notice(ctrlr);
}
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n", SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n",
spdk_nvmf_subsystem_get_nqn(subsystem), spdk_nvmf_subsystem_get_nqn(subsystem),
spdk_bdev_get_name(bdev), spdk_bdev_get_name(bdev),

View File

@ -16,6 +16,11 @@ if [ -z $NVMF_FIRST_TARGET_IP ]; then
exit 0 exit 0
fi fi
if check_ip_is_soft_roce $NVMF_FIRST_TARGET_IP; then
echo "Bypass AER tests for softRoCE NIC"
exit 0
fi
timing_enter aer timing_enter aer
timing_enter start_nvmf_tgt timing_enter start_nvmf_tgt
@ -27,19 +32,64 @@ trap "killprocess $nvmfpid; exit 1" SIGINT SIGTERM EXIT
waitforlisten $nvmfpid waitforlisten $nvmfpid
timing_exit start_nvmf_tgt timing_exit start_nvmf_tgt
bdevs="$bdevs $($rpc_py construct_malloc_bdev 64 512)" modprobe -v nvme-rdma
$rpc_py construct_nvmf_subsystem nqn.2016-06.io.spdk:cnode1 "trtype:RDMA traddr:$NVMF_FIRST_TARGET_IP trsvcid:4420" '' -a -s SPDK00000000000001 -n "$bdevs"
$rootdir/test/nvme/aer/aer -r "\ $rpc_py construct_malloc_bdev 64 512 --name Malloc0
trtype:RDMA \ $rpc_py construct_nvmf_subsystem nqn.2016-06.io.spdk:cnode1 "trtype:RDMA traddr:$NVMF_FIRST_TARGET_IP trsvcid:$NVMF_PORT" '' -a -s SPDK00000000000001 -n Malloc0
adrfam:IPv4 \
traddr:$NVMF_FIRST_TARGET_IP \ # TODO: this aer test tries to invoke an AER completion by setting the temperature
trsvcid:$NVMF_PORT \ #threshold to a very low value. This does not work with emulated controllers
subnqn:nqn.2014-08.org.nvmexpress.discovery" #though so currently the test is disabled.
#$rootdir/test/nvme/aer/aer -r "\
# trtype:RDMA \
# adrfam:IPv4 \
# traddr:$NVMF_FIRST_TARGET_IP \
# trsvcid:$NVMF_PORT \
# subnqn:nqn.2014-08.org.nvmexpress.discovery"
# Namespace Attribute Notice Tests with kernel initiator
nvme connect -t rdma -n "nqn.2016-06.io.spdk:cnode1" -a "$NVMF_FIRST_TARGET_IP" -s "$NVMF_PORT"
sleep 2
sync sync
function get_nvme_name {
bdevs=$(lsblk -d | cut -d " " -f 1 | grep "^nvme[0-9]n2") || true
}
bdevs=""
get_nvme_name
if [ -n "$bdevs" ]; then
echo "Ignore adding Namespace 2 test"
$rpc_py delete_bdev Malloc0
nvmfcleanup
killprocess $nvmfpid
exit 0
fi
# Add a new namespace
$rpc_py construct_malloc_bdev 128 4096 --name Malloc1
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 Malloc1 -n 2
sleep 3
sync
bdevs=""
get_nvme_name
if [ -z "$bdevs" ]; then
echo "AER for adding a Namespace test failed"
nvmfcleanup
killprocess $nvmfpid
exit 1
fi
$rpc_py delete_bdev Malloc0
$rpc_py delete_bdev Malloc1
$rpc_py delete_nvmf_subsystem nqn.2016-06.io.spdk:cnode1 $rpc_py delete_nvmf_subsystem nqn.2016-06.io.spdk:cnode1
trap - SIGINT SIGTERM EXIT trap - SIGINT SIGTERM EXIT
nvmfcleanup
killprocess $nvmfpid killprocess $nvmfpid
timing_exit aer timing_exit aer

View File

@ -35,15 +35,11 @@ fi
timing_enter host timing_enter host
if [ $RUN_NIGHTLY -eq 1 ]; then
# TODO: temporarily disabled - temperature AER doesn't fire on emulated controllers
#run_test test/nvmf/host/aer.sh
true
fi
run_test test/nvmf/host/bdevperf.sh run_test test/nvmf/host/bdevperf.sh
run_test test/nvmf/host/identify.sh run_test test/nvmf/host/identify.sh
run_test test/nvmf/host/perf.sh run_test test/nvmf/host/perf.sh
run_test test/nvmf/host/identify_kernel_nvmf.sh run_test test/nvmf/host/identify_kernel_nvmf.sh
run_test test/nvmf/host/aer.sh
run_test test/nvmf/host/fio.sh run_test test/nvmf/host/fio.sh
timing_exit host timing_exit host

View File

@ -186,6 +186,12 @@ spdk_nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
return 0; return 0;
} }
int
spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr)
{
return 0;
}
static void static void
test_discovery_log(void) test_discovery_log(void)
{ {

View File

@ -207,6 +207,12 @@ spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
return &bdev->uuid; return &bdev->uuid;
} }
int
spdk_nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr)
{
return 0;
}
static void static void
test_spdk_nvmf_subsystem_add_ns(void) test_spdk_nvmf_subsystem_add_ns(void)
{ {