Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6acb9a5875 | ||
|
5882a3621b | ||
|
c5f0959de6 | ||
|
1a970987df | ||
|
78554349e7 | ||
|
9da2afe938 | ||
|
c4e28a51a6 | ||
|
f7f016d5ef | ||
|
c2e522ec9e | ||
|
58a35d24d5 | ||
|
d7b0ae8913 | ||
|
bb9348e736 | ||
|
a10baa808e | ||
|
15edc31247 | ||
|
9d04c1d2f7 | ||
|
3f2d3a6ff2 | ||
|
d831e63353 | ||
|
fca143dcb0 | ||
|
10adee24ff | ||
|
0afad8dd11 | ||
|
d8f54aed9a | ||
|
b47e2267cf | ||
|
c0bf57f87d |
176
CHANGELOG.md
176
CHANGELOG.md
@ -1,6 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## v20.04: (Upcoming Release)
|
||||
## v20.04.2: (Upcoming Release)
|
||||
|
||||
## v20.04.1:
|
||||
|
||||
### dpdk
|
||||
|
||||
Updated DPDK submodule to DPDK 19.11.2, which includes fixes for DPDK vulnerabilities:
|
||||
CVE-2020-10722, CVE-2020-10723, CVE-2020-10724, CVE-2020-10725, CVE-2020-10724.
|
||||
|
||||
## v20.04:
|
||||
|
||||
### configuration
|
||||
|
||||
@ -8,6 +17,24 @@ Legacy INI style configuration for SPDK applications has been deprecated and wil
|
||||
removed in future release.
|
||||
Please switch to JSON-RPC configuration files and/or RPC driven run-time configuration.
|
||||
|
||||
### copy
|
||||
|
||||
The copy engine library, modules and public APIs have been renamed. Use of the word `copy`
|
||||
has been replaced with the word `accel` short for accelerator in preparation for adding new
|
||||
capabilities in the future. Additionally, APIs for what was previously called the `memcpy`
|
||||
engine have been renamed to identify the engine as a software accelerator.
|
||||
|
||||
### crypto
|
||||
|
||||
Support for AES_XTS was added for the QAT polled mode driver (pmd). The create RPC
|
||||
`bdev_crypto_create` has 2 new optional parameters: cipher and key2. Cipher can be either
|
||||
AES_CBC (default) or AES_XTS. AES_XTS is only valid when using the QAT polled mode driver.
|
||||
The key2 parameter is the second key required for AES_XTS.
|
||||
|
||||
### event
|
||||
|
||||
Reactors now accumulate CPU stats and they are retrieved by the RPC `framework_get_reactors`.
|
||||
|
||||
### idxd
|
||||
|
||||
IDXD support was added in the form of a low level library that can directly
|
||||
@ -16,51 +43,77 @@ with the generic accel framework API. IDXD is the first in a family of offload
|
||||
engines that share the same interface, specifically DSA is added here. More info
|
||||
can be found here: https://01.org/blogs/2019/introducing-intel-data-streaming-accelerator
|
||||
|
||||
Much of the implementation models IOAT, however their low level interfaces are very
|
||||
Much of the implementation models IOAT, however the low level interfaces are very
|
||||
different. The RPC to enable IDXD requires a configuration number as well. The
|
||||
code includes 2 pre-defined configurations of IDXD groups/work queues/engines. A future
|
||||
code includes two pre-defined configurations of IDXD groups/work queues/engines. A future
|
||||
version will provide an interface to allow for setting of individual configuration
|
||||
parameters.
|
||||
|
||||
IDXD is not yet available so this feature should be considered experimental. It will
|
||||
be built up with additional documentation as an ongoing activity.
|
||||
|
||||
### ocf
|
||||
|
||||
Update OCF submodule to OCF v20.03
|
||||
|
||||
New version of OCF comes with API changes and bug fixes
|
||||
|
||||
### nvme
|
||||
|
||||
Export internal nvme_ctrlr_cmd_security_receive/send() APIs as public APIs with "spdk_"
|
||||
prefix.
|
||||
|
||||
Added `priority` field in `spdk_nvme_transport_id`, this field is used to specify the priority
|
||||
of the NVMe-oF connection, and currently it is used for NVMe-oF tcp connection.
|
||||
|
||||
### copy
|
||||
|
||||
The copy engine library, modules and public APIs have been renamed. Use of the word `copy`
|
||||
has been replaced with the word `accel` short for accelerator in preparation for adding new
|
||||
capabilities in the future. Additionally, APIs for what was previously called the `memcpy`
|
||||
engine have been renamed to identify the engine as a software accelerator.
|
||||
|
||||
### event
|
||||
|
||||
Reactor now accumulates CPU stats and they are retrieved by the RPC `framework_get_reactors`.
|
||||
|
||||
### iSCSI
|
||||
### iscsi
|
||||
|
||||
The iSCSI target now creates a lightweight thread per poll group instead of assuming a pool
|
||||
of lightweight threads already exist at start up time. A poll group is a collection of
|
||||
unrelated iSCSI connections. Each poll group is only accessed from the associated
|
||||
lightweight thread.
|
||||
|
||||
### vmd
|
||||
### ftl
|
||||
|
||||
A new function, `spdk_vmd_fini`, has been added. It releases all resources acquired by the VMD
|
||||
library through the `spdk_vmd_init` call.
|
||||
Several changes have been made to the `spdk_ftl_conf`, `spdk_ftl_dev_init_ops`, and
|
||||
`spdk_ftl_attrs` structs. Please see `include/spdk/ftl.h` for more details.
|
||||
|
||||
### miscellaneous
|
||||
|
||||
The `--json-ignore-init-errors` command line parameter has been added to ignore
|
||||
initialization errors on JSON config load.
|
||||
|
||||
The public header file io_channel.h has been removed. Please use thread.h which has the
|
||||
exact same API.
|
||||
|
||||
### nvme
|
||||
|
||||
Exported internal nvme_ctrlr_cmd_security_receive/send() APIs as public APIs with "the spdk_"
|
||||
prefix.
|
||||
|
||||
Added `priority` field in `spdk_nvme_transport_id`, this field is used to specify the priority
|
||||
of the NVMe-oF connection, and currently it is used for NVMe-oF tcp connection.
|
||||
|
||||
A new poll group API has been added to allow for pooling of nvme qpairs across a single
|
||||
entity which can be polled for completions. This new API consists of the `spdk_nvme_poll_group`
|
||||
family of functions. As a result of this new API, all NVMe transports are expected to implement
|
||||
several poll group related functions.
|
||||
|
||||
A new flag, `create_only`, has been added to the `spdk_nvme_io_qpair_opts` structure. This flag
|
||||
allows a user to call `spdk_nvme_ctrlr_get_default_io_qpair` without also connecting the qpair
|
||||
within the context of that call.
|
||||
|
||||
As a result of the `create_only` flag, two new API functions, `spdk_nvme_ctrlr_connect_io_qpair`
|
||||
and `spdk_nvme_ctrlr_disconnect_io_qpair`, have been added to facilitate connecting newly created
|
||||
qpairs (for example, after they have been added to a poll group) and disconnecting qpairs without
|
||||
destroying them (for example to disconnect a qpair before migrating it to a new poll group and
|
||||
reconnecting it).
|
||||
|
||||
The functions `spdk_nvme_ctrlr_alloc_cmb_io_buffer` and `spdk_nvme_ctrlr_free_cmb_io_buffer`
|
||||
have been changed to `spdk_nvme_ctrlr_map_cmb` and `spdk_nvme_ctrlr_unmap_cmb` respectively.
|
||||
|
||||
An additional function, `spdk_nvme_ctrlr_reserve_cmb`, has been added to facilitate reserving
|
||||
the entire size of the controller memory buffer for data transfer.
|
||||
|
||||
### nvme_cuse
|
||||
|
||||
`spdk_nvme_cuse_get_ctrlr_name` now takes two additional parameters, `char *name` which
|
||||
stores the pointer to the controller name, and `size_t *size` which stores the length of
|
||||
the name. The return type has also been changed from char * to int.
|
||||
|
||||
`spdk_nvme_cuse_get_ns_name` now takes two additional parameters, `char *name` which
|
||||
stores the pointer to the namespace name, and `size_t *size` which stores the length of
|
||||
the name. The return type has also been changed from char * to int.
|
||||
|
||||
### nvme_opal
|
||||
|
||||
Several public OPAL structure definitions have been changed since the last release.
|
||||
|
||||
### nvmf
|
||||
|
||||
@ -71,36 +124,49 @@ of lightweight threads already exist at start up time. A poll group is a collect
|
||||
unrelated NVMe-oF connections. Each poll group is only accessed from the associated
|
||||
lightweight thread.
|
||||
|
||||
### Miscellaneous
|
||||
A new struct, `spdk_nvmf_subsystem_listener`, has been added to encapsulate the subsystem specific
|
||||
nature of a listener object.
|
||||
|
||||
`--json-ignore-init-errors` command line param has been added to ignore initialization errors
|
||||
on JSON config load.
|
||||
`spdk_nvmf_tgt_listen` no longer accepts a callback function or argument. It also returns an
|
||||
int to indicate the status of the listen call.
|
||||
|
||||
The public header file io_channel.h has been removed. Please use thread.h which has the
|
||||
exact same API.
|
||||
The execution of `spdk_nvme_poll_group_destroy` is now asynchronous and the function accepts
|
||||
a cb_fn and cb_arg to call upon completion.
|
||||
|
||||
### crypto
|
||||
The execution of `spdk_nvmf_subsystem_add_listener` is now asynchronous and the function accepts
|
||||
a cb_fn and cb_arg to call upon completion.
|
||||
|
||||
Support for AES_XTS was added for the QAT polled mode driver (pmd). The create RPC
|
||||
`bdev_crypto_create` has 2 new optional parameters: cipher and key2. Cipher can be either
|
||||
AES_CBC (default) or AES_XTS. AES_XTS is only valid when using the QAT polled mode driver.
|
||||
The key2 parameter is the second key required for AES_XTS.
|
||||
The `nvmf_transport.h` header has been made public to allow custom NVMe-oF transports to integrate
|
||||
with NVMe-oF libraries without using internal APIs.
|
||||
|
||||
### util
|
||||
### ocf
|
||||
|
||||
New functions `spdk_sn32_lt` and `spdk_sn32_gt` have been added. They compare two sequence
|
||||
numbers based on serial number arithmetic.
|
||||
Updated the OCF submodule to OCF v20.03
|
||||
|
||||
New version of OCF comes with API changes and bug fixes
|
||||
|
||||
### rpc
|
||||
|
||||
A new RPC `thread_set_cpumask` has been added to set the cpumask of the thread
|
||||
to the specified value.
|
||||
|
||||
A new RPC `thread_get_pollers` has been added to retrieve pollers of SPDK threads.
|
||||
A new RPC `thread_get_pollers` has been added to retrieve pollers from SPDK threads.
|
||||
|
||||
A new RPC `thread_get_io_channels` has been added to retrieve I/O channels of SPDK threads.
|
||||
A new RPC `thread_get_io_channels` has been added to retrieve I/O channels from SPDK threads.
|
||||
|
||||
A new RPC `bdev_rbd_resize` has been added to resize the Ceph RBD bdev.
|
||||
A new RPC `bdev_rbd_resize` has been added to resize Ceph RBD bdevs.
|
||||
|
||||
### sock
|
||||
|
||||
The `spdk_sock_set_priority` function has been removed since the feature to set the sock priority
|
||||
will be contained in two new functions, i.e., `spdk_sock_listen_ext` and `spdk_sock_connect_ext`.
|
||||
Users may now specify the priority of the socket in the opts that they want to use.
|
||||
|
||||
### spdk_top
|
||||
|
||||
A new application, `spdk_top`, has been added which allows users to monitor resource consumption
|
||||
by a running SPDK application. More information on this application can be found in
|
||||
`app/spdk_top/README`.
|
||||
|
||||
### thread
|
||||
|
||||
@ -113,7 +179,7 @@ Current SPDK operation types are `SPDK_THREAD_OP_NEW` and `SPDK_THREAD_OP_RESCHE
|
||||
The operation `SPDK_THREAD_OP_NEW` is called each time a new thread is created.
|
||||
The operation `SPDK_THREAD_OP_RESCHED` is called when SPDK thread needs to be rescheduled.
|
||||
|
||||
An unique ID has been added for each created SPDK thread, it is retrieved by a new function
|
||||
A unique ID has been added for each created SPDK thread, it is retrieved by a new function
|
||||
`spdk_thread_get_id`, and the SPDK thread which has the specific ID is got by
|
||||
a new function `spdk_thread_get_by_id`.
|
||||
|
||||
@ -130,15 +196,19 @@ threads configuration, and a new function `spdk_thread_get_last_tsc` has been ad
|
||||
Voluntary termination of SPDK thread has been supported by refining the functions `spdk_thread_exit`
|
||||
and `spdk_thread_poll`.
|
||||
|
||||
### util
|
||||
|
||||
New functions `spdk_sn32_lt` and `spdk_sn32_gt` have been added. They compare two sequence
|
||||
numbers based on serial number arithmetic.
|
||||
|
||||
### vhost
|
||||
|
||||
Poll groups per session have been replaced by SPDK threads per vhost controller.
|
||||
|
||||
### sock
|
||||
### vmd
|
||||
|
||||
Remove `spdk_sock_set_priority` function since the feature to set the sock priority will be
|
||||
contained in two new functions, i.e., `spdk_sock_listen_ext` and `spdk_sock_connect_ext`.
|
||||
Users may now specify the priority of the socket in the opts that they want to use.
|
||||
A new function, `spdk_vmd_fini`, has been added. It releases all resources acquired by the VMD
|
||||
library through the `spdk_vmd_init` call.
|
||||
|
||||
## v20.01
|
||||
|
||||
|
@ -944,6 +944,10 @@ store_last_run_counter(const char *poller_name, uint64_t thread_id, uint64_t las
|
||||
}
|
||||
|
||||
history = calloc(1, sizeof(*history));
|
||||
if (history == NULL) {
|
||||
fprintf(stderr, "Unable to allocate a history object in store_last_run_counter.\n");
|
||||
return;
|
||||
}
|
||||
history->poller_name = strdup(poller_name);
|
||||
history->thread_id = thread_id;
|
||||
history->last_run_counter = last_run_counter;
|
||||
@ -983,8 +987,10 @@ sort_pollers(const void *p1, const void *p2, void *arg)
|
||||
return strcmp(poller1->thread_name, poller2->thread_name);
|
||||
case 3: /* Sort by run counter */
|
||||
last_run_counter = get_last_run_counter(poller1->name, poller1->thread_id);
|
||||
assert(last_run_counter != NULL);
|
||||
count1 = poller1->run_count - *last_run_counter;
|
||||
last_run_counter = get_last_run_counter(poller2->name, poller2->thread_id);
|
||||
assert(last_run_counter != NULL);
|
||||
count2 = poller2->run_count - *last_run_counter;
|
||||
break;
|
||||
case 4: /* Sort by period */
|
||||
@ -1021,6 +1027,7 @@ copy_pollers(struct rpc_pollers *pollers, uint64_t pollers_count, enum spdk_poll
|
||||
last_run_counter = get_last_run_counter(pollers->pollers[i].name, thread->id);
|
||||
}
|
||||
|
||||
assert(last_run_counter != NULL);
|
||||
*last_run_counter = pollers->pollers[i].run_count;
|
||||
}
|
||||
pollers_info[*current_count] = &pollers->pollers[i];
|
||||
@ -1113,6 +1120,7 @@ refresh_pollers_tab(uint8_t current_page)
|
||||
|
||||
if (!col_desc[3].disabled) {
|
||||
last_run_counter = get_last_run_counter(pollers[i]->name, pollers[i]->thread_id);
|
||||
assert(last_run_counter != NULL);
|
||||
|
||||
snprintf(run_count, MAX_TIME_STR_LEN, "%" PRIu64, pollers[i]->run_count - *last_run_counter);
|
||||
print_max_len(g_tabs[POLLERS_TAB], TABS_DATA_START_ROW + item_index, col,
|
||||
@ -1377,6 +1385,10 @@ draw_filtering_menu(uint8_t position, WINDOW *filter_win, uint8_t tab, MENU **my
|
||||
elements = i;
|
||||
|
||||
my_items = (ITEM **)calloc(elements * WINDOW_COLUMNS + ADDITIONAL_ELEMENTS, sizeof(ITEM *));
|
||||
if (my_items == NULL) {
|
||||
fprintf(stderr, "Unable to allocate an item list in draw_filtering_menu.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < elements * 2; i++) {
|
||||
my_items[i] = new_item(col_desc[i / WINDOW_COLUMNS].name, NULL);
|
||||
@ -1441,7 +1453,7 @@ filter_columns(uint8_t tab)
|
||||
PANEL *filter_panel;
|
||||
WINDOW *filter_win;
|
||||
ITEM **my_items;
|
||||
MENU *my_menu;
|
||||
MENU *my_menu = NULL;
|
||||
int i, c, elements;
|
||||
bool stop_loop = false;
|
||||
ITEM *cur;
|
||||
@ -1552,6 +1564,10 @@ change_sorting(uint8_t tab)
|
||||
elements = i;
|
||||
|
||||
my_items = (ITEM **)calloc(elements + 1, sizeof(ITEM *));
|
||||
if (my_items == NULL) {
|
||||
fprintf(stderr, "Unable to allocate an item list in change_sorting.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < elements; ++i) {
|
||||
my_items[i] = new_item(g_col_desc[tab][i].name, NULL);
|
||||
|
@ -35,7 +35,12 @@ fi
|
||||
|
||||
timing_enter build_release
|
||||
|
||||
./configure $(get_config_params) --disable-debug --enable-lto
|
||||
if [ $(uname -s) = Linux ]; then
|
||||
./configure $(get_config_params) --disable-debug --enable-lto --disable-unit-tests
|
||||
else
|
||||
# LTO needs a special compiler to work on BSD.
|
||||
./configure $(get_config_params) --disable-debug
|
||||
fi
|
||||
$MAKE ${MAKEFLAGS}
|
||||
$MAKE ${MAKEFLAGS} clean
|
||||
|
||||
|
5
configure
vendored
5
configure
vendored
@ -494,6 +494,11 @@ if [[ "${CONFIG[ISAL]}" = "n" ]] && [[ "${CONFIG[REDUCE]}" = "y" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${CONFIG[LTO]}" = "y" ]] && [[ "${CONFIG[UNIT_TESTS]}" = "y" ]]; then
|
||||
echo "ERROR Conflicting options: --enable-lto is not compatible with --enable-unit-tests."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${CONFIG[ENV]}" ]; then
|
||||
CONFIG[ENV]=$rootdir/lib/env_dpdk
|
||||
echo "Using default SPDK env in ${CONFIG[ENV]}"
|
||||
|
2
dpdk
2
dpdk
@ -1 +1 @@
|
||||
Subproject commit 76f9669b1f4cdd52bae2c3408ad129272bf99d1f
|
||||
Subproject commit ef71bfaface10cc19b75e45d3158ab71a788e3a9
|
@ -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.
|
||||
|
@ -71,7 +71,6 @@ static struct spdk_conf *default_config = NULL;
|
||||
struct spdk_conf *
|
||||
spdk_conf_allocate(void)
|
||||
{
|
||||
SPDK_ERRLOG("INI configuration has been deprecated and will be removed in a future release. Please switch to JSON-RPC.\n");
|
||||
return calloc(1, sizeof(struct spdk_conf));
|
||||
}
|
||||
|
||||
@ -611,6 +610,7 @@ spdk_conf_read(struct spdk_conf *cp, const char *file)
|
||||
if (file == NULL || file[0] == '\0') {
|
||||
return -1;
|
||||
}
|
||||
SPDK_ERRLOG("INI configuration has been deprecated and will be removed in a future release. Please switch to JSON-RPC.\n");
|
||||
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL) {
|
||||
|
@ -78,6 +78,11 @@ ifneq (, $(wildcard $(DPDK_ABS_DIR)/lib/librte_bus_pci.*))
|
||||
DPDK_LIB_LIST += rte_bus_pci
|
||||
endif
|
||||
|
||||
# DPDK 20.05 eal dependency
|
||||
ifneq (, $(wildcard $(DPDK_ABS_DIR)/lib/librte_telemetry.*))
|
||||
DPDK_LIB_LIST += rte_telemetry
|
||||
endif
|
||||
|
||||
# There are some complex dependencies when using crypto, reduce or both so
|
||||
# here we add the feature specific ones and set a flag to add the common
|
||||
# ones after that.
|
||||
|
@ -77,8 +77,8 @@ void pci_driver_register(struct spdk_pci_driver *driver);
|
||||
int pci_device_init(struct rte_pci_driver *driver, struct rte_pci_device *device);
|
||||
int pci_device_fini(struct rte_pci_device *device);
|
||||
|
||||
void pci_init(void);
|
||||
void pci_fini(void);
|
||||
void pci_env_init(void);
|
||||
void pci_env_fini(void);
|
||||
int mem_map_init(bool legacy_mem);
|
||||
int vtophys_init(void);
|
||||
|
||||
|
@ -499,7 +499,7 @@ spdk_env_dpdk_post_init(bool legacy_mem)
|
||||
{
|
||||
int rc;
|
||||
|
||||
pci_init();
|
||||
pci_env_init();
|
||||
|
||||
rc = mem_map_init(legacy_mem);
|
||||
if (rc < 0) {
|
||||
@ -519,7 +519,7 @@ spdk_env_dpdk_post_init(bool legacy_mem)
|
||||
void
|
||||
spdk_env_dpdk_post_fini(void)
|
||||
{
|
||||
pci_fini();
|
||||
pci_env_fini();
|
||||
|
||||
spdk_free_args(g_eal_cmdline, g_eal_cmdline_argcount);
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ _get_alarm_thread_cb(void *unused)
|
||||
}
|
||||
|
||||
void
|
||||
pci_init(void)
|
||||
pci_env_init(void)
|
||||
{
|
||||
#if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0)
|
||||
struct spdk_pci_driver *driver;
|
||||
@ -298,7 +298,7 @@ pci_init(void)
|
||||
}
|
||||
|
||||
void
|
||||
pci_fini(void)
|
||||
pci_env_fini(void)
|
||||
{
|
||||
struct spdk_pci_device *dev;
|
||||
char bdf[32];
|
||||
|
@ -1611,6 +1611,7 @@ ftl_update_l2p(struct spdk_ftl_dev *dev, const struct ftl_wbuf_entry *entry,
|
||||
struct ftl_wbuf_entry *prev;
|
||||
struct ftl_band *band;
|
||||
int valid;
|
||||
bool io_weak = entry->io_flags & FTL_IO_WEAK;
|
||||
|
||||
prev_addr = ftl_l2p_get(dev, entry->lba);
|
||||
if (ftl_addr_invalid(prev_addr)) {
|
||||
@ -1618,14 +1619,7 @@ ftl_update_l2p(struct spdk_ftl_dev *dev, const struct ftl_wbuf_entry *entry,
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the L2P's physical address is different than what we expected we don't need to */
|
||||
/* do anything (someone's already overwritten our data). */
|
||||
if ((entry->io_flags & FTL_IO_WEAK) && !ftl_addr_cmp(prev_addr, entry->addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ftl_addr_cached(prev_addr)) {
|
||||
assert(!(entry->io_flags & FTL_IO_WEAK));
|
||||
prev = ftl_get_entry_from_addr(dev, prev_addr);
|
||||
pthread_spin_lock(&prev->lock);
|
||||
|
||||
@ -1634,12 +1628,33 @@ ftl_update_l2p(struct spdk_ftl_dev *dev, const struct ftl_wbuf_entry *entry,
|
||||
prev_addr = ftl_l2p_get(dev, entry->lba);
|
||||
|
||||
/* If the entry is no longer in cache, another write has been */
|
||||
/* scheduled in the meantime, so we have to invalidate its LBA */
|
||||
/* scheduled in the meantime, so we can return to evicted path */
|
||||
if (!ftl_addr_cached(prev_addr)) {
|
||||
ftl_invalidate_addr(dev, prev_addr);
|
||||
pthread_spin_unlock(&prev->lock);
|
||||
goto evicted;
|
||||
}
|
||||
|
||||
/* If previous entry is part of cache, remove and invalidate it */
|
||||
/*
|
||||
* Relocating block could still reside in cache due to fact that write
|
||||
* buffers are independent for each IO channel and enough amount of data
|
||||
* (write unit size) must be collected before it will be submitted to lower
|
||||
* layer.
|
||||
* When previous entry wasn't overwritten invalidate old address and entry.
|
||||
* Otherwise skip relocating block.
|
||||
*/
|
||||
if (io_weak &&
|
||||
/* Check if prev_addr was updated in meantime */
|
||||
!(ftl_addr_cmp(prev_addr, ftl_get_addr_from_entry(prev)) &&
|
||||
/* Check if relocating address it the same as in previous entry */
|
||||
ftl_addr_cmp(prev->addr, entry->addr))) {
|
||||
pthread_spin_unlock(&prev->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If previous entry is part of cache and was written into disk remove
|
||||
* and invalidate it
|
||||
*/
|
||||
if (prev->valid) {
|
||||
ftl_invalidate_addr(dev, prev->addr);
|
||||
prev->valid = false;
|
||||
@ -1650,6 +1665,15 @@ ftl_update_l2p(struct spdk_ftl_dev *dev, const struct ftl_wbuf_entry *entry,
|
||||
return;
|
||||
}
|
||||
|
||||
evicted:
|
||||
/*
|
||||
* If the L2P's physical address is different than what we expected we don't need to
|
||||
* do anything (someone's already overwritten our data).
|
||||
*/
|
||||
if (io_weak && !ftl_addr_cmp(prev_addr, entry->addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Lock the band containing previous physical address. This assures atomic changes to */
|
||||
/* the L2P as wall as metadata. The valid bits in metadata are used to */
|
||||
/* check weak writes validity. */
|
||||
@ -1660,7 +1684,7 @@ ftl_update_l2p(struct spdk_ftl_dev *dev, const struct ftl_wbuf_entry *entry,
|
||||
|
||||
/* If the address has been invalidated already, we don't want to update */
|
||||
/* the L2P for weak writes, as it means the write is no longer valid. */
|
||||
if (!(entry->io_flags & FTL_IO_WEAK) || valid) {
|
||||
if (!io_weak || valid) {
|
||||
ftl_l2p_set(dev, entry->lba, addr);
|
||||
}
|
||||
|
||||
|
@ -923,6 +923,11 @@ ftl_dev_get_zone_info_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_ar
|
||||
"zone id: %"PRIu64"\n", init_ctx->zone_id);
|
||||
}
|
||||
|
||||
/* Set write pointer to the last block plus one for zone in full state */
|
||||
if (zone->info.state == SPDK_BDEV_ZONE_STATE_FULL) {
|
||||
zone->info.write_pointer = zone->info.zone_id + zone->info.capacity;
|
||||
}
|
||||
|
||||
if (zone->info.state != SPDK_BDEV_ZONE_STATE_OFFLINE) {
|
||||
band->num_zones++;
|
||||
CIRCLEQ_INSERT_TAIL(&band->zones, zone, circleq);
|
||||
|
@ -1629,7 +1629,7 @@ static void
|
||||
nvme_rdma_ctrlr_disconnect_qpair(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair)
|
||||
{
|
||||
struct nvme_rdma_qpair *rqpair = nvme_rdma_qpair(qpair);
|
||||
struct nvme_rdma_ctrlr *rctrlr;
|
||||
struct nvme_rdma_ctrlr *rctrlr = NULL;
|
||||
struct nvme_rdma_cm_event_entry *entry, *tmp;
|
||||
|
||||
nvme_rdma_unregister_mem(rqpair);
|
||||
@ -1658,8 +1658,7 @@ nvme_rdma_ctrlr_disconnect_qpair(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme
|
||||
|
||||
if (rqpair->cm_id) {
|
||||
rdma_disconnect(rqpair->cm_id);
|
||||
if (qpair->ctrlr != NULL) {
|
||||
|
||||
if (rctrlr != NULL) {
|
||||
if (nvme_rdma_process_event(rqpair, rctrlr->cm_channel, RDMA_CM_EVENT_DISCONNECTED)) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Target did not respond to qpair disconnect.\n");
|
||||
}
|
||||
|
@ -1121,18 +1121,17 @@ spdk_vhost_scsi_dev_remove_tgt(struct spdk_vhost_dev *vdev, unsigned scsi_tgt_nu
|
||||
svdev = to_scsi_dev(vdev);
|
||||
assert(svdev != NULL);
|
||||
scsi_dev_state = &svdev->scsi_dev_state[scsi_tgt_num];
|
||||
|
||||
if (scsi_dev_state->status != VHOST_SCSI_DEV_PRESENT) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (scsi_dev_state->dev == NULL || scsi_dev_state->status == VHOST_SCSI_DEV_ADDING) {
|
||||
SPDK_ERRLOG("%s: SCSI target %u is not occupied\n", vdev->name, scsi_tgt_num);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
assert(scsi_dev_state->status != VHOST_SCSI_DEV_EMPTY);
|
||||
if (scsi_dev_state->status != VHOST_SCSI_DEV_PRESENT) {
|
||||
SPDK_WARNLOG("%s: SCSI target %u has been already marked for hotremoval.\n",
|
||||
vdev->name, scsi_tgt_num);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
SPDK_ERRLOG("calloc failed\n");
|
||||
|
@ -1204,9 +1204,18 @@ _device_unregister_cb(void *io_device)
|
||||
rte_cryptodev_sym_session_free(crypto_bdev->session_decrypt);
|
||||
rte_cryptodev_sym_session_free(crypto_bdev->session_encrypt);
|
||||
free(crypto_bdev->drv_name);
|
||||
if (crypto_bdev->key) {
|
||||
memset(crypto_bdev->key, 0, strnlen(crypto_bdev->key, (AES_CBC_KEY_LENGTH + 1)));
|
||||
free(crypto_bdev->key);
|
||||
}
|
||||
if (crypto_bdev->key2) {
|
||||
memset(crypto_bdev->key2, 0, strnlen(crypto_bdev->key2, (AES_XTS_KEY_LENGTH + 1)));
|
||||
free(crypto_bdev->key2);
|
||||
}
|
||||
if (crypto_bdev->xts_key) {
|
||||
memset(crypto_bdev->xts_key, 0, strnlen(crypto_bdev->xts_key, (AES_XTS_KEY_LENGTH * 2) + 1));
|
||||
free(crypto_bdev->xts_key);
|
||||
}
|
||||
free(crypto_bdev->crypto_bdev.name);
|
||||
free(crypto_bdev);
|
||||
}
|
||||
|
@ -58,6 +58,7 @@
|
||||
enum spdk_sock_task_type {
|
||||
SPDK_SOCK_TASK_POLLIN = 0,
|
||||
SPDK_SOCK_TASK_WRITE,
|
||||
SPDK_SOCK_TASK_CANCEL,
|
||||
};
|
||||
|
||||
enum spdk_uring_sock_task_status {
|
||||
@ -82,6 +83,7 @@ struct spdk_uring_sock {
|
||||
struct spdk_uring_sock_group_impl *group;
|
||||
struct spdk_uring_task write_task;
|
||||
struct spdk_uring_task pollin_task;
|
||||
struct spdk_uring_task cancel_task;
|
||||
int outstanding_io;
|
||||
struct spdk_pipe *recv_pipe;
|
||||
void *recv_buf;
|
||||
@ -858,6 +860,26 @@ _sock_prep_pollin(struct spdk_sock *_sock)
|
||||
task->status = SPDK_URING_SOCK_TASK_IN_PROCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_sock_prep_cancel_task(struct spdk_sock *_sock, void *user_data)
|
||||
{
|
||||
struct spdk_uring_sock *sock = __uring_sock(_sock);
|
||||
struct spdk_uring_task *task = &sock->cancel_task;
|
||||
struct io_uring_sqe *sqe;
|
||||
|
||||
if (task->status == SPDK_URING_SOCK_TASK_IN_PROCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(sock->group != NULL);
|
||||
sock->group->io_queued++;
|
||||
|
||||
sqe = io_uring_get_sqe(&sock->group->uring);
|
||||
io_uring_prep_cancel(sqe, user_data, 0);
|
||||
io_uring_sqe_set_data(sqe, task);
|
||||
task->status = SPDK_URING_SOCK_TASK_IN_PROCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_sock_uring_group_reap(struct spdk_uring_sock_group_impl *group, int max, int max_read_events,
|
||||
struct spdk_sock **socks)
|
||||
@ -919,7 +941,6 @@ spdk_sock_uring_group_reap(struct spdk_uring_sock_group_impl *group, int max, in
|
||||
if (spdk_unlikely(task->sock->outstanding_io > 0 &&
|
||||
TAILQ_EMPTY(&sock->base.pending_reqs))) {
|
||||
if (--sock->outstanding_io == 0) {
|
||||
sock->group = NULL;
|
||||
/* Just for sock close case */
|
||||
if (sock->base.flags.closed) {
|
||||
spdk_uring_sock_close(&sock->base);
|
||||
@ -927,6 +948,11 @@ spdk_sock_uring_group_reap(struct spdk_uring_sock_group_impl *group, int max, in
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SPDK_SOCK_TASK_CANCEL:
|
||||
if ((status == 0) && (sock->outstanding_io > 0)) {
|
||||
sock->outstanding_io--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SPDK_UNREACHABLE();
|
||||
@ -1151,32 +1177,15 @@ spdk_uring_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group,
|
||||
sock->pollin_task.sock = sock;
|
||||
sock->pollin_task.type = SPDK_SOCK_TASK_POLLIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
sock->cancel_task.sock = sock;
|
||||
sock->cancel_task.type = SPDK_SOCK_TASK_CANCEL;
|
||||
|
||||
static int
|
||||
spdk_uring_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group,
|
||||
struct spdk_sock *_sock)
|
||||
{
|
||||
struct spdk_uring_sock *sock = __uring_sock(_sock);
|
||||
struct spdk_uring_sock_group_impl *group = __uring_group_impl(_group);
|
||||
|
||||
if (sock->write_task.status != SPDK_URING_SOCK_TASK_NOT_IN_USE) {
|
||||
sock->outstanding_io++;
|
||||
}
|
||||
|
||||
if (sock->pollin_task.status != SPDK_URING_SOCK_TASK_NOT_IN_USE) {
|
||||
sock->outstanding_io++;
|
||||
}
|
||||
|
||||
if ((sock->recv_pipe != NULL) &&
|
||||
spdk_pipe_reader_bytes_available(sock->recv_pipe) > 0) {
|
||||
TAILQ_REMOVE(&group->pending_recv, sock, link);
|
||||
sock->pending_recv = false;
|
||||
}
|
||||
|
||||
if (!sock->outstanding_io) {
|
||||
sock->group = NULL;
|
||||
/* switched from another polling group due to scheduling */
|
||||
if (spdk_unlikely(sock->recv_pipe != NULL &&
|
||||
(spdk_pipe_reader_bytes_available(sock->recv_pipe) > 0))) {
|
||||
assert(sock->pending_recv == false);
|
||||
sock->pending_recv = true;
|
||||
TAILQ_INSERT_TAIL(&group->pending_recv, sock, link);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1220,6 +1229,41 @@ spdk_uring_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_eve
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_uring_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group,
|
||||
struct spdk_sock *_sock)
|
||||
{
|
||||
struct spdk_uring_sock *sock = __uring_sock(_sock);
|
||||
struct spdk_uring_sock_group_impl *group = __uring_group_impl(_group);
|
||||
|
||||
if (sock->write_task.status != SPDK_URING_SOCK_TASK_NOT_IN_USE) {
|
||||
/* For write, we do not need to cancel it */
|
||||
sock->outstanding_io++;
|
||||
}
|
||||
|
||||
if (sock->pollin_task.status != SPDK_URING_SOCK_TASK_NOT_IN_USE) {
|
||||
sock->outstanding_io++;
|
||||
_sock_prep_cancel_task(_sock, &sock->pollin_task);
|
||||
}
|
||||
|
||||
|
||||
/* Since spdk_sock_group_remove_sock is not asynchronous interface, so
|
||||
* currently can use a while loop here. */
|
||||
while (sock->pollin_task.status != SPDK_URING_SOCK_TASK_NOT_IN_USE) {
|
||||
spdk_uring_sock_group_impl_poll(_group, 32, NULL);
|
||||
}
|
||||
|
||||
if (sock->recv_pipe != NULL) {
|
||||
if (spdk_pipe_reader_bytes_available(sock->recv_pipe) > 0) {
|
||||
TAILQ_REMOVE(&group->pending_recv, sock, link);
|
||||
sock->pending_recv = false;
|
||||
}
|
||||
assert(sock->pending_recv == false);
|
||||
}
|
||||
sock->group = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_uring_sock_group_impl_close(struct spdk_sock_group_impl *_group)
|
||||
{
|
||||
@ -1242,9 +1286,15 @@ spdk_uring_sock_group_impl_close(struct spdk_sock_group_impl *_group)
|
||||
static int
|
||||
spdk_uring_sock_flush(struct spdk_sock *_sock)
|
||||
{
|
||||
struct spdk_uring_sock *sock = __uring_sock(_sock);
|
||||
|
||||
if (!sock->group) {
|
||||
return _sock_flush_client(_sock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spdk_net_impl g_uring_net_impl = {
|
||||
.name = "uring",
|
||||
.getaddr = spdk_uring_sock_getaddr,
|
||||
|
@ -2,12 +2,12 @@
|
||||
%bcond_with doc
|
||||
|
||||
Name: spdk
|
||||
Version: master
|
||||
Version: 20.04.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/v20.04.x.tar.gz
|
||||
Summary: Set of libraries and utilities for high performance user-mode storage
|
||||
|
||||
%define package_version %{epoch}:%{version}-%{release}
|
||||
|
@ -827,7 +827,9 @@ function discover_bdevs()
|
||||
local rootdir=$1
|
||||
local config_file=$2
|
||||
local cfg_type=$3
|
||||
local wait_for_spdk_bdev=${4:-30}
|
||||
shift 3
|
||||
local bdev_svc_opts=("$@")
|
||||
local wait_for_spdk_bdev=30
|
||||
local rpc_server=/var/tmp/spdk-discover-bdevs.sock
|
||||
|
||||
if [ ! -e $config_file ]; then
|
||||
@ -841,7 +843,7 @@ function discover_bdevs()
|
||||
|
||||
# Start the bdev service to query for the list of available
|
||||
# bdevs.
|
||||
$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 \
|
||||
$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 "${bdev_svc_opts[@]}" \
|
||||
$cfg_type $config_file &>/dev/null &
|
||||
stubpid=$!
|
||||
while ! [ -e /var/run/spdk_bdev0 ]; do
|
||||
|
@ -22,11 +22,11 @@ $spdkcli_job "'/bdevs/malloc create 32 512 Malloc0' 'Malloc0' True
|
||||
'/bdevs/malloc create 32 512 Malloc1' 'Malloc1' True
|
||||
"
|
||||
pci_blk=$(lspci -nn -D | grep '1af4:1001' | head -1 | awk '{print $1;}')
|
||||
if [ -n "$pci_blk" ]; then
|
||||
if [ -n "$pci_blk" ] && grep -Eq "DRIVER=(uio|vfio)" "/sys/bus/pci/devices/$pci_blk/uevent"; then
|
||||
$spdkcli_job "'/bdevs/virtioblk_disk create virtioblk_pci pci $pci_blk' 'virtioblk_pci' True"
|
||||
fi
|
||||
pci_scsi=$(lspci -nn -D | grep '1af4:1004' | head -1 | awk '{print $1;}')
|
||||
if [ -n "$pci_scsi" ]; then
|
||||
if [ -n "$pci_scsi" ] && grep -Eq "DRIVER=(uio|vfio)" "/sys/bus/pci/devices/$pci_scsi/uevent"; then
|
||||
$spdkcli_job "'/bdevs/virtioscsi_disk create virtioscsi_pci pci $pci_scsi' 'virtioscsi_pci' True"
|
||||
fi
|
||||
$spdkcli_job "'/vhost/scsi create sample_scsi' 'sample_scsi' True
|
||||
@ -63,10 +63,10 @@ $spdkcli_job "'/vhost/block delete sample_block' 'sample_block'
|
||||
'/vhost/scsi/sample_scsi remove_target 0' 'Malloc0'
|
||||
'/vhost/scsi delete sample_scsi' 'sample_scsi'
|
||||
"
|
||||
if [ -n "$pci_blk" ]; then
|
||||
if [ -n "$pci_blk" ] && grep -Eq "DRIVER=(uio|vfio)" "/sys/bus/pci/devices/$pci_blk/uevent"; then
|
||||
$spdkcli_job "'/bdevs/virtioblk_disk delete virtioblk_pci' 'virtioblk_pci'"
|
||||
fi
|
||||
if [ -n "$pci_scsi" ]; then
|
||||
if [ -n "$pci_scsi" ] && grep -Eq "DRIVER=(uio|vfio)" "/sys/bus/pci/devices/$pci_scsi/uevent"; then
|
||||
$spdkcli_job "'/bdevs/virtioscsi_disk delete virtioscsi_pci' 'virtioscsi_pci'"
|
||||
fi
|
||||
$spdkcli_job "'/bdevs/malloc delete Malloc0' 'Malloc0'
|
||||
|
@ -58,6 +58,7 @@ function run_spdk_fio() {
|
||||
function create_bdev_config()
|
||||
{
|
||||
local vbdevs
|
||||
local g_opt
|
||||
|
||||
if [ -z "$($RPC_PY bdev_get_bdevs | jq '.[] | select(.name=="Nvme0n1")')" ]; then
|
||||
error "Nvme0n1 bdev not found!"
|
||||
@ -82,7 +83,13 @@ function create_bdev_config()
|
||||
$RPC_PY vhost_create_scsi_controller naa.Malloc1.0
|
||||
$RPC_PY vhost_scsi_controller_add_target naa.Malloc1.0 0 Malloc1
|
||||
|
||||
vbdevs=$(discover_bdevs $rootdir $testdir/bdev.json "--json")
|
||||
# Check default size of host hugepages. If it's 2MB then we have to use
|
||||
# bdev_svc "-g" option for virtio devices.
|
||||
if (( $(grep "Hugepagesize" /proc/meminfo | grep -Eo "[[:digit:]]+") == 2048 )); then
|
||||
g_opt="-g"
|
||||
fi
|
||||
|
||||
vbdevs=$(discover_bdevs $rootdir $testdir/bdev.json "--json" $g_opt)
|
||||
virtio_bdevs=$(jq -r '[.[].name] | join(":")' <<< $vbdevs)
|
||||
virtio_with_unmap=$(jq -r '[.[] | select(.supported_io_types.unmap==true).name]
|
||||
| join(":")' <<< $vbdevs)
|
||||
|
Loading…
Reference in New Issue
Block a user