Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
64f1ea8ea4 | ||
|
1f0dd58a43 | ||
|
049e9290cf | ||
|
82c0c8ca03 | ||
|
1cf1b00b1b | ||
|
1d839c1ac3 | ||
|
9bdc45693a | ||
|
c7a0275edf | ||
|
a5a51c7b56 | ||
|
f2a113d144 | ||
|
b4ed65d26f | ||
|
26e589c3a4 | ||
|
14eeeea669 | ||
|
3f732d80d3 | ||
|
e02a868dd3 | ||
|
d02ff4c422 | ||
|
4b87c7259a | ||
|
02f9f45524 | ||
|
84c4530e9b | ||
|
0811dda8bf | ||
|
9b37f63fe9 | ||
|
edb5cd988a | ||
|
68eb748759 | ||
|
bbe2ed83dc | ||
|
d53d7a5723 | ||
|
2a1fe02d98 | ||
|
081cd04ea2 |
39
CHANGELOG.md
39
CHANGELOG.md
@ -1,6 +1,39 @@
|
||||
# Changelog
|
||||
|
||||
## v21.01: (Upcoming Release)
|
||||
## v21.01.2: (Upcoming Release)
|
||||
|
||||
## v21.01.1:
|
||||
|
||||
### dpdk
|
||||
|
||||
Added `rte_ethdev` and `rte_net` dependencies for all builds with DPDK.
|
||||
|
||||
Fixed compatibility issues with DPDK 19.11.
|
||||
|
||||
### iscsi
|
||||
|
||||
A security vulnerability has been identified and fixed in the SPDK iSCSI target.
|
||||
A TEXT PDU with no data, but CONTINUE flag set, would result in a NULL pointer dereference
|
||||
and crash the SPDK iSCSI target process. All users of the SPDK iSCSI target
|
||||
are recommended to update. All SPDK versions <= v21.01 are affected.
|
||||
|
||||
### nbd
|
||||
|
||||
Fixed kernel hang when bdev is removed by always setting NBD_SET_TIMEOUT.
|
||||
|
||||
### nvme
|
||||
|
||||
Fixed segfault when removing qpair when transport connection fails (issue #1777).
|
||||
|
||||
### ocssd
|
||||
|
||||
Fixed the bug that no media event is pushed to the target bdev.
|
||||
|
||||
### sock
|
||||
|
||||
Added `enable_quickack` and `enable_placement_id` when saving JSON configuration.
|
||||
|
||||
## v21.01: Dynamic scheduler, vfio-user, ZNS Zone Append
|
||||
|
||||
### bdev
|
||||
|
||||
@ -75,6 +108,10 @@ The `--pci-blacklist` command line option has been deprecated, replaced with
|
||||
The `--pci-whitelist/-W` command line options have been deprecated, replaced with
|
||||
`--pci-allowed/-A`.
|
||||
|
||||
Added new experimental `dynamic` scheduler that rebalances idle threads, adjusts CPU frequency
|
||||
using dpdk_governor and turns idle reactor cores to interrupt mode. Please see
|
||||
[scheduler documentation](https://www.spdk.io/doc/scheduler.html) for details.
|
||||
|
||||
## ioat
|
||||
|
||||
The PCI BDF whitelist option has been removed from the `ioat_scan_accel_engine` RPC.
|
||||
|
2
CONFIG
2
CONFIG
@ -121,7 +121,7 @@ CONFIG_VHOST=y
|
||||
CONFIG_VIRTIO=y
|
||||
|
||||
# Build custom vfio-user transport for NVMf target and NVMe initiator.
|
||||
CONFIG_VFIO_USER=y
|
||||
CONFIG_VFIO_USER=n
|
||||
|
||||
# Build with PMDK backends
|
||||
CONFIG_PMDK=n
|
||||
|
@ -2027,6 +2027,7 @@ show_thread(uint8_t current_page)
|
||||
|
||||
get_data();
|
||||
|
||||
assert(thread_number < g_threads_stats.threads.threads_count);
|
||||
for (i = 0; i < g_threads_stats.threads.threads_count; i++) {
|
||||
thread_info[i] = &g_threads_stats.threads.thread_info[i];
|
||||
}
|
||||
@ -2067,6 +2068,7 @@ show_core(uint8_t current_page)
|
||||
|
||||
get_data();
|
||||
|
||||
assert(core_number < g_cores_stats.cores.cores_count);
|
||||
for (i = 0; i < g_cores_stats.cores.cores_count; i++) {
|
||||
core_info[i] = &g_cores_stats.cores.core[i];
|
||||
}
|
||||
@ -2178,6 +2180,7 @@ show_poller(uint8_t current_page)
|
||||
get_data();
|
||||
|
||||
prepare_poller_data(current_page, pollers, &count, current_page);
|
||||
assert(poller_number < count);
|
||||
|
||||
poller_win = newwin(POLLER_WIN_HEIGHT, POLLER_WIN_WIDTH,
|
||||
(g_max_row - poller_counter) / 2, (g_max_col - POLLER_WIN_HOR_POS) / 2);
|
||||
@ -2300,6 +2303,7 @@ show_stats(void)
|
||||
} else {
|
||||
active_tab = THREADS_TAB;
|
||||
}
|
||||
g_selected_row = 0;
|
||||
current_page = 0;
|
||||
switch_tab(active_tab);
|
||||
break;
|
||||
|
@ -4,7 +4,8 @@ set -e
|
||||
|
||||
rootdir=$(readlink -f $(dirname $0))
|
||||
|
||||
conf=~/autorun-spdk.conf
|
||||
default_conf=~/autorun-spdk.conf
|
||||
conf=${1:-${default_conf}}
|
||||
|
||||
# If the configuration of tests is not provided, no tests will be carried out.
|
||||
if [[ ! -f $conf ]]; then
|
||||
|
42
configure
vendored
42
configure
vendored
@ -454,36 +454,22 @@ else
|
||||
fi
|
||||
BUILD_CMD+=(-I/usr/local/include -L/usr/local/lib)
|
||||
|
||||
function set_os_id_version() {
|
||||
if [[ -f /etc/os-release ]]; then
|
||||
source /etc/os-release
|
||||
fi
|
||||
|
||||
OSID=$ID
|
||||
OSVERSION=$VERSION_ID
|
||||
|
||||
echo "OS-ID: $OSID | OS-Version: $OSVERSION"
|
||||
}
|
||||
|
||||
if [[ "${CONFIG[VFIO_USER]}" = "y" ]]; then
|
||||
set_os_id_version
|
||||
|
||||
if [[ $arch != x86_64* ]] || [[ $sys_name == "FreeBSD" ]]; then
|
||||
echo "Non x86_64 and Linux platform, disable CONFIG_VFIO_USER"
|
||||
CONFIG[VFIO_USER]="n"
|
||||
# disable tests on ubuntu16 due to lack of macro definition in pci_regs.h
|
||||
elif [[ $OSID == "ubuntu" ]] && [[ $OSVERSION == "16.04" ]]; then
|
||||
echo "ubuntu16 OS, disable CONFIG_VFIO_USER"
|
||||
CONFIG[VFIO_USER]="n"
|
||||
elif ! hash cmake; then
|
||||
echo "cmake not installed, disable CONFIG_VFIO_USER"
|
||||
CONFIG[VFIO_USER]="n"
|
||||
elif [[ ! -d /usr/include/json-c ]] && [[ ! -d /usr/local/include/json-c ]]; then
|
||||
echo "json-c-devel not installed, disable CONFIG_VFIO_USER"
|
||||
CONFIG[VFIO_USER]="n"
|
||||
elif [[ ! -e /usr/include/cmocka.h ]] && [[ ! -e /usr/local/include/cmocka.h ]]; then
|
||||
echo "libcmocka-devel not installed, disable CONFIG_VFIO_USER"
|
||||
CONFIG[VFIO_USER]="n"
|
||||
if ! hash cmake; then
|
||||
echo "ERROR: --with-vfio-user requires cmake"
|
||||
echo "Please install then re-run this script"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d /usr/include/json-c ]] && [[ ! -d /usr/local/include/json-c ]]; then
|
||||
echo "ERROR: --with-vfio-user requires json-c-devel"
|
||||
echo "Please install then re-run this script"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -e /usr/include/cmocka.h ]] && [[ ! -e /usr/local/include/cmocka.h ]]; then
|
||||
echo "ERROR: --with-vfio-user requires libcmocka-devel"
|
||||
echo "Please install then re-run this script"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -835,6 +835,7 @@ INPUT += \
|
||||
peer_2_peer.md \
|
||||
pkgconfig.md \
|
||||
porting.md \
|
||||
scheduler.md \
|
||||
shfmt.md \
|
||||
spdkcli.md \
|
||||
spdk_top.md \
|
||||
|
@ -1,5 +1,6 @@
|
||||
# General Information {#general}
|
||||
|
||||
- @subpage event
|
||||
- @subpage scheduler
|
||||
- @subpage logical_volumes
|
||||
- @subpage accel_fw
|
||||
|
@ -78,7 +78,7 @@ A detailed description of each RPC method and its parameters is also available.
|
||||
scripts/rpc.py bdev_nvme_attach_controller --help
|
||||
~~~
|
||||
|
||||
### Generate JSON-RPC methods for current configuration
|
||||
### Generate JSON-RPC methods for current configuration {#jsonrpc_generate}
|
||||
|
||||
An initial configuration can be specified for an SPDK application via the '-c' command line parameter.
|
||||
The configuration file is a JSON file containing all of the JSON-RPC method invocations necessary
|
||||
@ -206,6 +206,18 @@ Finally, call the rpc.py script with '--plugin' parameter to provide above pytho
|
||||
./scripts/rpc.py --plugin rpc_plugin bdev_example_create 10 4096
|
||||
~~~
|
||||
|
||||
### Converting from legacy configuration {#jsonrpc_convert}
|
||||
|
||||
Starting with SPDK 20.10, legacy configuration file support has been removed.
|
||||
Users with extensive configuration files already running in SPDK application,
|
||||
can [generate JSON-RPC for current configuration](@ref jsonrpc_generate).
|
||||
|
||||
If binary for deploying the application is unavailable, the legacy configuration
|
||||
file can be converted to JSON-RPC using python tool:
|
||||
~~~
|
||||
./scripts/config_converter.py < config.ini > config.json
|
||||
~~~
|
||||
|
||||
# App Framework {#jsonrpc_components_app}
|
||||
|
||||
## spdk_kill_instance {#rpc_spdk_kill_instance}
|
||||
|
@ -116,10 +116,6 @@ An NVMe over Fabrics target can be configured using JSON RPCs.
|
||||
The basic RPCs needed to configure the NVMe-oF subsystem are detailed below. More information about
|
||||
working with NVMe over Fabrics specific RPCs can be found on the @ref jsonrpc_components_nvmf_tgt RPC page.
|
||||
|
||||
Using .ini style configuration files for configuration of the NVMe-oF target is deprecated and should
|
||||
be replaced with JSON based RPCs. .ini style configuration files can be converted to json format by way
|
||||
of the new script `scripts/config_converter.py`.
|
||||
|
||||
## FC transport support {#nvmf_fc_transport}
|
||||
|
||||
To build nvmf_tgt with the FC transport, there is an additional FC LLD (Low Level Driver) code dependency.
|
||||
|
82
doc/scheduler.md
Normal file
82
doc/scheduler.md
Normal file
@ -0,0 +1,82 @@
|
||||
# Scheduler {#scheduler}
|
||||
|
||||
SPDK's event/application framework (`lib/event`) now supports scheduling of
|
||||
lightweight threads. Schedulers are provided as plugins, called
|
||||
implementations. A default implementation is provided, but users may wish to
|
||||
write their own scheduler to integrate into broader code frameworks or meet
|
||||
their performance needs.
|
||||
|
||||
This feature should be considered experimental and is disabled by default. When
|
||||
enabled, the scheduler framework gathers data for each spdk thread and reactor
|
||||
and passes it to a scheduler implementation to perform one of the following
|
||||
actions.
|
||||
|
||||
## Actions
|
||||
|
||||
### Move a thread
|
||||
|
||||
`spdk_thread`s can be moved to another reactor. Schedulers can examine the
|
||||
suggested cpu_mask value for each lightweight thread to see if the user has
|
||||
requested specific reactors, or choose a reactor using whatever algorithm they
|
||||
deem fit.
|
||||
|
||||
### Switch reactor mode
|
||||
|
||||
Reactors by default run in a mode that constantly polls for new actions for the
|
||||
most efficient processing. Schedulers can switch a reactor into a mode that
|
||||
instead waits for an event on a file descriptor. On Linux, this is implemented
|
||||
using epoll. This results in reduced CPU usage but may be less responsive when
|
||||
events occur. A reactor cannot enter this mode if any `spdk_threads` are
|
||||
currently scheduled to it. This limitation is expected to be lifted in the
|
||||
future, allowing `spdk_threads` to enter interrupt mode.
|
||||
|
||||
### Set frequency of CPU core
|
||||
|
||||
The frequency of CPU cores can be modified by the scheduler in response to
|
||||
load. Only CPU cores that match the application cpu_mask may be modified. The
|
||||
mechanism for controlling CPU frequency is pluggable and the default provided
|
||||
implementation is called `dpdk_governor`, based on the `rte_power` library from
|
||||
DPDK.
|
||||
|
||||
#### Known limitation
|
||||
|
||||
When SMT (Hyperthreading) is enabled the two logical CPU cores sharing a single
|
||||
physical CPU core must run at the same frequency. If one of two of such logical
|
||||
CPU cores is outside the application cpu_mask, the policy and frequency on that
|
||||
core has to be managed by the administrator.
|
||||
|
||||
## Scheduler implementations
|
||||
|
||||
The scheduler in use may be controlled by JSON-RPC. Please use the
|
||||
[framework_set_scheduler](jsonrpc.md/#rpc_framework_set_scheduler) RPC to
|
||||
switch between schedulers or change their options.
|
||||
|
||||
[spdk_top](spdk_top.md#spdk_top) is a useful tool to observe the behavior of
|
||||
schedulers in different scenarios and workloads.
|
||||
|
||||
### static [default]
|
||||
|
||||
The `static` scheduler is the default scheduler and does no dynamic scheduling.
|
||||
Lightweight threads are distributed round-robin among reactors, respecting
|
||||
their requested cpu_mask, and then they are never moved. This is equivalent to
|
||||
the previous behavior of the SPDK event/application framework.
|
||||
|
||||
### dynamic
|
||||
|
||||
The `dynamic` scheduler is designed for power saving and reduction of CPU
|
||||
utilization, especially in cases where workloads show large variations over
|
||||
time.
|
||||
|
||||
Active threads are distributed equally among reactors, taking cpu_mask into
|
||||
account. All idle threads are moved to the main core. Once an idle thread becomes
|
||||
active, it is redistributed again.
|
||||
|
||||
When a reactor has no scheduled `spdk_thread`s it is switched into interrupt
|
||||
mode and stops actively polling. After enough threads become active, the
|
||||
reactor is switched back into poll mode and threads are assigned to it again.
|
||||
|
||||
The main core can contain active threads only when their execution time does
|
||||
not exceed the sum of all idle threads. When no active threads are present on
|
||||
the main core, the frequency of that CPU core will decrease as the load
|
||||
decreases. All CPU cores corresponding to the other reactors remain at maximum
|
||||
frequency.
|
@ -54,7 +54,7 @@
|
||||
* Patch level is incremented on maintenance branch releases and reset to 0 for each
|
||||
* new major.minor release.
|
||||
*/
|
||||
#define SPDK_VERSION_PATCH 0
|
||||
#define SPDK_VERSION_PATCH 2
|
||||
|
||||
/**
|
||||
* Version string suffix.
|
||||
|
@ -51,7 +51,7 @@ DPDK_INC := -I$(DPDK_INC_DIR)
|
||||
DPDK_LIB_LIST = rte_eal rte_mempool rte_ring rte_mbuf rte_pci rte_bus_pci rte_mempool_ring
|
||||
|
||||
ifeq ($(OS),Linux)
|
||||
DPDK_LIB_LIST += rte_power
|
||||
DPDK_LIB_LIST += rte_power rte_ethdev rte_net
|
||||
endif
|
||||
|
||||
# DPDK 20.05 eal dependency
|
||||
@ -101,7 +101,7 @@ endif
|
||||
LINK_HASH=n
|
||||
|
||||
ifeq ($(CONFIG_VHOST),y)
|
||||
DPDK_LIB_LIST += rte_vhost rte_net
|
||||
DPDK_LIB_LIST += rte_vhost
|
||||
LINK_HASH=y
|
||||
ifneq ($(DPDK_FRAMEWORK),y)
|
||||
DPDK_LIB_LIST += rte_cryptodev
|
||||
|
@ -1238,7 +1238,11 @@ vtophys_iommu_device_event(const char *device_name,
|
||||
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
||||
if (strcmp(dev->name, device_name) == 0) {
|
||||
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
||||
#if RTE_VERSION < RTE_VERSION_NUM(20, 11, 0, 0)
|
||||
if (pci_dev->kdrv == RTE_KDRV_VFIO) {
|
||||
#else
|
||||
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
||||
#endif
|
||||
/* This is a new PCI device using vfio */
|
||||
g_vfio.device_ref++;
|
||||
}
|
||||
@ -1267,7 +1271,11 @@ vtophys_iommu_device_event(const char *device_name,
|
||||
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
||||
if (strcmp(dev->name, device_name) == 0) {
|
||||
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
||||
#if RTE_VERSION < RTE_VERSION_NUM(20, 11, 0, 0)
|
||||
if (pci_dev->kdrv == RTE_KDRV_VFIO) {
|
||||
#else
|
||||
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
||||
#endif
|
||||
/* This is a PCI device using vfio */
|
||||
g_vfio.device_ref--;
|
||||
}
|
||||
@ -1362,7 +1370,11 @@ vtophys_iommu_init(void)
|
||||
RTE_DEV_FOREACH(dev, "bus=pci", &dev_iter) {
|
||||
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
|
||||
|
||||
#if RTE_VERSION < RTE_VERSION_NUM(20, 11, 0, 0)
|
||||
if (pci_dev->kdrv == RTE_KDRV_VFIO) {
|
||||
#else
|
||||
if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
|
||||
#endif
|
||||
/* This is a PCI device using vfio */
|
||||
g_vfio.device_ref++;
|
||||
}
|
||||
|
@ -1010,8 +1010,10 @@ void
|
||||
spdk_reactors_start(void)
|
||||
{
|
||||
struct spdk_reactor *reactor;
|
||||
struct spdk_cpuset tmp_cpumask = {};
|
||||
uint32_t i, current_core;
|
||||
int rc;
|
||||
char thread_name[32];
|
||||
|
||||
g_rusage_period = (CONTEXT_SWITCH_MONITOR_PERIOD * spdk_get_ticks_hz()) / SPDK_SEC_TO_USEC;
|
||||
g_reactor_state = SPDK_REACTOR_STATE_RUNNING;
|
||||
@ -1030,6 +1032,14 @@ spdk_reactors_start(void)
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For now, for each reactor spawn one thread. */
|
||||
snprintf(thread_name, sizeof(thread_name), "reactor_%u", reactor->lcore);
|
||||
|
||||
spdk_cpuset_zero(&tmp_cpumask);
|
||||
spdk_cpuset_set_cpu(&tmp_cpumask, i, true);
|
||||
|
||||
spdk_thread_create(thread_name, &tmp_cpumask);
|
||||
}
|
||||
spdk_cpuset_set_cpu(&g_reactor_core_mask, i, true);
|
||||
}
|
||||
|
@ -315,6 +315,16 @@ iscsi_parse_params(struct iscsi_param **params, const uint8_t *data,
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
/* Spec does not disallow TEXT PDUs with zero length, just return
|
||||
* immediately in that case, since there is no param data to parse
|
||||
* and any existing partial parameter would remain as-is.
|
||||
*/
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(data != NULL);
|
||||
|
||||
/* strip the partial text parameters if previous PDU have C enabled */
|
||||
if (partial_parameter && *partial_parameter) {
|
||||
for (i = 0; i < len && data[i] != '\0'; i++) {
|
||||
|
@ -50,6 +50,7 @@
|
||||
#define GET_IO_LOOP_COUNT 16
|
||||
#define NBD_BUSY_WAITING_MS 1000
|
||||
#define NBD_BUSY_POLLING_INTERVAL_US 20000
|
||||
#define NBD_IO_TIMEOUT_S 60
|
||||
|
||||
enum nbd_io_state_t {
|
||||
/* Receiving or ready to receive nbd request header */
|
||||
@ -922,6 +923,17 @@ nbd_start_complete(struct spdk_nbd_start_ctx *ctx)
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef NBD_SET_TIMEOUT
|
||||
rc = ioctl(ctx->nbd->dev_fd, NBD_SET_TIMEOUT, NBD_IO_TIMEOUT_S);
|
||||
if (rc == -1) {
|
||||
SPDK_ERRLOG("ioctl(NBD_SET_TIMEOUT) failed: %s\n", spdk_strerror(errno));
|
||||
rc = -errno;
|
||||
goto err;
|
||||
}
|
||||
#else
|
||||
SPDK_NOTICELOG("ioctl(NBD_SET_TIMEOUT) is not supported.\n");
|
||||
#endif
|
||||
|
||||
#ifdef NBD_FLAG_SEND_TRIM
|
||||
rc = ioctl(ctx->nbd->dev_fd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM);
|
||||
if (rc == -1) {
|
||||
|
@ -418,8 +418,12 @@ spdk_nvme_ctrlr_alloc_io_qpair(struct spdk_nvme_ctrlr *ctrlr,
|
||||
rc = spdk_nvme_ctrlr_connect_io_qpair(ctrlr, qpair);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("nvme_transport_ctrlr_connect_io_qpair() failed\n");
|
||||
nvme_robust_mutex_lock(&ctrlr->ctrlr_lock);
|
||||
nvme_ctrlr_proc_remove_io_qpair(qpair);
|
||||
TAILQ_REMOVE(&ctrlr->active_io_qpairs, qpair, tailq);
|
||||
spdk_bit_array_set(ctrlr->free_io_qids, qpair->id);
|
||||
nvme_transport_ctrlr_delete_io_qpair(ctrlr, qpair);
|
||||
nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2019, 2020 Mellanox Technologies LTD. All rights reserved.
|
||||
* Copyright (c) 2019-2021 Mellanox Technologies LTD. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -944,6 +944,11 @@ nvmf_rdma_resize_cq(struct spdk_nvmf_rdma_qpair *rqpair, struct spdk_nvmf_rdma_d
|
||||
}
|
||||
|
||||
if (rpoller->num_cqe != num_cqe) {
|
||||
if (device->context->device->transport_type == IBV_TRANSPORT_IWARP) {
|
||||
SPDK_ERRLOG("iWARP doesn't support CQ resize. Current capacity %u, required %u\n"
|
||||
"Using CQ of insufficient size may lead to CQ overrun\n", rpoller->num_cqe, num_cqe);
|
||||
return -1;
|
||||
}
|
||||
if (required_num_wr > device->attr.max_cqe) {
|
||||
SPDK_ERRLOG("RDMA CQE requirement (%d) exceeds device max_cqe limitation (%d)\n",
|
||||
required_num_wr, device->attr.max_cqe);
|
||||
@ -4106,19 +4111,24 @@ nvmf_rdma_qpair_abort_request(struct spdk_nvmf_qpair *qpair,
|
||||
struct spdk_nvmf_rdma_transport *rtransport;
|
||||
struct spdk_nvmf_transport *transport;
|
||||
uint16_t cid;
|
||||
uint32_t i;
|
||||
struct spdk_nvmf_rdma_request *rdma_req_to_abort = NULL;
|
||||
uint32_t i, max_req_count;
|
||||
struct spdk_nvmf_rdma_request *rdma_req_to_abort = NULL, *rdma_req;
|
||||
|
||||
rqpair = SPDK_CONTAINEROF(qpair, struct spdk_nvmf_rdma_qpair, qpair);
|
||||
rtransport = SPDK_CONTAINEROF(qpair->transport, struct spdk_nvmf_rdma_transport, transport);
|
||||
transport = &rtransport->transport;
|
||||
|
||||
cid = req->cmd->nvme_cmd.cdw10_bits.abort.cid;
|
||||
max_req_count = rqpair->srq == NULL ? rqpair->max_queue_depth : rqpair->poller->max_srq_depth;
|
||||
|
||||
for (i = 0; i < rqpair->max_queue_depth; i++) {
|
||||
if (rqpair->resources->reqs[i].state != RDMA_REQUEST_STATE_FREE &&
|
||||
rqpair->resources->reqs[i].req.cmd->nvme_cmd.cid == cid) {
|
||||
rdma_req_to_abort = &rqpair->resources->reqs[i];
|
||||
for (i = 0; i < max_req_count; i++) {
|
||||
rdma_req = &rqpair->resources->reqs[i];
|
||||
/* When SRQ == NULL, rqpair has its own requests and req.qpair pointer always points to the qpair
|
||||
* When SRQ != NULL all rqpairs share common requests and qpair pointer is assigned when we start to
|
||||
* process a request. So in both cases all requests which are not in FREE state have valid qpair ptr */
|
||||
if (rdma_req->state != RDMA_REQUEST_STATE_FREE && rdma_req->req.cmd->nvme_cmd.cid == cid &&
|
||||
rdma_req->req.qpair == qpair) {
|
||||
rdma_req_to_abort = rdma_req;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -832,6 +832,8 @@ spdk_sock_write_config_json(struct spdk_json_write_ctx *w)
|
||||
spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size);
|
||||
spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe);
|
||||
spdk_json_write_named_bool(w, "enable_zerocopy_send", opts.enable_zerocopy_send);
|
||||
spdk_json_write_named_bool(w, "enable_quickack", opts.enable_quickack);
|
||||
spdk_json_write_named_bool(w, "enable_placement_id", opts.enable_placement_id);
|
||||
spdk_json_write_object_end(w);
|
||||
spdk_json_write_object_end(w);
|
||||
} else {
|
||||
|
@ -85,8 +85,8 @@ int
|
||||
spdk_fd_group_add(struct spdk_fd_group *fgrp,
|
||||
int efd, spdk_fd_fn fn, void *arg)
|
||||
{
|
||||
struct event_handler *ehdlr;
|
||||
struct epoll_event epevent;
|
||||
struct event_handler *ehdlr = NULL;
|
||||
struct epoll_event epevent = {0};
|
||||
int rc;
|
||||
|
||||
/* parameter checking */
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "spdk/barrier.h"
|
||||
#include "spdk/vhost.h"
|
||||
#include "vhost_internal.h"
|
||||
#include <rte_version.h>
|
||||
|
||||
#include "spdk_internal/vhost_user.h"
|
||||
|
||||
@ -331,7 +332,11 @@ vhost_register_unix_socket(const char *path, const char *ctrl_name,
|
||||
}
|
||||
}
|
||||
|
||||
#if RTE_VERSION < RTE_VERSION_NUM(20, 8, 0, 0)
|
||||
if (rte_vhost_driver_register(path, 0) != 0) {
|
||||
#else
|
||||
if (rte_vhost_driver_register(path, RTE_VHOST_USER_ASYNC_COPY) != 0) {
|
||||
#endif
|
||||
SPDK_ERRLOG("Could not register controller %s with vhost library\n", ctrl_name);
|
||||
SPDK_ERRLOG("Check if domain socket %s already exists\n", path);
|
||||
return -EIO;
|
||||
|
@ -888,6 +888,7 @@ static int
|
||||
vhost_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
|
||||
{
|
||||
int rc;
|
||||
struct spdk_cpuset negative_vhost_mask;
|
||||
|
||||
if (cpumask == NULL) {
|
||||
return -1;
|
||||
@ -904,6 +905,16 @@ vhost_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
|
||||
return -1;
|
||||
}
|
||||
|
||||
spdk_cpuset_copy(&negative_vhost_mask, &g_vhost_core_mask);
|
||||
spdk_cpuset_negate(&negative_vhost_mask);
|
||||
spdk_cpuset_and(&negative_vhost_mask, cpumask);
|
||||
|
||||
if (spdk_cpuset_count(&negative_vhost_mask) != 0) {
|
||||
SPDK_ERRLOG("one of selected cpu is outside of core mask(=%s)\n",
|
||||
spdk_cpuset_fmt(&g_vhost_core_mask));
|
||||
return -1;
|
||||
}
|
||||
|
||||
spdk_cpuset_and(cpumask, &g_vhost_core_mask);
|
||||
|
||||
if (spdk_cpuset_count(cpumask) == 0) {
|
||||
|
@ -967,7 +967,7 @@ bdev_ocssd_push_media_events(struct nvme_bdev_ns *nvme_ns,
|
||||
TAILQ_FOREACH(nvme_bdev, &nvme_ns->bdevs, tailq) {
|
||||
ocssd_bdev = SPDK_CONTAINEROF(nvme_bdev, struct ocssd_bdev, nvme_bdev);
|
||||
if (bdev_ocssd_lba_in_range(ocssd_bdev, ocssd_ns, chunk_entry->lba)) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,12 @@
|
||||
%bcond_with doc
|
||||
|
||||
Name: spdk
|
||||
Version: master
|
||||
Version: 21.01.x
|
||||
Release: 0%{?dist}
|
||||
Epoch: 0
|
||||
URL: http://spdk.io
|
||||
|
||||
Source: https://github.com/spdk/spdk/archive/master.tar.gz
|
||||
Source: https://github.com/spdk/spdk/archive/v21.01.x.tar.gz
|
||||
Summary: Set of libraries and utilities for high performance user-mode storage
|
||||
|
||||
%define package_version %{epoch}:%{version}-%{release}
|
||||
@ -22,7 +22,7 @@ License: BSD
|
||||
ExclusiveArch: x86_64
|
||||
|
||||
BuildRequires: gcc gcc-c++ make
|
||||
BuildRequires: dpdk-devel, numactl-devel
|
||||
BuildRequires: dpdk-devel, numactl-devel, ncurses-devel
|
||||
BuildRequires: libiscsi-devel, libaio-devel, openssl-devel, libuuid-devel
|
||||
BuildRequires: libibverbs-devel, librdmacm-devel
|
||||
%if %{with doc}
|
||||
@ -32,6 +32,7 @@ BuildRequires: doxygen mscgen graphviz
|
||||
# Install dependencies
|
||||
Requires: dpdk >= 19.11, numactl-libs, openssl-libs
|
||||
Requires: libiscsi, libaio, libuuid
|
||||
Requires: python3-configshell, python3-pexpect
|
||||
# NVMe over Fabrics
|
||||
Requires: librdmacm, librdmacm
|
||||
Requires(post): /sbin/ldconfig
|
||||
|
@ -9,6 +9,7 @@ SPDK_TEST_ISCSI_INITIATOR=0
|
||||
SPDK_TEST_NVME=0
|
||||
SPDK_TEST_NVME_CLI=0
|
||||
SPDK_TEST_NVMF=1
|
||||
SPDK_TEST_VFIOUSER=1
|
||||
SPDK_TEST_RBD=0
|
||||
SPDK_TEST_CRYPTO=0
|
||||
SPDK_TEST_OCF=0
|
||||
|
@ -81,6 +81,8 @@ export SPDK_TEST_NVME_CLI
|
||||
export SPDK_TEST_NVME_CUSE
|
||||
: ${SPDK_TEST_NVMF=0}
|
||||
export SPDK_TEST_NVMF
|
||||
: ${SPDK_TEST_VFIOUSER=0}
|
||||
export SPDK_TEST_VFIOUSER
|
||||
: ${SPDK_TEST_NVMF_TRANSPORT="rdma"}
|
||||
export SPDK_TEST_NVMF_TRANSPORT
|
||||
: ${SPDK_TEST_RBD=0}
|
||||
@ -422,6 +424,10 @@ function get_config_params() {
|
||||
config_params+=' --with-raid5'
|
||||
fi
|
||||
|
||||
if [ $SPDK_TEST_VFIOUSER -eq 1 ]; then
|
||||
config_params+=' --with-vfio-user'
|
||||
fi
|
||||
|
||||
# Check whether liburing library header exists
|
||||
if [ -f /usr/include/liburing/io_uring.h ] && [ $SPDK_TEST_URING -eq 1 ]; then
|
||||
config_params+=' --with-uring'
|
||||
|
@ -185,6 +185,7 @@ SPDK_TEST_ISCSI_INITIATOR=1
|
||||
SPDK_TEST_NVME=1
|
||||
SPDK_TEST_NVME_CLI=1
|
||||
SPDK_TEST_NVMF=1
|
||||
SPDK_TEST_VFIOUSER=1
|
||||
SPDK_TEST_RBD=1
|
||||
SPDK_TEST_BLOCKDEV=1
|
||||
SPDK_TEST_BLOBFS=1
|
||||
|
@ -49,17 +49,6 @@ function confirm_abi_deps() {
|
||||
fi
|
||||
|
||||
cat << EOF > ${suppression_file}
|
||||
[suppress_type]
|
||||
name = spdk_nvme_ctrlr_data
|
||||
[suppress_type]
|
||||
type_kind = enum
|
||||
changed_enumerators = SPDK_BDEV_NUM_IO_TYPES
|
||||
[suppress_type]
|
||||
name = spdk_env_opts
|
||||
[suppress_type]
|
||||
name = spdk_app_opts
|
||||
[suppress_type]
|
||||
name = spdk_thread
|
||||
EOF
|
||||
|
||||
for object in "$libdir"/libspdk_*.so; do
|
||||
|
@ -41,7 +41,7 @@ run_test "nvmf_invalid" test/nvmf/target/invalid.sh "${TEST_ARGS[@]}"
|
||||
run_test "nvmf_abort" test/nvmf/target/abort.sh "${TEST_ARGS[@]}"
|
||||
run_test "nvmf_ns_hotplug_stress" test/nvmf/target/ns_hotplug_stress.sh "${TEST_ARGS[@]}"
|
||||
|
||||
if grep -q '#define SPDK_CONFIG_VFIO_USER 1' $rootdir/include/spdk/config.h; then
|
||||
if [ $SPDK_TEST_VFIOUSER -eq 1 ]; then
|
||||
run_test "nvmf_vfio_user" test/nvmf/target/nvmf_vfio_user.sh "${TEST_ARGS[@]}"
|
||||
fi
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"cpumask": "$(S)",
|
||||
"cpumask": "0x3",
|
||||
"ctrlr": "vhost_scsi1",
|
||||
"delay_base_us": 20,
|
||||
"iops_threshold": 1000000,
|
||||
|
@ -1993,6 +1993,43 @@ pdu_hdr_op_data_test(void)
|
||||
g_task_pool_is_empty = false;
|
||||
}
|
||||
|
||||
/* Test an ISCSI_OP_TEXT PDU with CONTINUE bit set but
|
||||
* no data.
|
||||
*/
|
||||
static void
|
||||
empty_text_with_cbit_test(void)
|
||||
{
|
||||
struct spdk_iscsi_sess sess = {};
|
||||
struct spdk_iscsi_conn conn = {};
|
||||
struct spdk_scsi_dev dev = {};
|
||||
struct spdk_iscsi_pdu *req_pdu;
|
||||
int rc;
|
||||
|
||||
req_pdu = iscsi_get_pdu(&conn);
|
||||
|
||||
sess.ExpCmdSN = 0;
|
||||
sess.MaxCmdSN = 64;
|
||||
sess.session_type = SESSION_TYPE_NORMAL;
|
||||
sess.MaxBurstLength = 1024;
|
||||
|
||||
conn.full_feature = 1;
|
||||
conn.sess = &sess;
|
||||
conn.dev = &dev;
|
||||
conn.state = ISCSI_CONN_STATE_RUNNING;
|
||||
|
||||
memset(&req_pdu->bhs, 0, sizeof(req_pdu->bhs));
|
||||
req_pdu->bhs.opcode = ISCSI_OP_TEXT;
|
||||
req_pdu->bhs.flags = ISCSI_TEXT_CONTINUE;
|
||||
|
||||
rc = iscsi_pdu_hdr_handle(&conn, req_pdu);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(!req_pdu->is_rejected);
|
||||
rc = iscsi_pdu_payload_handle(&conn, req_pdu);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
iscsi_put_pdu(req_pdu);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -2024,6 +2061,7 @@ main(int argc, char **argv)
|
||||
CU_ADD_TEST(suite, pdu_hdr_op_task_mgmt_test);
|
||||
CU_ADD_TEST(suite, pdu_hdr_op_nopout_test);
|
||||
CU_ADD_TEST(suite, pdu_hdr_op_data_test);
|
||||
CU_ADD_TEST(suite, empty_text_with_cbit_test);
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
|
@ -264,6 +264,14 @@ parse_valid_test(void)
|
||||
EXPECT_VAL("F", "IIII");
|
||||
CU_ASSERT_PTR_NULL(partial_parameter);
|
||||
|
||||
/* partial parameter: NULL data */
|
||||
/* It is technically allowed to have a TEXT PDU with no data, yet
|
||||
* CONTINUE bit is enabled - make sure we handle that case correctly.
|
||||
*/
|
||||
rc = iscsi_parse_params(¶ms, NULL, 0, true, &partial_parameter);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT_PTR_NULL(partial_parameter);
|
||||
|
||||
/* Second partial parameter is the only parameter */
|
||||
PARSE("OOOO", true, &partial_parameter);
|
||||
CU_ASSERT_STRING_EQUAL(partial_parameter, "OOOO");
|
||||
|
@ -2162,6 +2162,27 @@ test_nvme_ctrlr_init_set_keep_alive_timeout(void)
|
||||
nvme_ctrlr_destruct(&ctrlr);
|
||||
}
|
||||
|
||||
static void
|
||||
test_alloc_io_qpair_fail(void)
|
||||
{
|
||||
struct spdk_nvme_ctrlr ctrlr = {};
|
||||
struct spdk_nvme_qpair *q0;
|
||||
|
||||
setup_qpairs(&ctrlr, 1);
|
||||
|
||||
/* Modify the connect_qpair return code to inject a failure */
|
||||
g_connect_qpair_return_code = 1;
|
||||
|
||||
/* Attempt to allocate a qpair, this should fail */
|
||||
q0 = spdk_nvme_ctrlr_alloc_io_qpair(&ctrlr, NULL, 0);
|
||||
SPDK_CU_ASSERT_FATAL(q0 == NULL);
|
||||
|
||||
/* Verify that the qpair is removed from the lists */
|
||||
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&ctrlr.active_io_qpairs));
|
||||
|
||||
cleanup_qpairs(&ctrlr);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -2200,6 +2221,7 @@ int main(int argc, char **argv)
|
||||
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_nvmf_ioccsz);
|
||||
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_num_queues);
|
||||
CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_keep_alive_timeout);
|
||||
CU_ADD_TEST(suite, test_alloc_io_qpair_fail);
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
|
@ -267,28 +267,56 @@ create_controller_test(void)
|
||||
int ret;
|
||||
char long_name[PATH_MAX];
|
||||
|
||||
spdk_cpuset_set_cpu(&g_vhost_core_mask, 0, true);
|
||||
spdk_cpuset_parse(&g_vhost_core_mask, "0xf");
|
||||
|
||||
/* Create device with cpumask implcitly matching whole application */
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", NULL);
|
||||
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||
SPDK_CU_ASSERT_FATAL(!strcmp(spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)), "f"));
|
||||
cleanup_vdev(vdev);
|
||||
|
||||
/* Create device with cpumask matching whole application */
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0xf");
|
||||
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||
SPDK_CU_ASSERT_FATAL(!strcmp(spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)), "f"));
|
||||
cleanup_vdev(vdev);
|
||||
|
||||
/* Create device with single core in cpumask */
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0x2");
|
||||
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||
SPDK_CU_ASSERT_FATAL(!strcmp(spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)), "2"));
|
||||
cleanup_vdev(vdev);
|
||||
|
||||
/* Create device with cpumask spanning two cores */
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0x3");
|
||||
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||
SPDK_CU_ASSERT_FATAL(!strcmp(spdk_cpuset_fmt(spdk_thread_get_cpumask(vdev->thread)), "3"));
|
||||
cleanup_vdev(vdev);
|
||||
|
||||
/* Create device with incorrect cpumask outside of application cpumask */
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0xf0");
|
||||
SPDK_CU_ASSERT_FATAL(ret != 0);
|
||||
|
||||
/* Create device with incorrect cpumask partially outside of application cpumask */
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0xff");
|
||||
SPDK_CU_ASSERT_FATAL(ret != 0);
|
||||
|
||||
/* Create device with no name */
|
||||
ret = alloc_vdev(&vdev, NULL, "0x1");
|
||||
CU_ASSERT(ret != 0);
|
||||
|
||||
/* Create device with incorrect cpumask */
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0x2");
|
||||
ret = alloc_vdev(&vdev, NULL, NULL);
|
||||
CU_ASSERT(ret != 0);
|
||||
|
||||
/* Create device with too long name and path */
|
||||
memset(long_name, 'x', sizeof(long_name));
|
||||
long_name[PATH_MAX - 1] = 0;
|
||||
snprintf(dev_dirname, sizeof(dev_dirname), "some_path/");
|
||||
ret = alloc_vdev(&vdev, long_name, "0x1");
|
||||
ret = alloc_vdev(&vdev, long_name, NULL);
|
||||
CU_ASSERT(ret != 0);
|
||||
dev_dirname[0] = 0;
|
||||
|
||||
/* Create device when device name is already taken */
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", "0x1");
|
||||
ret = alloc_vdev(&vdev, "vdev_name_0", NULL);
|
||||
SPDK_CU_ASSERT_FATAL(ret == 0 && vdev);
|
||||
ret = alloc_vdev(&vdev2, "vdev_name_0", "0x1");
|
||||
ret = alloc_vdev(&vdev2, "vdev_name_0", NULL);
|
||||
CU_ASSERT(ret != 0);
|
||||
cleanup_vdev(vdev);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ function err_cleanup() {
|
||||
|
||||
# start vhost and configure it
|
||||
trap 'err_cleanup; exit 1' SIGINT SIGTERM EXIT
|
||||
$SPDK_BIN_DIR/vhost &
|
||||
$SPDK_BIN_DIR/vhost -m 0xf &
|
||||
vhost_pid=$!
|
||||
waitforlisten $vhost_pid
|
||||
|
||||
@ -35,17 +35,22 @@ rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 0 Nvme0n1p0
|
||||
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 1 Nvme0n1p1
|
||||
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 2 Nvme0n1p2
|
||||
rpc_cmd vhost_scsi_controller_add_target naa.Nvme0n1_scsi0.0 3 Nvme0n1p3
|
||||
[[ "$(rpc_cmd vhost_get_controllers -n naa.Nvme0n1_scsi0.0 | jq -r '.[].cpumask')" == "0xf" ]]
|
||||
|
||||
rpc_cmd vhost_create_blk_controller naa.Nvme0n1_blk0.0 Nvme0n1p4
|
||||
rpc_cmd vhost_create_blk_controller naa.Nvme0n1_blk1.0 Nvme0n1p5
|
||||
rpc_cmd vhost_create_blk_controller naa.Nvme0n1_blk0.0 Nvme0n1p4 --cpumask 0xf
|
||||
[[ "$(rpc_cmd vhost_get_controllers -n naa.Nvme0n1_blk0.0 | jq -r '.[].cpumask')" == "0xf" ]]
|
||||
rpc_cmd vhost_create_blk_controller naa.Nvme0n1_blk1.0 Nvme0n1p5 --cpumask 0x1
|
||||
[[ "$(rpc_cmd vhost_get_controllers -n naa.Nvme0n1_blk1.0 | jq -r '.[].cpumask')" == "0x1" ]]
|
||||
|
||||
rpc_cmd bdev_malloc_create 128 512 --name Malloc0
|
||||
rpc_cmd vhost_create_scsi_controller naa.Malloc0.0
|
||||
rpc_cmd vhost_create_scsi_controller naa.Malloc0.0 --cpumask 0x2
|
||||
rpc_cmd vhost_scsi_controller_add_target naa.Malloc0.0 0 Malloc0
|
||||
[[ "$(rpc_cmd vhost_get_controllers -n naa.Malloc0.0 | jq -r '.[].cpumask')" == "0x2" ]]
|
||||
|
||||
rpc_cmd bdev_malloc_create 128 4096 --name Malloc1
|
||||
rpc_cmd vhost_create_scsi_controller naa.Malloc1.0
|
||||
rpc_cmd vhost_create_scsi_controller naa.Malloc1.0 --cpumask 0xc
|
||||
rpc_cmd vhost_scsi_controller_add_target naa.Malloc1.0 0 Malloc1
|
||||
[[ "$(rpc_cmd vhost_get_controllers -n naa.Malloc1.0 | jq -r '.[].cpumask')" == "0xc" ]]
|
||||
|
||||
# start a dummy app, create vhost bdevs in it, then dump the config for FIO
|
||||
$SPDK_BIN_DIR/spdk_tgt -r /tmp/spdk2.sock -g &
|
||||
|
@ -63,7 +63,7 @@ notice "==============="
|
||||
notice ""
|
||||
notice "running SPDK"
|
||||
notice ""
|
||||
vhost_run 0
|
||||
vhost_run 0 "-m 0xf"
|
||||
notice ""
|
||||
rpc_py="$rootdir/scripts/rpc.py -s $(get_vhost_dir 0)/rpc.sock"
|
||||
$rpc_py bdev_malloc_create -b Malloc0 128 4096
|
||||
@ -88,8 +88,13 @@ if $rpc_py vhost_delete_controller unk0 > /dev/null; then
|
||||
fi
|
||||
|
||||
# SCSI
|
||||
notice "Trying to create scsi controller with incorrect cpumask"
|
||||
if $rpc_py vhost_create_scsi_controller vhost.invalid.cpumask --cpumask 0x2; then
|
||||
notice "Trying to create scsi controller with incorrect cpumask outside of application cpumask"
|
||||
if $rpc_py vhost_create_scsi_controller vhost.invalid.cpumask --cpumask 0xf0; then
|
||||
error "Creating scsi controller with incorrect cpumask succeeded, but it shouldn't"
|
||||
fi
|
||||
|
||||
notice "Trying to create scsi controller with incorrect cpumask partially outside of application cpumask"
|
||||
if $rpc_py vhost_create_scsi_controller vhost.invalid.cpumask --cpumask 0xff; then
|
||||
error "Creating scsi controller with incorrect cpumask succeeded, but it shouldn't"
|
||||
fi
|
||||
|
||||
@ -167,8 +172,13 @@ notice "Re-adding device 0 to naa.0"
|
||||
$rpc_py vhost_scsi_controller_add_target naa.0 0 Malloc0
|
||||
|
||||
# BLK
|
||||
notice "Trying to create block controller with incorrect cpumask"
|
||||
if $rpc_py vhost_create_blk_controller vhost.invalid.cpumask Malloc0 --cpumask 0x2; then
|
||||
notice "Trying to create block controller with incorrect cpumask outside of application cpumask"
|
||||
if $rpc_py vhost_create_blk_controller vhost.invalid.cpumask Malloc0 --cpumask 0xf0; then
|
||||
error "Creating block controller with incorrect cpumask succeeded, but it shouldn't"
|
||||
fi
|
||||
|
||||
notice "Trying to create block controller with incorrect cpumask partially outside of application cpumask"
|
||||
if $rpc_py vhost_create_blk_controller vhost.invalid.cpumask Malloc0 --cpumask 0xff; then
|
||||
error "Creating block controller with incorrect cpumask succeeded, but it shouldn't"
|
||||
fi
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user