Compare commits

..

75 Commits

Author SHA1 Message Date
Tomasz Zawadzki
752ceb0c12 lib/blob: prevent overflowing uint32_t when clearing cluster data
When blob is deleted or reduced in size, the trimmed clusters
are cleared using bs_batch_clear_dev().

blob_persist_clear_clusters() iterated over the clusters
and batched each contigous set of LBA.

The lba_count is of the uint32_t type, long enough
contigous set of LBA could overflow it.
As a result that range would only be cleared with the
overflown value.

This patch prevents that overflow from occuring by
verifying against UINT32_MAX.

This is already addressed with an API change in SPDK 21.10:
(f01146ae)blob: use uint64_t for unmap and write_zeroes lba count

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I17282a2a81587c26b7e89a74dcc6a9c8a017ce15
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9971
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-11-17 10:55:17 +00:00
Tomasz Zawadzki
ca470ff844 lib/blob: chunk spdk_bs_init to exact multiple of sector size
During spdk_bs_init() data present on the device can be cleared
depending on the clear_method used.

Picking BS_CLEAR_WITH_UNMAP results in deallocate command sent
when NVMe device is used.

The size of logical blocks do not have to match the indirection unit
size (IU) of the device. The SSDs can only unmap full physical blocks.
Since the deallocate command is advisory, the controller can complete
the command without deallocating any blocks.

In practice this results in some controllers not deallocating any blocks
if number of logical blocks is not aligned to the IU size.

Make sure that spdk_bs_init() handles this case.
The size of the unmap is now chunked at UINT32_MAX - 127,
which is an even multiple of 512B blocks with a 64KiB IU.

This is already addressed with an API change in SPDK 21.10:
(f01146ae)blob: use uint64_t for unmap and write_zeroes lba count

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: Ie00bd5ae7cdaec4f1486f16fceb6cb18e30bf563
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9970
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-11-17 10:55:17 +00:00
Michal Berger
10807f35f9 test/scheduler: Commonize collect_cpu_idle()
Signed-off-by: Michal Berger <michalx.berger@intel.com>
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7564 (master)

(cherry picked from commit 330e9f779c)
Change-Id: I72da312e0d7fe71ae40b582501b52be615de4b63
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9992
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
64b08f6ea3 test/scheduler: Add function for calculating cpu load
This is done in order to detect cpu times in a more deterministic
fashion.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7563 (master)

(cherry picked from commit 0ea8956025)
Change-Id: I005d6fececdc15500bcf637e96f2fbecbd4273f1
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9989
Reviewed-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
e2025217a7 test/scheduler: Wait for a bit for the governor to change the freq
Issues like https://github.com/spdk/spdk/issues/1784 showed that
governor may need some more time to properly adjust cpufreq's sysfs
knobs. In case we see that frequency setting hasn't changed after
given iteration, wait for 0.5s to make sure it finally settles.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6283 (master)

(cherry picked from commit 92e49c0044)
Change-Id: Ibf25d0d1962bf2b07b13d60d6096c5cc185c1279
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9967
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Jim Harris
a1570edd1d nvme: reset mapping_length correctly for contig SGL
spdk_vtophys() takes a mapping_length parameter, so
it can return the length for which the returned
virtual address is valid.

But spdk_vtophys() will only return the max
between the valid length and the input mapping_length
parameter.

So the nvme SGL building code for contiguous buffers
was broken, since it would only set the mapping_length
once, before the loop started.  Worst case, if a buffer
started just before (maybe 256 bytes) before a huge page
boundary, each time through the loop we would create
a new SGL for only 256 bytes at a time, very quickly
running out of SGL entries for a large buffer.

Fixes #1852.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7659 (master)

(cherry picked from commit 5354d0c63f)
Change-Id: Ib1000d8b130e8e4bfeacccd6e60f8109428dfc1e
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9958
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
cb37376ef6 autotest: Use $HOME as a base for the $DEPENDENCY_DIR
Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8646 (master)

(cherry picked from commit 117e555d9d)
Change-Id: I8f21f6f9a1cf837931646a7458f0ad8147cf6810
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9951
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Maciej Wawryk
6b740d2c10 test: move spdk_test_image.qcow2 to spdk_dependencies dir
Signed-off-by: Maciej Wawryk <maciejx.wawryk@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6940 (master)

(cherry picked from commit 1fc0c2d8b9)
Change-Id: I8d75f5fa22e79c93d1f8929b6df048b440d9fb8a
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9934
Reviewed-by: Maciej Wawryk <maciejx.wawryk@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Maciej Wawryk
5cf63f81be test: removal deprecated sys_sgsw user location
Replace old '/home/sys_sgsw' location by new created
'/home/sys_sgci/spdk_dependencies'
Also update readme with current user name.

Signed-off-by: Maciej Wawryk <maciejx.wawryk@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6927 (master)

(cherry picked from commit 1fc0c2d8b9)

Change-Id: Ifcea15f704183c7ae0044ee02bd28b6bd891b262
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9933
Reviewed-by: Maciej Wawryk <maciejx.wawryk@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
f94c640130 autotest: Don't run spdk_dd tests under crypto job
Currently, crypto job also executes tests from the SPDK_TEST_BLOCKDEV
suite, including spdk_dd tests. The dd tests under a bare-metal system
can take up to 4 minutes alone and that brings the crypto job to the
very edge of timing out.

Since these tests are extensively covered under separate vg jobs we
won't lose any coverage by excluding them from crypto's - the basic
set of SPDK_TEST_BLOCKDEV tests would still remain as part of this
job.

Fixes: #2017

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8545 (master)

(cherry picked from commit c6db5f41e5)
Change-Id: Ic245c7a1711fbb95131df977b81dbdac8af1c15a
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9915
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
2021-10-27 08:47:51 +00:00
Michal Berger
1ea7b29ff8 test/vhost: Don't fetch .qcow2 image needed for tests
Simply fail. It's expected to have this image already installed on
the system.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6375 (master)

(cherry picked from commit ee191fa807)
Change-Id: Ie7bbde84fe633c8b5a4d41bd6dcbee66d6f4a0c5
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9914
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
18936662df test/common: Supress mem leak triggered during nvme_fio test
This is needed since fio, by default, links to libtcmalloc if found
during the build. See:

01fe773df4

Fixes #2192

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9822 (master)

(cherry picked from commit bec627fcb0)
Change-Id: I1de8fe9d489f92acb79ef0f169229a6c09ce1179
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9859
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
1cf67849c8 check_format: Ignore shellcheck's SC2128 and SC2178 directives
These are currently prone to false-positives especially in terms of
scoping. Consider the following:

foo() {
	local bar=(42)
	echo "${bar[*]}"
}

bar=43
foo
echo "$bar"

Some versions of shellcheck, including the latest, 0.7.2, complain
about $bar being reused as a plain string here. This is incorrect
since foo() holds its own copy of bar[@] hence the assignment which
takes place outside of it doesn't affect its content.

SC2178 can be mitigated be reversing the order of declaration:

bar=43
foo() { ... }
...

but the SC2128 still remains.

Currently, in our code majority of these warnings are coming from
false-positives due to initial source'ing which most of our test
scripts do (e.g. they fetch a function where local bar=() is used
and in the test itself $bar happens to be assigned a plain string.
This is still valid code).

To mitigate, disable these directives untill shellcheck is capable
of properly interpreting scoping when checking them.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8503 (master)

(cherry-picked from commit 9d48662103)
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Change-Id: Ifbde973eae6e261d79e1c340eb28644bce5f4e45
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9801
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
49e5142b3c pkgdep/git: Bump fio to 3.28
Older versions of fio depend on raw driver which recently got removed
from the linux kernel:

git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=603e4922f1c

Due to that, these fio versions won't build anymore under latest
kernels available, e.g., for fedora (due to missing raw.h from the
kernel-headers package). Details here:

https://github.com/axboe/fio/commit/382975557

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9718 (master)

(cherry picked from commit 65f01122b2)
Change-Id: Ie63769395c482f1965c6664e8f5143c71ef80253
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9838
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
91c22965cc check_format: Fixes for shellcheck's SC2268 directive
SC2268: Avoid x-prefix in comparisons as it no longer serves a purpose

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8505 (master)

(cherry picked from commit dd2b935dc4)
Change-Id: Ica5ddfa8c39f34741c7344906abe802ff7451b1f
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9837
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
73c1c75f23 check_format: Fixes for shellcheck's SC2251 directive
SC2251: This ! is not on a condition and skips errexit.
        Use && exit 1 instead, or make sure $? is checked.

This is critical since our test suites heavily depend on errexit
to catch all abnormal conditions. Replace ! foo ... with a call to
NOT() wherever possible. For the test/ocf pieces, use [[ ]] instead
to define the condition for the existance of the ocf bdev.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8504 (master)

(cherry picked from commit 742f04b3f7)
Change-Id: Ied3f99b9f1dc0594e4aef64fc21e51498f19ac23
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9836
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
8aafde8856 check_format: Fixes for shellcheck's SC2269 directive
SC2269: This variable is assigned to itself, so the assignment does
        nothing.

Since the --id check doesn't change the value of $id, remove it
completely. This simplifies the process_shm() so the --id type is
considered to a be default and $id changed only in case --pid was
explicitly requested.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8502 (master)

(cherry picked from commit 63fd943282)
Change-Id: If8a4a43c6822fa1b32217a0b783cb96d0fee2644
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9835
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
199f14e3fd check_format: Fixes for shellcheck's SC2030 directive
SC2030: Modification of var is local (to subshell caused by pipeline)

This directive is raised since the for loop (or rather its contents)
is piped through to another process. In this context it's not harmful
since we are interested only in sending the stdout but since we operate
on variables that happen to be local to the process that handles the
loop shellcheck sees that as a potential issue. To make it happy
remove the pipe and sort pci addresses prior running the loop.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8501 (master)

(cherry picked from commit 8c176db2ca)
Change-Id: I835c5ac1da9012129c5d01d62880307f70caab1b
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9834
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Michal Berger
93b2a5420a check_format: Fixes for shellcheck's SC2155 directive
This is a first commit in the series addressing potential Bash issues
as discovered by the latest shellcheck release (0.7.2, shipped with
the very latest fedora33 and fedora34). The goal is to either fix,
locally or globally disable given directive(s).

SC2155: Declare and assign separately to avoid masking return values

Simplify the setting of the variable pointing at the root of the repo.
Also, keep it consistent with the rest of the scripts and declare it as
$rootdir.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8500 (master)

(cherry picked from commit 36f5f0df17)
Change-Id: I63e0b1a85ce16f7983e9ba6dd985046e8a39a650
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9833
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Niklas Cassel
731887d713 nvme/fio_plugin: remove ZBD_IGNORE usage
The define ZBD_IGNORE has been removed from upstream fio.

fio will now return an error if --zonemode=zbd is used with a
--filename that points to something that is unsupported by either
the zbd code in fio or by the ioengine itself.

ioengines are now supposed to return -EINVAL for unsupported files
(instead of returning 0 with ZBD_IGNORE for unsupported files).

This change does not need any special ifdef FIO_IOOPS_VERSION check.

Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8326 (master)

(cherry picked from commit bd53d09c31)
Change-Id: I7bec0b1f5dc8f166ebf683f6f3937b2ef295a21e
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9832
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Tomasz Zawadzki
6f6fced5a5 lib/blob: resize open_blobids on bs load
open_blobids holds bit array of currently open blobs,
this is a way for quicker determination than iterating
over all blobs. See patch introducing it:
(30ee8137)blob: Add a bitmask for quickly checking which blobs are open

That patch added resizes of this bit array to bs init
and bs recovery path (not shut down cleanly).

But that patch skipped over bs load from a clean shutdown.
This resulted in blob open having multiple blob pointers that
target the same blob id.

Fixes #1937

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7998 (master)

(cherry picked from commit 42ad9d0379)
Change-Id: I3c42a63d168d1f5b013b449f010c5b207936045b
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9831
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-10-27 08:47:51 +00:00
Pawel Piatek
a56704a0e1 autobuild: Update patches for mainline DPDK
Patch f95e331be3a1f856b816948990dd2afc67ea4020 is no longer needed,
since it was solved at upstream level.

Signed-off-by: Pawel Piatek <pawelx.piatek@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8698 (master)

(cherry picked from 93c4adda4d)
Change-Id: Icf064b121351566988c26390f45286e7a456ca39
Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8731
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-07-27 07:54:48 +00:00
Ben Walker
a37bb7d4a5 test: Fix missing comma in app_ut.c
Caught by clang 12.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8854 (master)

(cherry picked from d673fcee3d)
Change-Id: Ibed23c3aab80508aebf06e4ba44e14e385a3256b
Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8852
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-07-27 07:54:48 +00:00
Ben Walker
dc09422cd3 test/nvme: Fix bug where ctrlr->nsdata is null
Caught by clang 12 and UBSAN.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Change-Id: I2fbb82a9225ab0cb8616bd671f8b81987cb3d708
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8853
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-07-27 07:54:48 +00:00
Jim Harris
9b420e8c00 bdev/nvme: do not use DSM to emulate write zeroes
We cannot rely on DSM/DEALLOCATE as a write zeroes
alternative, even if DLFEAT reports that deallocated
blocks will be read as all zeroes.  DEALLOCATE is
advisory, meaning that blocks may not actually be
deallocated.  In cases where they are not deallocated,
they will not be read back later as zeroes.

QEMU 6.0 started reporting DLFEAT as returning zeroes
for deallocated blocks but for some of our write
zeroes tests, blocks aren't actually deallocated.

We may be able to add quirks in the future if we know
that a controller reliably deallocates blocks, but
for now we need to revert this completely.

Note that since bdev/nvme module now does not support
write zeroes in any cases, we need to disable the
write zeroes call in the unit tests.

Fixes issue #1932.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7723 (master)

(cherry picked from 3faf457f56
with minor modifications)

Change-Id: I79f0673774b621a9ffcc46891728cc7719e34cdb
Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8879
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-07-26 08:41:37 +00:00
Jim Harris
d28343f894 nvme: add quirks for new RedHat QEMU NVMe dev/vendor ID
QEMU 6.0 by default uses a RedHat dev/vendor ID rather
than the Intel one that has always been used to date.
We need the NVME_QUIRK_MAXIMUM_PCI_ACCESS_WIDTH quirk
so that we do not use wide instructions to copy SQEs
to a virtualized CMB, since QEMU does not support
that.

The NVME_INTEL_QUIRK_NO_LOG_PAGES quirk is only needed
for devices with SPDK_PCI_VID_INTEL, so we do not need
to carry this one over to the new REDHAT entry.

Fixes issue #1986.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8226 (master)

(cherry picked from 130c94c489)
Change-Id: I3d339b3525e7c6ceb792eb9d143e7a922c19344d
Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8878
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-07-26 08:41:37 +00:00
Michal Berger
b7a6b5f559 scripts/rpc: Make sure address argument is properly interpreted
In case the addr argument was not an existing unix socket file the rpc
client would consider it to be an actual ip address. As a result
connect() would be called with improper set of arguments. This could
cause the rpc.py to block for undesired amount of time until connect()
finally decided to return (seen on some fedora33 builds).

This was affecting sh wrapper functions like waitforlisten() which
use rpc.py to determine if given app is ready to be talk to blocking
execution of the tests for way too long then intendent.

To avoid such a scenario determine the format of the address and use
routines proper for given address family.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7777 (master)

(cherry picked from 6c1a1a3dca)
Change-Id: Iaac701d72c772629fa7c6478ff4781b0c5d485d5
Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8877
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-07-26 08:41:37 +00:00
paul luse
fce34b065d test/idxd: fix allocation issue with unit test
Fixes issue #1847

Signed-off-by: paul luse <paul.e.luse@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7016 (master)

(cherry picked from 48c057814b
with minor changes)

Change-Id: I34109935b5e8187192239fa34ff43946d0e7632f
Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8876
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-07-26 08:41:37 +00:00
Michal Berger
023a6b0b0d autotest: Don't override default amount of hugepages on Linux to 8GB
This is relevant mostly for the VMs. Allocating that much memory puts
a lot of pressure on remaining pieces of the system as currently we
allocate total of 12GB memory per VM instance in the CI pool. Default of
4GB hp should be enough to cover majority of the tests hence if there's
any suite that requires more memory, setup.sh should be called there
directly with an optimal value.

This is done to make sure we can accomodate proper resources in the CI
by knowing what are the actual requirements rather than just blindly
allocating "as much as possible".

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8436 (master)

(cherry-picked from 227428c3a4 with
minor changes)

Change-Id: Ie958c518c7ed702b068c7fc9042183fdf41aa816
Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8875
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-07-26 08:41:37 +00:00
Niklas Cassel
d56a2b7214 nvme: account for PRACT when calculating max sectors per transfer
There is a special case when using 8-byte metadata + PI + PRACT
where no metadata is transferred to/from controller.

Since _nvme_ns_cmd_rw() already calculates the proper sector size
using _nvme_get_host_buffer_sector_size(), which takes PRACT into
account, change the sectors_per_max_io calculation to also take
PRACT into account.

This will avoid certain requests that don't need splitting getting
split.

Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6247 (master)

(cherry picked from commit 4249dc1010)
Change-Id: I8d450d37c2458453701189f0e0eca4b8fe71173b
Signed-off-by: John Kariuki <John.K.Kariuki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8023
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-05-31 07:11:30 +00:00
Michal Berger
99379a07f1 autobuild: Ignore warnings comming from doxygen 1.8.20
This particular version reports plenty of false positives causing the
test to fail. Example:

nvme.md:2: warning: @copybrief or @copydoc target 'spdk_nvme_ctrlr_alloc_io_qpair()\ilinebr' not found
nvme.md:2: warning: @copybrief or @copydoc target 'spdk_nvme_ctrlr_get_ns()\ilinebr' not found
nvme.md:2: warning: @copybrief or @copydoc target 'spdk_nvme_ns_cmd_read()\ilinebr' not found
nvme.md:2: warning: @copybrief or @copydoc target 'spdk_nvme_ns_cmd_readv()\ilinebr' not found
nvme.md:2: warning: @copybrief or @copydoc target 'spdk_nvme_ns_cmd_read_with_md()\ilinebr' not found
nvme.md:2: warning: @copybrief or @copydoc target 'spdk_nvme_ns_cmd_write()\ilinebr' not found
nvme.md:2: warning: @copybrief or @copydoc target 'spdk_nvme_ns_cmd_writev()\ilinebr' not found

This is potentially a regression in caused by the following issue:
https://github.com/doxygen/doxygen/issues/7948

The above seems to be resolved in latest releases, however, until
they are shipped as part of distros we support, similar mitigation is
in order.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Change-Id: I1e39c94f9f388de99e1106bcf15750e4b39384e6
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7160
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7948
Reviewed-by: Karol Latecki <karol.latecki@intel.com>
2021-05-21 08:01:49 +00:00
Simon A. F. Lund
14c153e67f scripts/nvmf_perf: fix pylint E741
Signed-off-by: Simon A. F. Lund <simon.lund@samsung.com>
Change-Id: I039a2e22a665e0d52082e6876f2c7c1cd9a336c1
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6386
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7931
Reviewed-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-05-21 08:01:49 +00:00
Karol Latecki
27acba1262 autobuild: update patches for mainline DPDK
Patches stopped applying cleanly because of dpdk/dpdk changes:
7d5cfaa7508de0fd248b05effbf421a98317006a
4ad4b20a79052d9c8062b64eaf0170c16a333ff8
Needed to rebase custom patches.

Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Change-Id: I41b34c5c58070720c4010632e89468042e470613
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7938
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-05-21 08:01:49 +00:00
Karol Latecki
b0cdf76635 autobuild.sh: restore patches for older DPDK versions
Commit e9ebbdaefc updated
custom patches for mainline DPDK, but did not keep their
previous versions. We still need the old patches to build
with older DPDK versions.

Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7610 (master)

(cherry picked from commit c06df11513)
Change-Id: Ibe222a444bed2fdee63c8dcfcebc8402bb991fbe
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7637
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-05-10 10:45:57 +00:00
Karol Latecki
beb7cd3829 autobuild: Update patches for mainline DPDK
Previous patches stopped applying cleanly at DPDK
21.05-rc1, needed to update.

Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7538 (master)

(cherry picked from commit e9ebbdaefc)
Change-Id: If276f608c8394439064e9dfe30fed6d5531805d2
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7636
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-05-10 10:45:57 +00:00
Jim Harris
4d419d55b8 env_dpdk: save hotplug timeout timestamps separate from rte_devargs
DPDK recently clarified some semantics on the rte_devargs 'data'
and 'args' fields.  This actually breaks our use of the 'data'
field to store the 2 second timeout timestamp for delaying
attach to newly inserted devices.  Investigating this further,
it does not seem our use of the 'data' field was valid - it just
happened to work until now.

We could use the 'args' field now.  But knowing whether to use
'args' or 'data' would then be dependent on the DPDK version.
We cannot use RTE_VERSION_NUM to decide, because this is a
compile time decision, and it is possible in shared library
use cases that we could actually link and execute against a
different version of DPDK than we built against.

So instead we will create our own env_devargs structure that
will store these allowed_at timestamps. Currently it's just
a linked list (which is exactly how DPDK does it) - we could
make it more optimal with a hash table down the road, but this
code only executes when we are doing PCI enumeration so it is
not performance critical.

Fixes #1904.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7506 (master)

(cherry picked from commit 6c75f0a266)
Change-Id: I3ee5d65ba90635b5a96b97dd0f4ab72a093fe8f7
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7635
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-05-10 10:45:57 +00:00
Jim Harris
512fcf8e58 env_dpdk: add allowed_at helpers for PCI hotplug timeout
Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7505 (master)

(cherry picked from commit de9f4857d0)
Change-Id: I5265f99fc12e134bf156de75de433a739b9ef1ef
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7634
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
2021-05-10 10:45:57 +00:00
Krzysztof Karas
2879f9d2da build/fio: disable warning for fio clang-11 builds
Fio 3.19 fails to build with Clang 11 because of
implicit-const-int-float-conversion error.
Disable -Werror checking for now.

Fixes #1848

Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6991 (master)

(cherry picked from commit 7366e569fb)
Change-Id: I0f3922d7af412de35d9f79f3f5413af146996bf3
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7633
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-05-10 10:45:57 +00:00
Michal Berger
06bceceac8 test/common: Don't enable werror on FreeBSD
Facing similar issue as with 9ab2855d - can't build SPDK against fio
3.19.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6805 (master)

(cherry picked from commit f58afe93b8)
Change-Id: I4ea22e4f068a19d8d87be836454ec8deeeb2d48a
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7649
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-05-10 10:45:57 +00:00
Karol Latecki
edf5f3de0e autobuild: enable -Wno-stringop-overflow for DPDK builds only for GCC > 10
Use -Wno-stringop-overflow only for GCC > 10.
Change made to use the same condition as in
dpdkbuild/Makefile.

Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7537 (master)

(cherry picked from commit e1fe11875b)
Change-Id: I6a396e250807f46720ff5dcaf21f13d802404a1b
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7652
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-05-10 10:45:57 +00:00
Karol Latecki
f04c67984b autobuild: build mainline DPDK with -Werror only for GCC > 5
DPDK now officially supports only GCC > 4.9.0.
Some older systems like Centos7  (gcc 4.8.5) can still
build DPDK, but sometimes fail due to -Werror enabled.
Disable this option to increase build success chance.

Fixes #1891

Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7536 (master)

(cherry picked from commit 71b4e2a968)
Change-Id: I0950ad01e2d8361851e9ac42c556004980e00ff4
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7651
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-05-10 10:45:57 +00:00
Michal Berger
c8607790cb autopackage: Make lto build dependent only on RUN_NIGHTLY flag
This is done in preparation for the RPM tests.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7142 (master)

(cherry picked from commit d22233ac59)
Change-Id: I93cd0d3d7ddeff54387e2a270e9713b2415845b0
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7650
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-05-10 10:45:57 +00:00
wanghailiangx
08b6e24735 test/nvmf_tcp: allow tcp cases running in E810 NIC instead of virtual eth
Added nvmf_tcp_init() to run tcp through physical E810 network card.
If there is not E810 in system, tcp will still run on virtual eth.

Signed-off-by: wanghailiangx <hailiangx.e.wang@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6932 (master)

(cherry picked from commit 460bacc914)
Change-Id: I9a983c92175b27c45457682d42d72ef307fef260
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7655
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-05-10 10:45:57 +00:00
Michal Berger
a5b0bc0cd8 test/nvmf: Use rxe_cfg to get rxe-enabled net devices
Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6994 (master)

(cherry picked from commit c09b139e61)
Change-Id: Iafc067f880525f25363db1adf9a94a9fc9215455
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7747
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-05-10 10:45:57 +00:00
Michal Berger
0896f85b59 scripts/rxe_cfg: Add env switch to skip printing status header
Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6993 (master)

(cherry picked from commit 4d52dae32a)
Change-Id: Ibc3149b5b9591826ff9aeed38457c2aa9ff747e4
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7746
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-05-10 10:45:57 +00:00
Michal Berger
94abf2d8c2 scripts/rxe_cfg: Split collect_devices()
collect_devices() is split into two functions:

 - collect_net_devices(): Collect ethernet net devs from the
                          net class.
 - collect_rxe_devices(): Collect all rxe devices from the
                          infiniband class.

This is done in order to make handling of some conditions easier.
Case and point, in newer kernels, device/net link is not anymore
created for the soft roce devices, instead only ./parent attribute
is available. collect_rxe_devices() is adjusted to handle such
a condition.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6992

(cherry picked from commit e99cfdb6c9)
Change-Id: Idefa39c4a62c9e650a03e237f49940461e9782a6
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7745
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-05-10 10:45:57 +00:00
Karol Latecki
f4c28506d5 scripts/ceph: load loop module explicitly
Older losetup versions loaded "loop" in background, but
with 2.36.1 this doesn't happen. We know we're going to
use this module so let's load it ourselves.

Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7086 (master)

(cherry picked from commit f88416a1de)
Change-Id: If3364e92817ae9f09e9897872bd61ca9167184a1
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7744
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-05-10 10:45:57 +00:00
Karol Latecki
53603323e5 autotest.sh: call rdma_device_init only for RDMA tests
Check test flags before calling rdma_device_init if
it's really needed, so that we don't call it when doing
TCP tests.

Signed-off-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6998 (master)

(cherry picked from commit b7423187a2)
Change-Id: I2675a008cf84c7c4084cb83b44c279d2a497c3cb
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7805
Tested-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-05-10 10:45:57 +00:00
Tomasz Zawadzki
64f1ea8ea4 SPDK 21.01.2-pre
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I473719d4142702572ff4a51858bcf8cb86ef65ea
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6684
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-03-10 16:22:10 +00:00
Tomasz Zawadzki
1f0dd58a43 SPDK 21.01.1
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: Ic086efcf2be78403e905c9b9f4d8d9882a85c4d0
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6683
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-03-10 16:22:10 +00:00
Krzysztof Karas
049e9290cf spdk_top: fix app crashing on tab selection with TAB key
Fixes spdk_top crashing problem upon selecting a row in one tab,
then switching with TAB key to a different tab with fewer rows
and calling pop-up details window with ENTER key.

Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6367 (master)

(cherry picked from commit 6a34348219)
Change-Id: I52c5729eca0ce0eaad88767ff3add471a780140a
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6729
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-03-10 16:22:10 +00:00
Pawel Piatek
82c0c8ca03 autorun: allow pass configuration file path
Allow to pass configuration file as first parameter with
fallback to previous behaviour where config file is read
from home directory.

Signed-off-by: Pawel Piatek <pawelx.piatek@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6361 (master)

(cherry picked from commit 23c8f667a2)
Change-Id: I45972b04fe5fc978bf3b2bede45aae363be3069c
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6545
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Pawel Piatek <pawelx.piatek@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: <dongx.yi@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-03-05 08:01:45 +00:00
Tomasz Zawadzki
1cf1b00b1b lib/vhost: force cpumask to be subset of application's CPU mask
Documentation for vhost target states that CPU mask must be a subset
of application CPU mask. This wasn't enforced right now and allowed
the cpumask on controller creation so long as at least single
CPU core overlapped with application's CPU mask.

This might have been misleading and covered up user configuration errors.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6212 (master)

(cherry picked from commit b74363bcdf)
Change-Id: I03f959ec37efd0be9b98cff9c93c5f996b04af35
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6390
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-03-05 08:01:35 +00:00
Tomasz Zawadzki
1d839c1ac3 test/vhost: verify cpumask argument for controller creation
`--cpumask` argument for vhost controller creation was
untested. This patch specifies this argument and verifies output
under following conditions:
- no cpumask, resulting in it being equal to the app cpumask
- cpumask equal to app cpumask
- single core
- single non-main core
- two cores

It was motivated by recent changes to reactor code affecting
vhost without it being caught by CI. See commit 7cc83b62.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6211 (master)

(cherry picked from commit daab1abc4f)
Change-Id: I92c603061619092007bc27a189d3d8787461a16f
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6389
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-03-05 08:01:35 +00:00
Rui Chang
9bdc45693a lib/util: Fix valgrind error reported on ARM platform
Signed-off-by: Rui Chang <rui.chang@arm.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6214 (master)

(cherry picked from commit 1293377629)
Change-Id: I244a1b0350b4426666e390781b500de65d250c09
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6391
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Rui Chang <rui.chang@arm.com>
2021-03-05 08:01:28 +00:00
Liu Xiaodong
c7a0275edf nbd: set io timeout
After setting io timeout, host can avoid nbd io
stuck or kernel hang occasionally caused by nbd
stop or underlying bdev removal.

Signed-off-by: Liu Xiaodong <xiaodong.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6191 (master)

(cherry picked from commit b7c33b5e61)
Change-Id: I4ba2a0af7ff7bed369cdaf86121f082136dc1a0b
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6394
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: <dongx.yi@intel.com>
2021-03-03 08:12:01 +00:00
Tomasz Zawadzki
a5a51c7b56 lib/iscsi: return immediately from iscsi_parse_params if len is 0
The spec does not disallow TEXT PDUs with no data.  In that
case, just return immediately from iscsi_parse_params.

This avoids a NULL pointer dereference with a TEXT PDU that has
no data, but CONTINUE flag is set.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Signed-off-by: Jim Harris <james.r.harris@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6319 (master)

(cherry picked from commit f3fd56fc3c)
Change-Id: I2605293daf171633a45132d7b5532fdfc9128aff
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6601
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-03-03 08:11:04 +00:00
Shuhei Matsumoto
f2a113d144 bdev/ocssd: Fix the bug that no media event is pushed to the target bdev
Recent refactoring added a critical bug that no media event is pushed
to the target bdev.

Fix the bug by changing return to break.

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6455 (master)

(cherry picked from commit bd8de45801)
Change-Id: Ia674ea2c9c21d08dd23b50a0f726da55011d4be4
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6616
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-03-03 08:09:19 +00:00
Richael Zhuang
b4ed65d26f sock: add enable_quickack and enable_placement_id when writing json config
Signed-off-by: Richael Zhuang <richael.zhuang@arm.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6144 (master)

(cherry picked from commit c0a3cf7b88)
Change-Id: If67dcb6bf7b9742d2c96481057b472e31e87e87d
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6392
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-02-26 11:51:37 +00:00
sunshihao520
26e589c3a4 pkg: add python3 requires in spdk.spec
When use rpm -i to install spdk-tools, it requires python3-configshell
and python3-pexpect. Add this requires to spec to avoid install failure.

Signed-off-by: sunshihao <sunshihao@huawei.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6336 (master)

(cherry picked from commit a4ee18886d)
Change-Id: I7fc7e9aab35c3fd730401282b72b1604f765a73f
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6431
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: sunshihao <sunshihao@huawei.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-02-19 11:03:19 +00:00
Tomasz Zawadzki
14eeeea669 lib/env_dpdk: add rte_net dependency
Vhost is enabled by default, so rte_net was always included.
When disabled, rte_power failed as it depends on rte_ethdev and rte_net.

rte_vhost was only possible to enable on Linux, so there
is no conflict with adding it next to rte_power under this condition.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6398 (master)

(cherry picked from commit 232f34d754)
Change-Id: I2e183004d6457e404471740a0540dcb08aa738d8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6430
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-02-17 09:34:19 +00:00
Vasuki Manikarnike
3f732d80d3 lib/nvme: Remove qpair from all lists before freeing it.
Fixes #1777.

When a qpair cannot be allocated because the transport connection fails,
the qpair was freed without unlinking it from the other structures.
This was leading to a segfault when attempting to create and free other
qpairs.
Also added a unit test to cover this case.

Signed-off-by: Vasuki Manikarnike <vasuki.manikarnike@hpe.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6272 (master)

(cherry picked from commit d92c2f118a)
Change-Id: I74b78d1847f90117248b07203b43a11ff5cfa5d6
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6393
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
2021-02-16 08:18:52 +00:00
sunshihao520
e02a868dd3 lib:vhost Add version check when use RTE_VHOST_USER_ASYNC_COPY in 21.01
In dpdk 19.11 version, RTE_VHOST_USER_ASYNC_COPY is not define.
After dpdk 20.08, we can use RTE_VHOST_USER_ASYNC_COPY.
Use version check to avoid this problem.

Signed-off-by: sunshihao <sunshihao@huawei.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6274 (master)

(cherry picked from commit 9529803fe0)
Change-Id: Iaf9914e8380f3d54cded1e2f16af6a7dc3504f95
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6255
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
2021-02-16 08:13:11 +00:00
sunshihao520
d02ff4c422 pkg:spdk.spec Add ncurses-devel to BuildRequires
ncurses.h is needed in spdk_top, add ncurses-devel to BuildRequires.

Signed-off-by: sunshihao <sunshihao@huawei.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6258 (master)

(cherry picked from commit ccbdd1750f)
Change-Id: I22754838788fe237a29ab74a675a94ab7007bd33
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6388
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: sunshihao <sunshihao@huawei.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
2021-02-16 08:13:11 +00:00
sunshihao520
4b87c7259a lib:env_dpdk fix the enum rte_kernel_driver definition deference between dpdk 19.11 and 20.11
In dpdk 19.11, rte_kernel_driver is the old version, add version check before use the members.
Signed-off-by: sunshihao <sunshihao@huawei.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6252 (master)

(cherry picked from commit b1687cd456)
Change-Id: Ic1db37cc0760c7d03692fd2cdcbb6ff1e41f872d
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6321
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: sunshihao <sunshihao@huawei.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
2021-02-16 08:13:11 +00:00
Jim Harris
02f9f45524 env_dpdk: add rte_ethdev dependency
As of DPDK main commit 682a6454 ("power: add ethdev
power management"), rte_power depends on rte_ethdev.
So add rte_ethdev library, but only on Linux since
that is the only place where we use rte_power.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6210 (master)

(cherry picked from commit 710838103b)
Change-Id: Ibc3473d6ec75c14a8c0c5517616950017cb2ea96
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6320
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-02-08 16:57:07 +00:00
Tomasz Zawadzki
84c4530e9b version: 21.01.1 pre
Removed the suppress for tracking ABI differences.
Maintanance release will need to capture any changes,
rather than ignore some.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: Ia01fecf872f213b61b9545ff7c476a9312e02109
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6158
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2021-02-05 11:55:55 +00:00
Tomasz Zawadzki
0811dda8bf SPDK 21.01 LTS
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: Ifcbc56f11f6e5a918a0cabe4e9719d3832f4674d
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6157
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-02-03 15:50:18 +00:00
Tomasz Zawadzki
9b37f63fe9 Revert "lib/event: do not spawn a thread for each reactor"
This reverts commit 72eed604b4.

spdk_vhost_init() relies on having a thread on each reactor.
Without the revert, every vhost controller is created on the same
core and even passing --cpumask when creating does not affect it.

Proper fix would be to change spdk_vhost_init(),
but would require additional testing. For now revert the patch
that spawned always idle threads.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>

(cherry picked from commit 724d50d3e1b8d881575efb0a1643220179c0fe2d)
Change-Id: I0dbd6c9fe1d9d23ada260da8fc7b48086223c632
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6187
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
2021-02-01 08:04:44 +00:00
Tomasz Zawadzki
edb5cd988a doc: added scheduler framework documentation
Added changelog entry for dynamic scheduler, along with general
information on scheduler framework and behaviour of particular
scheduler implemenations.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Signed-off-by: Ben Walker <benjamin.walker@intel.com>

(cherry picked from commit a691353a2a8d99984875c550af037df983996093)
Change-Id: I9fcef56323c4be136b6b531297b070562981eee5
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6185
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-02-01 08:04:38 +00:00
andypma
68eb748759 vhost/compat: add RTE_VHOST_USER_ASYNC_COPY flag when used IOVA_PA mode
Recently, we discovered that under the SPDK + UIO mode, it is possible that vm may be wrong when doing io.
such as:
[root@VM_6_151_centos ~]# mkfs.xfs /dev/vdc
meta-data=/dev/vdc               isize=512    agcount=4, agsize=234421142 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=937684566, imaxpct=5
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=457853, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
bad magic number
bad magic number
Metadata corruption detected at xfs_sb block 0x0/0x1000
libxfs_writebufr: write verifer failed on xfs_sb bno 0x0/0x1000

the github issue link: https://github.com/spdk/spdk/issues/1738
After investigation, we found as below:
The qemu set to VHOST_USER_SET_MEM_TABLE then call vhost_user_set_mem_table(dpdk version spdk-20.11)->mmap(without MAP_POPULATE)
the mmap will only return the virtual address not map the virtual address to the physical address actually.
after call vtophys_notify->vtophys_get_paddr_pagemap, we will get a wrong physical(the virtual address we not access)

So this patch is to set MAP_POPULATE during we use SPDK + UIO.

Signed-off-by: andypma <andypma@tencent.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5970 (master)

(cherry picked from commit 7741de6b7d)
Change-Id: Ib921b6d7381f46bb5894ed787cef52e02524197a
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6182
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-01-29 17:06:10 +00:00
Changpeng Liu
bbe2ed83dc nvmf/vfio_user: disable vfio_user by default
Users can use "--with-vfio-user" to enable it when testing it.
For CI configuration, we add a new test flag SPDK_TEST_VFIOUSER
to enable CI tests.

Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6139 (master)

(cherry picked from commit 3b673b8431)
Change-Id: Id284df721171d01cc52491ebf4088bcc17eee147
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6181
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-01-29 17:06:10 +00:00
Tomasz Zawadzki
d53d7a5723 doc: list methods to convert from legacy config
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6154 (master)

(cherry picked from commit f58b29784a)
Change-Id: Iccc272ddaeefad3d02b9d63607173bd2b76bd112
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6180
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-01-29 17:06:10 +00:00
Alexey Marchuk
2a1fe02d98 nvmf/rdma: Handle CQ resize for iWARP transport
Since iWARP doesn't support CQ resize, we can't
accept new qpairs when CQ size is insufficient.
In other case if we accept new qpairs we can
et CQ overrun and receive IBV_EVENT_CQ_ERR ibv
async event. In that case we will have to close
all qpairs that use this CQ.

Part of the fix for issue #1747

Signed-off-by: Alexey Marchuk <alexeymar@mellanox.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6106 (master)

(cherry picked from commit 4a2c27f717)
Change-Id: I30b9163a7c8abb8651f8813c6bbdb80000741c9c
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6179
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2021-01-29 17:06:10 +00:00
Alexey Marchuk
081cd04ea2 nvmf/rdma: Fix search for req to abort when SRQ enabled
When SRQ is enabled, all qpairs share common pool of
rdma requests and we should check that rdma_req which
cid matches belongs to the correct qpair.

Signed-off-by: Alexey Marchuk <alexeymar@mellanox.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6110 (master)

(cherry picked from commit 137866e573)
Change-Id: I2505ca39c5110e8e67a48abbe34b6df9ff00229f
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6146
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2021-01-29 08:15:53 +00:00
464 changed files with 6083 additions and 23312 deletions

5
.gitignore vendored
View File

@ -2,17 +2,12 @@
*.a
*.cmd
*.d
*.dll
*.exe
*.gcda
*.gcno
*.kdev4
*.ko
*.lib
*.log
*.o
*.obj
*.pdb
*.pyc
*.so
*.so.*

2
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "dpdk"]
path = dpdk
url = https://git.quacker.org/d/numam-dpdk.git
url = https://github.com/spdk/dpdk.git
[submodule "intel-ipsec-mb"]
path = intel-ipsec-mb
url = https://github.com/spdk/intel-ipsec-mb.git

View File

@ -1,66 +1,14 @@
# Changelog
## v21.04.1: (Upcoming Release)
## v21.01.2: (Upcoming Release)
## v21.04: ZNS NVMe bdev, PMR, ADQ initiator, RPM
## v21.01.1:
### accel
### dpdk
Two new accelerated crc32 functions `spdk_accel_submit_crc32cv` and
`spdk_accel_batch_prep_crc32cv` are added in order to provide the
chained accelerated CRC32 computation support.
Added `rte_ethdev` and `rte_net` dependencies for all builds with DPDK.
### bdev
For `bdev_ocssd_create` RPC, the optional parameter `range` was removed.
Only one OCSSD bdev can be created for one OCSSD namespace.
Removed the `spdk_bdev_open` from bdev library API.
Removed the `spdk_vbdev_register` and `spdk_bdev_part_base_construct` from bdev module API.
Removed the `config_text` function for bdev modules to report legacy config.
Added `spdk_bdev_get_max_active_zones` API to display maximum number active zones of a given bdev.
Added `spdk_bdev_get_max_zone_append_size` API to display maximum zone append data transfer size.
### bdev_nvme
Added support for zoned namespaces.
### blobstore
Removed the `spdk_bdev_create_bs_dev_from_desc` and `spdk_bdev_create_bs_dev` API.
### env
Added `spdk_pci_device_allow` API to allow applications to add PCI addresses to
the allowed list after the application has started.
Removed the `pci_whitelist`, `pci_blacklist` and `master_core` members of struct `spdk_env_opts`.
Added hotplug support based on uevent in `pci_event.c`. Added usage of this functionality in
nvme, virtio-scsi and virtio_blk libraries. Please see the new API `spdk_pci_event_listen`,
`spdk_pci_get_event`, `spdk_pci_register_error_handler` and `spdk_pci_unregister_error_handler`.
### event
Removed the `config_file`, `max_delay_us`, `pci_whitelist`
and `pci_blacklist` members of struct `spdk_app_opts`.
### idxd
A new API `spdk_idxd_device_needs_rebalance` was added so that users of the library
can know whether they need to rebalance the flow control for the channel
that was just added/removed. This is based on how the low level library
shares devices amongst channels.
The API `spdk_idxd_reconfigure_chan` had the `num_channels` removed as this
is now tracked in the library. The app makes use the new API above to
determine whether to rebalance or not. This applies to `spdk_idxd_configure_chan`
as well.
The API `spdk_idxd_put_channel` now returns the rebalance state for the
underlying device.
Fixed compatibility issues with DPDK 19.11.
### iscsi
@ -69,147 +17,23 @@ A TEXT PDU with no data, but CONTINUE flag set, would result in a NULL pointer d
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.
### net
### nbd
The net library is deprecated and will be removed in the 21.07 release.
Fixed kernel hang when bdev is removed by always setting NBD_SET_TIMEOUT.
### nvme
Added a new function `spdk_nvme_ctrlr_get_regs_pmrcap` to get the PMR capabilities.
Fixed segfault when removing qpair when transport connection fails (issue #1777).
Added an accelerated table pointer in `spdk_nvme_poll_group`
which can be used to provide the accelerated functions by users with
hardware engine, such as crc32c accelerated function.
### ocssd
Added new functions `spdk_nvme_ctrlr_get_pmrsz`, `spdk_nvme_ctrlr_enable_pmr`,
`spdk_nvme_ctrlr_disable_pmr`, `spdk_nvme_ctrlr_map_pmr` and `spdk_nvme_ctrlr_unmap_pmr`.
Added NVMe transport operations to enable, disable, map and unmap the PMR.
Added `spdk_nvme_qpair_get_optimal_poll_group` function and `qpair_get_optimal_poll_group`
function pointer in spdk_nvmf_transport_ops structure in order to add the qpair to the most
suitable polling group.
Added OPTPERF and namespace optimal performance fields to nvme_spec.h.
Added `spdk_nvme_set_hotplug_filter` API to allow applications to choose which
hot-inserted SSDs should be probed. This is useful for use cases where multiple
independent SPDK processes are running on one node. The filter function can
then be implemented in these processes to decide which SSDs to probe based on
the new SSD's PCI address.
New functions `spdk_nvme_poll_group_get_stats` and `spdk_nvme_poll_group_free_stats`
were added. These functions allow to get transport statistics per NVME poll group.
Added `spdk_nvme_map_cmd` API to map the NVMe command with SGL cases.
Added support for vector variant of ZNS zone append commands with new API
`spdk_nvme_zns_zone_appendv` and `spdk_nvme_zns_zone_appendv_with_md`.
Added `spdk_nvme_zns_ns_get_max_open_zones` and `spdk_nvme_zns_ns_get_max_active_zones` API,
to display maximum number of open and active zones of the given namespace.
Added `spdk_nvme_zns_ns_get_zone_size_sectors` API to provide size of zone in number of
sectors.
Added `spdk_nvme_qpair_get_id` API to display the ID of the specified qpair.
### nvmf
Removed the `spdk_nvmf_tgt_listen` and `spdk_nvmf_subsystem_add_ns` API.
Added new APIs:
- `spdk_nvmf_poll_group_dump_stat` (function in `nvmf.h`).
- `poll_group_dump_stat` (transport op in `nvmf_transport.h`).
The following APIs have been deprecated and will be removed in SPDK 21.07:
- `spdk_nvmf_poll_group_get_stat` (function in `nvmf.h`),
- `spdk_nvmf_transport_poll_group_get_stat` (function in `nvmf.h`),
- `spdk_nvmf_transport_poll_group_free_stat`(function in `nvmf.h`),
- `spdk_nvmf_rdma_device_stat` (struct in `nvmf.h`),
- `spdk_nvmf_transport_poll_group_stat` (struct in `nvmf.h`),
- `poll_group_get_stat` (transport op in `nvmf_transport.h`),
- `poll_group_free_stat` (transport op in `nvmf_transport.h`).
See header files for details.
The `trtype` field in JSON returned by `nvmf_get_stats` RPC contains now the name of the transport,
which is the same as the type for defined transports and more informative for a custom transport.
Added `hdgst` and `ddgst` parameters to `bdev_nvme_attach_controller` RPC in order change
state of TCP header and data digest.
Added `num_cqe` parameter to `nvmf_create_transport` RPC to set number of completion queues (CQ)
for RDMA transport. Useful when CQ resize operation is not supported, for example iWARP.
### ocf
Updated OCF submodule to v20.12.2
Added `bdev_ocf_set_cache_mode` RPC to dynamically switch cache mode of OCF bdev.
### opal
Removed the `spdk_opal_supported` API.
### raid
For `bdev_raid_create` RPC, the deprecated parameter `strip_size` was removed.
### rpc
New RPC `bdev_nvme_get_transport_statistics` was added, it allows to get transport statistics
of nvme poll groups.
Parameter `enable-zerocopy-send` of RPC `sock_impl_set_options` is deprecated and will be removed in SPDK 21.07,
use `enable-zerocopy-send-server` or `enable-zerocopy-send-client` instead.
Parameter `disable-zerocopy-send` of RPC `sock_impl_set_options` is deprecated and will be removed in SPDK 21.07,
use `disable-zerocopy-send-server` or `disable-zerocopy-send-client` instead.
### rpm
Added support for new RPM spec, rpmbuild/spdk.spec, which can be used for packaging the
SPDK. The pkg/spdk.spec is considered to be deprecated and scheduled for removal in SPDK 21.07.
See [RPM documentation](https://spdk.io/doc/rpm.html) for more details.
Fixed the bug that no media event is pushed to the target bdev.
### sock
The type of `enable_placement_id` in struct `spdk_sock_impl_opts` is changed from
bool to int. We can use RPC to configure different value of `enable_placement_id`.
Then we can leverage SO_INCOMING_CPU to get placement_id, which aims to utilize
CPU cache locality, enabled by setting enable_placement_id=2.
Added `enable_quickack` and `enable_placement_id` when saving JSON configuration.
A new socket placement mode called PLACEMENT_MARK has been added. Some NICs allow
sockets to be marked using the SO_MARK socket option as a hint for which hardware
queue they should be associated with. This mode leverages that by setting the same
value for all sockets within a poll group.
New parameters `enable_zerocopy_send_server` and `enable_zerocopy_send_client` were added
to struct spdk_sock_impl_opts, these parameters enable or disable zero copy send for server
and client sockets which are created using `spdk_sock_listen` and `spdk_sock_listen_ext` (server);
`spdk_sock_connect` and `spdk_sock_connect_ext` (client) functions. Existing parameter
`enable_zerocopy_send` enables or disables zero copy send for both server and client sockets.
### thread
A new API `spdk_io_channel_get_io_device` was added to get the io_device for the specified
I/O channel.
Added `spdk_thread_set_interrupt_mode` function in order to set present spdk_thread into
interrupt mode or back to poll mode. It is valid only when thread interrupt facility is
enabled by `spdk_interrupt_mode_enable`.
Added `spdk_poller_register_interrupt` function to mark that the poller is capable of
entering interrupt mode. Callback function will be called when the poller must transition
into or out of interrupt mode.
### virtio
Added the `bdev_virtio_blk_set_hotplug` RPC for the virtio blk pci device.
## v21.01:
## v21.01: Dynamic scheduler, vfio-user, ZNS Zone Append
### bdev

4
CONFIG
View File

@ -87,9 +87,6 @@ CONFIG_ENV=
# installation.
CONFIG_DPDK_DIR=
# This directory should contain 'include' and 'lib' directories for WPDK.
CONFIG_WPDK_DIR=
# Build SPDK FIO plugin. Requires CONFIG_FIO_SOURCE_DIR set to a valid
# fio source code directory.
CONFIG_FIO_PLUGIN=n
@ -125,7 +122,6 @@ CONFIG_VIRTIO=y
# Build custom vfio-user transport for NVMf target and NVMe initiator.
CONFIG_VFIO_USER=n
CONFIG_VFIO_USER_DIR=
# Build with PMDK backends
CONFIG_PMDK=n

13
LICENSE
View File

@ -1,16 +1,3 @@
The SPDK repo contains multiple git submodules each with its own
license info. Unless otherwise noted all other code in this repo
is BSD as stated below.
Submodule license info:
dpdk: see dpdk/license
intel-ipsec-mb: see intel-ipsec-mb/LICENSE
isa-l: see isa-l/LICENSE
libvfio-user: see libvfio-user/LICENSE
ocf: see ocf/LICENSE
The rest of the SPDK repo:
BSD LICENSE
Copyright (c) Intel Corporation.

View File

@ -63,13 +63,6 @@ endif
endif
endif
ifeq ($(OS),Windows)
ifeq ($(CURDIR)/wpdk/build,$(CONFIG_WPDK_DIR))
WPDK = wpdk
DIRS-y += wpdk
endif
endif
ifeq ($(CONFIG_SHARED),y)
LIB = shared_lib
else
@ -108,11 +101,10 @@ uninstall: $(DIRS-y)
$(Q)echo "Uninstalled spdk"
ifneq ($(SKIP_DPDK_BUILD),1)
dpdkdeps $(DPDK_DEPS): $(WPDK)
dpdkbuild: $(WPDK) $(DPDK_DEPS)
dpdkbuild: $(DPDK_DEPS)
endif
lib: $(WPDK) $(DPDKBUILD) $(VFIOUSERBUILD)
lib: $(DPDKBUILD) $(VFIOUSERBUILD)
module: lib
shared_lib: module
app: $(LIB)
@ -128,7 +120,7 @@ mk/cc.mk:
false
build_dir: mk/cc.mk
$(Q)mkdir -p build/lib/pkgconfig/tmp
$(Q)mkdir -p build/lib/pkgconfig
$(Q)mkdir -p build/bin
$(Q)mkdir -p build/fio
$(Q)mkdir -p build/examples

View File

@ -41,10 +41,7 @@ DIRS-y += iscsi_top
DIRS-y += iscsi_tgt
DIRS-y += spdk_tgt
DIRS-y += spdk_lspci
ifneq ($(OS),Windows)
# TODO - currently disabled on Windows due to lack of support for curses
DIRS-y += spdk_top
endif
ifeq ($(OS),Linux)
DIRS-$(CONFIG_VHOST) += vhost
DIRS-y += spdk_dd

View File

@ -37,7 +37,6 @@
#include "spdk/event.h"
#include "spdk/fd.h"
#include "spdk/string.h"
#include "spdk/util.h"
#include "spdk/vmd.h"
#include <libaio.h>

View File

@ -84,7 +84,6 @@
#define MAX_POLLER_IND_STR_LEN 8
#define MAX_CORE_MASK_STR_LEN 16
#define MAX_CORE_STR_LEN 6
#define MAX_CORE_FREQ_STR_LEN 18
#define MAX_TIME_STR_LEN 12
#define MAX_POLLER_RUN_COUNT 20
#define MAX_PERIOD_STR_LEN 12
@ -92,14 +91,16 @@
#define FROM_HEX 16
#define THREAD_WIN_WIDTH 69
#define THREAD_WIN_HEIGHT 9
#define THREAD_WIN_HOR_POS 75
#define THREAD_WIN_FIRST_COL 2
#define CORE_WIN_FIRST_COL 16
#define CORE_WIN_WIDTH 48
#define CORE_WIN_HEIGHT 11
#define CORE_WIN_HEIGHT 9
#define CORE_WIN_HOR_POS 60
#define POLLER_WIN_HEIGHT 8
#define POLLER_WIN_WIDTH 64
#define POLLER_WIN_FIRST_COL 14
#define FIRST_DATA_ROW 7
#define POLLER_WIN_HOR_POS 59
enum tabs {
THREADS_TAB,
@ -142,6 +143,7 @@ struct core_info {
uint8_t g_sleep_time = 1;
uint16_t g_selected_row;
uint16_t g_max_selected_row;
struct rpc_thread_info *g_thread_info[MAX_THREADS];
const char *poller_type_str[SPDK_POLLER_TYPES_COUNT] = {"Active", "Timed", "Paused"};
const char *g_tab_title[NUMBER_OF_TABS] = {"[1] THREADS", "[2] POLLERS", "[3] CORES"};
struct spdk_jsonrpc_client *g_rpc_client;
@ -178,7 +180,6 @@ static struct col_desc g_col_desc[NUMBER_OF_TABS][TABS_COL_COUNT] = {
{.name = "Poller count", .max_data_string = MAX_POLLER_COUNT_STR_LEN},
{.name = "Idle [us]", .max_data_string = MAX_TIME_STR_LEN},
{.name = "Busy [us]", .max_data_string = MAX_TIME_STR_LEN},
{.name = "Frequency [MHz]", .max_data_string = MAX_CORE_FREQ_STR_LEN},
{.name = (char *)NULL}
}
};
@ -257,7 +258,6 @@ struct rpc_core_info {
uint32_t lcore;
uint64_t busy;
uint64_t idle;
uint32_t core_freq;
struct rpc_core_threads threads;
};
@ -275,6 +275,7 @@ struct rpc_threads_stats g_threads_stats;
struct rpc_pollers_stats g_pollers_stats;
struct rpc_cores_stats g_cores_stats;
struct rpc_poller_info g_pollers_history[RPC_MAX_POLLERS];
struct rpc_thread_info g_thread_history[RPC_MAX_THREADS];
static void
init_str_len(void)
@ -474,7 +475,6 @@ static const struct spdk_json_object_decoder rpc_core_info_decoders[] = {
{"lcore", offsetof(struct rpc_core_info, lcore), spdk_json_decode_uint32},
{"busy", offsetof(struct rpc_core_info, busy), spdk_json_decode_uint64},
{"idle", offsetof(struct rpc_core_info, idle), spdk_json_decode_uint64},
{"core_freq", offsetof(struct rpc_core_info, core_freq), spdk_json_decode_uint32, true},
{"lw_threads", offsetof(struct rpc_core_info, threads), rpc_decode_cores_lw_threads},
};
@ -544,60 +544,12 @@ rpc_send_req(char *rpc_name, struct spdk_jsonrpc_client_response **resp)
return 0;
}
static int
sort_threads(const void *p1, const void *p2)
{
const struct rpc_thread_info thread_info1 = *(struct rpc_thread_info *)p1;
const struct rpc_thread_info thread_info2 = *(struct rpc_thread_info *)p2;
uint64_t count1, count2;
switch (g_current_sort_col[THREADS_TAB]) {
case 0: /* Sort by name */
return strcmp(thread_info1.name, thread_info2.name);
case 1: /* Sort by core */
count2 = thread_info1.core_num;
count1 = thread_info2.core_num;
break;
case 2: /* Sort by active pollers number */
count1 = thread_info1.active_pollers_count;
count2 = thread_info2.active_pollers_count;
break;
case 3: /* Sort by timed pollers number */
count1 = thread_info1.timed_pollers_count;
count2 = thread_info2.timed_pollers_count;
break;
case 4: /* Sort by paused pollers number */
count1 = thread_info1.paused_pollers_count;
count2 = thread_info2.paused_pollers_count;
break;
case 5: /* Sort by idle time */
count1 = thread_info1.idle - thread_info1.last_idle;
count2 = thread_info2.idle - thread_info2.last_idle;
break;
case 6: /* Sort by busy time */
count1 = thread_info1.busy - thread_info1.last_busy;
count2 = thread_info2.busy - thread_info2.last_busy;
break;
default:
return 0;
}
if (count2 > count1) {
return 1;
} else if (count2 < count1) {
return -1;
} else {
return 0;
}
}
static int
get_data(void)
{
struct spdk_jsonrpc_client_response *json_resp = NULL;
struct rpc_thread_info *thread_info;
struct rpc_core_info *core_info;
struct rpc_threads_stats threads_stats;
uint64_t i, j;
int rc = 0;
@ -607,37 +559,24 @@ get_data(void)
}
/* Decode json */
memset(&threads_stats, 0, sizeof(threads_stats));
if (spdk_json_decode_object(json_resp->result, rpc_threads_stats_decoders,
SPDK_COUNTOF(rpc_threads_stats_decoders), &threads_stats)) {
SPDK_COUNTOF(rpc_threads_stats_decoders), &g_threads_stats)) {
rc = -EINVAL;
goto end;
}
/* This is to free allocated char arrays with old thread names */
free_rpc_threads_stats(&g_threads_stats);
spdk_jsonrpc_client_free_response(json_resp);
for (i = 0; i < threads_stats.threads.threads_count; i++) {
for (j = 0; j < g_threads_stats.threads.threads_count; j++) {
if (g_threads_stats.threads.thread_info[j].id == threads_stats.threads.thread_info[i].id) {
threads_stats.threads.thread_info[i].last_busy = g_threads_stats.threads.thread_info[j].busy;
threads_stats.threads.thread_info[i].last_idle = g_threads_stats.threads.thread_info[j].idle;
}
}
for (i = 0; i < g_threads_stats.threads.threads_count; i++) {
thread_info = &g_threads_stats.threads.thread_info[i];
g_thread_info[thread_info->id] = thread_info;
}
memcpy(&g_threads_stats, &threads_stats, sizeof(struct rpc_threads_stats));
qsort(&g_threads_stats.threads.thread_info, threads_stats.threads.threads_count,
sizeof(g_threads_stats.threads.thread_info[0]), sort_threads);
rc = rpc_send_req("thread_get_pollers", &json_resp);
if (rc) {
goto end;
}
/* Free old pollers values before allocating memory for new ones */
free_rpc_pollers_stats(&g_pollers_stats);
/* Decode json */
memset(&g_pollers_stats, 0, sizeof(g_pollers_stats));
if (spdk_json_decode_object(json_resp->result, rpc_pollers_stats_decoders,
@ -653,9 +592,6 @@ get_data(void)
goto end;
}
/* Free old cores values before allocating memory for new ones */
free_rpc_cores_stats(&g_cores_stats);
/* Decode json */
memset(&g_cores_stats, 0, sizeof(g_cores_stats));
if (spdk_json_decode_object(json_resp->result, rpc_cores_stats_decoders,
@ -668,7 +604,7 @@ get_data(void)
core_info = &g_cores_stats.cores.core[i];
for (j = 0; j < core_info->threads.threads_count; j++) {
g_threads_stats.threads.thread_info[j].core_num = core_info->lcore;
g_thread_info[core_info->threads.thread[j].id]->core_num = core_info->lcore;
}
}
@ -858,6 +794,53 @@ get_time_str(uint64_t ticks, char *time_str)
snprintf(time_str, MAX_TIME_STR_LEN, "%" PRIu64, time);
}
static int
sort_threads(const void *p1, const void *p2)
{
const struct rpc_thread_info *thread_info1 = *(struct rpc_thread_info **)p1;
const struct rpc_thread_info *thread_info2 = *(struct rpc_thread_info **)p2;
uint64_t count1, count2;
switch (g_current_sort_col[THREADS_TAB]) {
case 0: /* Sort by name */
return strcmp(thread_info1->name, thread_info2->name);
case 1: /* Sort by core */
count2 = thread_info1->core_num;
count1 = thread_info2->core_num;
break;
case 2: /* Sort by active pollers number */
count1 = thread_info1->active_pollers_count;
count2 = thread_info2->active_pollers_count;
break;
case 3: /* Sort by timed pollers number */
count1 = thread_info1->timed_pollers_count;
count2 = thread_info2->timed_pollers_count;
break;
case 4: /* Sort by paused pollers number */
count1 = thread_info1->paused_pollers_count;
count2 = thread_info2->paused_pollers_count;
break;
case 5: /* Sort by idle time */
count1 = thread_info1->idle - thread_info1->last_idle;
count2 = thread_info2->idle - thread_info2->last_idle;
break;
case 6: /* Sort by busy time */
count1 = thread_info1->busy - thread_info1->last_busy;
count2 = thread_info2->busy - thread_info2->last_busy;
break;
default:
return 0;
}
if (count2 > count1) {
return 1;
} else if (count2 < count1) {
return -1;
} else {
return 0;
}
}
static void
draw_row_background(uint8_t item_index, uint8_t tab)
{
@ -876,7 +859,7 @@ refresh_threads_tab(uint8_t current_page)
{
struct col_desc *col_desc = g_col_desc[THREADS_TAB];
uint64_t i, threads_count;
uint16_t j;
uint16_t j, k;
uint16_t col;
uint8_t max_pages, item_index;
static uint8_t last_page = 0;
@ -897,16 +880,30 @@ refresh_threads_tab(uint8_t current_page)
g_last_threads_count = threads_count;
}
for (i = 0; i < threads_count; i++) {
thread_info[i] = &g_threads_stats.threads.thread_info[i];
}
/* Thread IDs starts from '1', so we have to take this into account when copying.
* TODO: In future we can have gaps in ID list, so we will need to change the way we
* handle copying threads list below */
memcpy(thread_info, &g_thread_info[1], sizeof(struct rpc_thread_info *) * threads_count);
if (last_page != current_page) {
for (i = 0; i < threads_count; i++) {
/* Thread IDs start from 1, so we have to do i + 1 */
g_threads_stats.threads.thread_info[i].last_idle = g_thread_info[i + 1]->idle;
g_threads_stats.threads.thread_info[i].last_busy = g_thread_info[i + 1]->busy;
}
last_page = current_page;
}
max_pages = (threads_count + g_max_data_rows - 1) / g_max_data_rows;
qsort(thread_info, threads_count, sizeof(thread_info[0]), sort_threads);
for (k = 0; k < threads_count; k++) {
g_thread_history[thread_info[k]->id].busy = thread_info[k]->busy - thread_info[k]->last_busy;
g_thread_history[thread_info[k]->id].idle = thread_info[k]->idle - thread_info[k]->last_idle;
}
for (i = current_page * g_max_data_rows;
i < spdk_min(threads_count, (uint64_t)((current_page + 1) * g_max_data_rows));
i++) {
@ -950,6 +947,7 @@ refresh_threads_tab(uint8_t current_page)
col += col_desc[4].max_data_string + 2;
}
g_thread_history[thread_info[i]->id].idle = thread_info[i]->idle - thread_info[i]->last_idle;
if (!col_desc[5].disabled) {
if (g_interval_data == true) {
get_time_str(thread_info[i]->idle - thread_info[i]->last_idle, idle_time);
@ -961,6 +959,7 @@ refresh_threads_tab(uint8_t current_page)
col += col_desc[5].max_data_string;
}
g_thread_history[thread_info[i]->id].busy = thread_info[i]->busy - thread_info[i]->last_busy;
if (!col_desc[6].disabled) {
if (g_interval_data == true) {
get_time_str(thread_info[i]->busy - thread_info[i]->last_busy, busy_time);
@ -976,6 +975,11 @@ refresh_threads_tab(uint8_t current_page)
}
}
for (k = 0; k < threads_count; k++) {
thread_info[k]->last_idle = thread_info[k]->idle;
thread_info[k]->last_busy = thread_info[k]->busy;
}
g_max_selected_row = i - current_page * g_max_data_rows - 1;
return max_pages;
@ -1346,8 +1350,7 @@ refresh_cores_tab(uint8_t current_page)
uint8_t max_pages, item_index;
static uint8_t last_page = 0;
char core[MAX_CORE_STR_LEN], threads_number[MAX_THREAD_COUNT_STR_LEN],
pollers_number[MAX_POLLER_COUNT_STR_LEN], idle_time[MAX_TIME_STR_LEN],
busy_time[MAX_TIME_STR_LEN], core_freq[MAX_CORE_FREQ_STR_LEN];
pollers_number[MAX_POLLER_COUNT_STR_LEN], idle_time[MAX_TIME_STR_LEN], busy_time[MAX_TIME_STR_LEN];
struct core_info cores[RPC_MAX_CORES];
memset(&cores, 0, sizeof(cores));
@ -1433,18 +1436,6 @@ refresh_cores_tab(uint8_t current_page)
}
print_max_len(g_tabs[CORES_TAB], TABS_DATA_START_ROW + item_index, offset,
col_desc[4].max_data_string, ALIGN_RIGHT, busy_time);
offset += col_desc[4].max_data_string + 2;
}
if (!col_desc[5].disabled) {
if (!g_cores_stats.cores.core[core_num].core_freq) {
snprintf(core_freq, MAX_CORE_FREQ_STR_LEN, "%s", "N/A");
} else {
snprintf(core_freq, MAX_CORE_FREQ_STR_LEN, "%" PRIu32,
g_cores_stats.cores.core[core_num].core_freq);
}
print_max_len(g_tabs[CORES_TAB], TABS_DATA_START_ROW + item_index, offset,
col_desc[5].max_data_string, ALIGN_RIGHT, core_freq);
}
store_core_last_stats(cores[core_num].core, cores[core_num].idle, cores[core_num].busy);
@ -1610,7 +1601,6 @@ filter_columns(uint8_t tab)
ITEM *cur;
void (*p)(enum tabs tab);
uint8_t current_index, len = 0;
bool disabled[TABS_COL_COUNT];
for (i = 0; col_desc[i].name != NULL; ++i) {
len = spdk_max(col_desc[i].name_len, len);
@ -1641,10 +1631,6 @@ filter_columns(uint8_t tab)
goto fail;
}
for (int i = 0; i < TABS_COL_COUNT; i++) {
disabled[i] = col_desc[i].disabled;
}
while (!stop_loop) {
c = wgetch(filter_win);
@ -1657,17 +1643,6 @@ filter_columns(uint8_t tab)
break;
case 27: /* ESC */
case 'q':
for (int i = 0; i < TABS_COL_COUNT; i++) {
cur = current_item(my_menu);
col_desc[i].disabled = disabled[i];
my_items = refresh_filtering_menu(&my_menu, filter_win, tab, my_items, elements,
item_index(cur) + 1);
if (my_items == NULL || my_menu == NULL) {
goto fail;
}
}
stop_loop = true;
break;
case ' ': /* Space */
@ -1922,17 +1897,6 @@ free_resources(void)
}
}
static uint64_t
get_position_for_window(uint64_t window_size, uint64_t max_size)
{
/* This function calculates position for pop-up detail window.
* Since horizontal and vertical positions are calculated the same way
* there is no need for separate functions. */
window_size = spdk_min(window_size, max_size);
return (max_size - window_size) / 2;
}
static void
display_thread(struct rpc_thread_info *thread_info)
{
@ -1951,8 +1915,7 @@ display_thread(struct rpc_thread_info *thread_info)
thread_info->paused_pollers_count;
thread_win = newwin(pollers_count + THREAD_WIN_HEIGHT, THREAD_WIN_WIDTH,
get_position_for_window(THREAD_WIN_HEIGHT + pollers_count, g_max_row),
get_position_for_window(THREAD_WIN_WIDTH, g_max_col));
(g_max_row - pollers_count) / 2, (g_max_col - THREAD_WIN_HOR_POS) / 2);
keypad(thread_win, TRUE);
thread_panel = new_panel(thread_win);
@ -1973,9 +1936,9 @@ display_thread(struct rpc_thread_info *thread_info)
thread_info->core_num);
if (g_interval_data) {
get_time_str(thread_info->idle - thread_info->last_idle, idle_time);
get_time_str(g_thread_history[thread_info->id].idle, idle_time);
mvwprintw(thread_win, 3, THREAD_WIN_FIRST_COL + 32, idle_time);
get_time_str(thread_info->busy - thread_info->last_busy, busy_time);
get_time_str(g_thread_history[thread_info->id].busy, busy_time);
mvwprintw(thread_win, 3, THREAD_WIN_FIRST_COL + 54, busy_time);
} else {
get_time_str(thread_info->idle, idle_time);
@ -2042,6 +2005,7 @@ display_thread(struct rpc_thread_info *thread_info)
c = wgetch(thread_win);
switch (c) {
case 10: /* ENTER */
case 27: /* ESC */
stop_loop = true;
break;
@ -2057,13 +2021,22 @@ display_thread(struct rpc_thread_info *thread_info)
static void
show_thread(uint8_t current_page)
{
struct rpc_thread_info thread_info;
struct rpc_thread_info *thread_info[g_threads_stats.threads.threads_count];
uint64_t thread_number = current_page * g_max_data_rows + g_selected_row;
uint64_t i;
get_data();
assert(thread_number < g_threads_stats.threads.threads_count);
thread_info = g_threads_stats.threads.thread_info[thread_number];
for (i = 0; i < g_threads_stats.threads.threads_count; i++) {
thread_info[i] = &g_threads_stats.threads.thread_info[i];
}
display_thread(&thread_info);
qsort(thread_info, g_threads_stats.threads.threads_count, sizeof(thread_info[0]), sort_threads);
display_thread(thread_info[thread_number]);
free_data();
}
static void
@ -2093,6 +2066,8 @@ show_core(uint8_t current_page)
bool stop_loop = false;
char idle_time[MAX_TIME_STR_LEN], busy_time[MAX_TIME_STR_LEN];
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];
@ -2100,8 +2075,7 @@ show_core(uint8_t current_page)
threads_count = g_cores_stats.cores.core->threads.threads_count;
core_win = newwin(threads_count + CORE_WIN_HEIGHT, CORE_WIN_WIDTH,
get_position_for_window(CORE_WIN_HEIGHT + threads_count, g_max_row),
get_position_for_window(CORE_WIN_WIDTH, g_max_col));
(g_max_row - threads_count) / 2, (g_max_col - CORE_WIN_HOR_POS) / 2);
keypad(core_win, TRUE);
core_panel = new_panel(core_win);
@ -2117,20 +2091,9 @@ show_core(uint8_t current_page)
mvwaddch(core_win, -1, 0, ACS_LTEE);
mvwhline(core_win, 2, 1, ACS_HLINE, CORE_WIN_WIDTH - 2);
mvwaddch(core_win, 2, CORE_WIN_WIDTH, ACS_RTEE);
print_in_middle(core_win, 3, 0, CORE_WIN_WIDTH - (CORE_WIN_WIDTH / 3), "Frequency:", COLOR_PAIR(5));
if (core_info[core_number]->core_freq) {
mvwprintw(core_win, 3, CORE_WIN_FIRST_COL + 15, "%" PRIu32,
core_info[core_number]->core_freq);
} else {
mvwprintw(core_win, 3, CORE_WIN_FIRST_COL + 15, "%s", "N/A");
}
print_left(core_win, 3, 1, CORE_WIN_WIDTH, "Thread count: Idle time:", COLOR_PAIR(5));
mvwaddch(core_win, -1, 0, ACS_LTEE);
mvwhline(core_win, 4, 1, ACS_HLINE, CORE_WIN_WIDTH - 2);
mvwaddch(core_win, 4, CORE_WIN_WIDTH, ACS_RTEE);
print_left(core_win, 5, 1, CORE_WIN_WIDTH, "Thread count: Idle time:", COLOR_PAIR(5));
mvwprintw(core_win, 5, CORE_WIN_FIRST_COL, "%" PRIu64,
mvwprintw(core_win, 3, CORE_WIN_FIRST_COL, "%" PRIu64,
g_cores_history[core_number].threads_count);
if (g_interval_data == true) {
@ -2140,20 +2103,20 @@ show_core(uint8_t current_page)
get_time_str(core_info[core_number]->idle, idle_time);
get_time_str(core_info[core_number]->busy, busy_time);
}
mvwprintw(core_win, 5, CORE_WIN_FIRST_COL + 20, idle_time);
mvwprintw(core_win, 3, CORE_WIN_FIRST_COL + 20, idle_time);
print_left(core_win, 7, 1, CORE_WIN_WIDTH, "Poller count: Busy time:", COLOR_PAIR(5));
mvwprintw(core_win, 7, CORE_WIN_FIRST_COL, "%" PRIu64,
print_left(core_win, 5, 1, CORE_WIN_WIDTH, "Poller count: Busy time:", COLOR_PAIR(5));
mvwprintw(core_win, 5, CORE_WIN_FIRST_COL, "%" PRIu64,
g_cores_history[core_number].pollers_count);
mvwprintw(core_win, 7, CORE_WIN_FIRST_COL + 20, busy_time);
mvwprintw(core_win, 5, CORE_WIN_FIRST_COL + 20, busy_time);
mvwhline(core_win, 4, 1, ACS_HLINE, CORE_WIN_WIDTH - 2);
mvwhline(core_win, 6, 1, ACS_HLINE, CORE_WIN_WIDTH - 2);
mvwhline(core_win, 8, 1, ACS_HLINE, CORE_WIN_WIDTH - 2);
print_left(core_win, 9, 1, CORE_WIN_WIDTH, "Threads on this core", COLOR_PAIR(5));
print_left(core_win, 7, 1, CORE_WIN_WIDTH, "Threads on this core", COLOR_PAIR(5));
for (j = 0; j < core_info[core_number]->threads.threads_count; j++) {
mvwprintw(core_win, j + 10, 1, core_info[core_number]->threads.thread[j].name);
mvwprintw(core_win, j + 8, 1, core_info[core_number]->threads.thread[j].name);
}
refresh();
@ -2164,9 +2127,9 @@ show_core(uint8_t current_page)
while (!stop_loop) {
for (j = 0; j < core_info[core_number]->threads.threads_count; j++) {
if (j != current_threads_row) {
mvwprintw(core_win, j + 10, 1, core_info[core_number]->threads.thread[j].name);
mvwprintw(core_win, j + 8, 1, core_info[core_number]->threads.thread[j].name);
} else {
print_left(core_win, j + 10, 1, CORE_WIN_WIDTH - 2,
print_left(core_win, j + 8, 1, CORE_WIN_WIDTH - 2,
core_info[core_number]->threads.thread[j].name, COLOR_PAIR(2));
}
}
@ -2198,6 +2161,8 @@ show_core(uint8_t current_page)
del_panel(core_panel);
delwin(core_win);
free_data();
}
static void
@ -2205,19 +2170,20 @@ show_poller(uint8_t current_page)
{
PANEL *poller_panel;
WINDOW *poller_win;
uint64_t count = 0;
uint64_t poller_counter = 0, count = 0;
uint64_t poller_number = current_page * g_max_data_rows + g_selected_row;
struct rpc_poller_info *pollers[RPC_MAX_POLLERS];
bool stop_loop = false;
char poller_period[MAX_TIME_STR_LEN];
int c;
get_data();
prepare_poller_data(current_page, pollers, &count, current_page);
assert(poller_number < count);
poller_win = newwin(POLLER_WIN_HEIGHT, POLLER_WIN_WIDTH,
get_position_for_window(POLLER_WIN_HEIGHT, g_max_row),
get_position_for_window(POLLER_WIN_WIDTH, g_max_col));
(g_max_row - poller_counter) / 2, (g_max_col - POLLER_WIN_HOR_POS) / 2);
keypad(poller_win, TRUE);
poller_panel = new_panel(poller_win);
@ -2267,6 +2233,7 @@ show_poller(uint8_t current_page)
while (!stop_loop) {
c = wgetch(poller_win);
switch (c) {
case 10: /* ENTER */
case 27: /* ESC */
stop_loop = true;
break;
@ -2277,6 +2244,8 @@ show_poller(uint8_t current_page)
del_panel(poller_panel);
delwin(poller_win);
free_data();
}
static void
@ -2291,15 +2260,12 @@ show_stats(void)
uint8_t active_tab = THREADS_TAB;
uint8_t current_page = 0;
uint8_t max_pages = 1;
uint16_t required_size = WINDOW_HEADER + 1;
char current_page_str[CURRENT_PAGE_STR_LEN];
bool force_refresh = true;
clock_gettime(CLOCK_REALTIME, &time_now);
time_last = time_now.tv_sec;
memset(&g_threads_stats, 0, sizeof(g_threads_stats));
switch_tab(THREADS_TAB);
while (1) {
@ -2307,34 +2273,13 @@ show_stats(void)
getmaxyx(stdscr, max_row, max_col);
if (max_row != g_max_row || max_col != g_max_col) {
g_max_row = spdk_max(max_row, required_size);
g_max_row = max_row;
g_max_col = max_col;
g_data_win_size = g_max_row - required_size + 1;
g_data_win_size = g_max_row - MENU_WIN_HEIGHT - TAB_WIN_HEIGHT - TABS_DATA_START_ROW;
g_max_data_rows = g_max_row - WINDOW_HEADER;
resize_interface(active_tab);
}
clock_gettime(CLOCK_REALTIME, &time_now);
time_dif = time_now.tv_sec - time_last;
if (time_dif < 0) {
time_dif = g_sleep_time;
}
if (time_dif >= g_sleep_time || force_refresh) {
time_last = time_now.tv_sec;
rc = get_data();
if (rc) {
mvprintw(g_max_row - 1, g_max_col - strlen(refresh_error) - 2, refresh_error);
}
max_pages = refresh_tab(active_tab, current_page);
snprintf(current_page_str, CURRENT_PAGE_STR_LEN - 1, "Page: %d/%d", current_page + 1, max_pages);
mvprintw(g_max_row - 1, 1, current_page_str);
refresh();
}
c = getch();
if (c == 'q') {
free_resources();
@ -2413,19 +2358,39 @@ show_stats(void)
force_refresh = false;
break;
}
clock_gettime(CLOCK_REALTIME, &time_now);
time_dif = time_now.tv_sec - time_last;
if (time_dif < 0) {
time_dif = g_sleep_time;
}
if (time_dif >= g_sleep_time || force_refresh) {
time_last = time_now.tv_sec;
rc = get_data();
if (rc) {
mvprintw(g_max_row - 1, g_max_col - strlen(refresh_error) - 2, refresh_error);
}
max_pages = refresh_tab(active_tab, current_page);
snprintf(current_page_str, CURRENT_PAGE_STR_LEN - 1, "Page: %d/%d", current_page + 1, max_pages);
mvprintw(g_max_row - 1, 1, current_page_str);
free_data();
refresh();
}
}
free_data();
}
static void
draw_interface(void)
{
int i;
uint16_t required_size = WINDOW_HEADER + 1;
getmaxyx(stdscr, g_max_row, g_max_col);
g_max_row = spdk_max(g_max_row, required_size);
g_data_win_size = g_max_row - required_size;
g_data_win_size = g_max_row - MENU_WIN_HEIGHT - TAB_WIN_HEIGHT - TABS_DATA_START_ROW;
g_max_data_rows = g_max_row - WINDOW_HEADER;
g_menu_win = newwin(MENU_WIN_HEIGHT, g_max_col, g_max_row - MENU_WIN_HEIGHT - 1,
@ -2495,40 +2460,13 @@ usage(const char *program_name)
printf("%s [options]", program_name);
printf("\n");
printf("options:\n");
printf(" -r <path> RPC connect address (default: /var/tmp/spdk.sock)\n");
printf(" -r <path> RPC listen address (default: /var/tmp/spdk.sock\n");
printf(" -h show this usage\n");
}
static int
wait_init(void)
{
struct spdk_jsonrpc_client_response *json_resp = NULL;
char *uninit_log = "Waiting for SPDK target application to initialize...",
*uninit_error = "Unable to read SPDK application state!";
int c, max_col, rc = 0;
max_col = getmaxx(stdscr);
print_in_middle(stdscr, FIRST_DATA_ROW, 1, max_col, uninit_log, COLOR_PAIR(5));
rc = rpc_send_req("framework_wait_init", &json_resp);
if (rc) {
spdk_jsonrpc_client_free_response(json_resp);
while (1) {
print_in_middle(stdscr, FIRST_DATA_ROW, 1, max_col, uninit_error, COLOR_PAIR(8));
c = getch();
if (c == 'q') {
return -1;
}
}
}
spdk_jsonrpc_client_free_response(json_resp);
return 0;
}
int main(int argc, char **argv)
{
int op, rc;
int op;
char *socket = SPDK_DEFAULT_RPC_ADDR;
while ((op = getopt(argc, argv, "r:h")) != -1) {
@ -2536,9 +2474,10 @@ int main(int argc, char **argv)
case 'r':
socket = optarg;
break;
case 'H':
default:
usage(argv[0]);
return op == 'h' ? 0 : 1;
return 1;
}
}
@ -2552,11 +2491,7 @@ int main(int argc, char **argv)
init_str_len();
setup_ncurses();
draw_interface();
rc = wait_init();
if (!rc) {
show_stats();
}
show_stats();
finish(0);

View File

@ -613,8 +613,6 @@ int main(int argc, char **argv)
file_name = optarg;
break;
case 'h':
usage();
exit(EXIT_SUCCESS);
default:
usage();
exit(1);

View File

@ -51,7 +51,10 @@ function ocf_precompile() {
function build_native_dpdk() {
local external_dpdk_dir
local external_dpdk_base_dir
local gcc_version
gcc_version=$(gcc -dumpversion)
gcc_version=${gcc_version//./}
external_dpdk_dir="$SPDK_RUN_EXTERNAL_DPDK"
external_dpdk_base_dir="$(dirname $external_dpdk_dir)"
@ -65,9 +68,17 @@ function build_native_dpdk() {
git clone --branch $SPDK_TEST_NATIVE_DPDK --depth 1 http://dpdk.org/git/dpdk "$external_dpdk_base_dir"
git -C "$external_dpdk_base_dir" log --oneline -n 5
dpdk_cflags="-fPIC -g -Werror -fcommon"
dpdk_cflags="-fPIC -g -fcommon"
dpdk_ldflags=""
if [[ $gcc_version -ge 5 ]]; then
dpdk_cflags+=" -Werror"
fi
if [[ $gcc_version -ge 10 ]]; then
dpdk_cflags+=" -Wno-stringop-overflow"
fi
# the drivers we use
# net/i40e driver is not really needed by us, but it's built as a workaround
# for DPDK issue: https://bugs.dpdk.org/show_bug.cgi?id=576
@ -113,7 +124,6 @@ function build_native_dpdk() {
cd $external_dpdk_base_dir
if [ "$(uname -s)" = "Linux" ]; then
dpdk_cflags+=" -Wno-stringop-overflow"
# Fix for freeing device if not kernel driver configured.
# TODO: Remove once this is merged in upstream DPDK
if grep "20.08.0" $external_dpdk_base_dir/VERSION; then
@ -123,12 +133,13 @@ function build_native_dpdk() {
wget https://github.com/karlatec/dpdk/commit/3219c0cfc38803aec10c809dde16e013b370bda9.patch -O dpdk-pci.patch
wget https://github.com/karlatec/dpdk/commit/adf8f7638de29bc4bf9ba3faf12bbdae73acda0c.patch -O dpdk-qat.patch
else
wget https://github.com/karlatec/dpdk/commit/f95e331be3a1f856b816948990dd2afc67ea4020.patch -O dpdk-pci.patch
wget https://github.com/karlatec/dpdk/commit/6fd2fa906ffdcee04e6ce5da40e61cb841be9827.patch -O dpdk-qat.patch
fi
git config --local user.name "spdk"
git config --local user.email "nomail@all.com"
git am dpdk-pci.patch
if [[ -f dpdk-pci.patch ]]; then
git am dpdk-pci.patch
fi
git am dpdk-qat.patch
fi

View File

@ -13,37 +13,6 @@ source "$1"
rootdir=$(readlink -f $(dirname $0))
source "$rootdir/test/common/autotest_common.sh"
function build_rpms() (
local version rpms
# Make sure linker will not attempt to look under DPDK's repo dir to get the libs
unset -v LD_LIBRARY_PATH
install_uninstall_rpms() {
rpms=("$HOME/rpmbuild/RPMS/x86_64/"spdk{,-devel,{,-dpdk}-libs}-$version-1.x86_64.rpm)
sudo rpm -i "${rpms[@]}"
rpms=("${rpms[@]##*/}") rpms=("${rpms[@]%.rpm}")
# Check if we can find one of the apps in the PATH now and verify if it doesn't miss
# any libs.
LIST_LIBS=yes "$rootdir/rpmbuild/rpm-deps.sh" "${SPDK_APP[@]##*/}"
sudo rpm -e "${rpms[@]}"
}
build_rpm() {
MAKEFLAGS="$MAKEFLAGS" SPDK_VERSION="$version" DEPS=no "$rootdir/rpmbuild/rpm.sh" "$@"
install_uninstall_rpms
}
version="test_shared"
run_test "build_shared_rpm" build_rpm --with-shared
if [[ -n $SPDK_TEST_NATIVE_DPDK ]]; then
version="test_shared_native_dpdk"
run_test "build_shared_native_dpdk_rpm" build_rpm --with-shared --with-dpdk="$SPDK_RUN_EXTERNAL_DPDK"
fi
)
out=$PWD
MAKEFLAGS=${MAKEFLAGS:--j16}
@ -59,11 +28,6 @@ if [ $(git status --porcelain --ignore-submodules | wc -l) -ne 0 ]; then
fi
timing_exit porcelain_check
if [[ $SPDK_TEST_RELEASE_BUILD -eq 1 ]]; then
run_test "build_rpms" build_rpms
$MAKE clean
fi
if [[ $RUN_NIGHTLY -eq 0 ]]; then
timing_finish
exit 0

View File

@ -60,6 +60,8 @@ src=$(readlink -f $(dirname $0))
out=$output_dir
cd $src
./scripts/setup.sh status
freebsd_update_contigmem_mod
# lcov takes considerable time to process clang coverage.
@ -125,11 +127,8 @@ if [ $(uname -s) = Linux ]; then
# Export our blocked list so it will take effect during next setup.sh
export PCI_BLOCKED
fi
run_test "setup.sh" "$rootdir/test/setup/test-setup.sh"
fi
./scripts/setup.sh status
if [[ $(uname -s) == Linux ]]; then
# Revert NVMe namespaces to default state
nvme_namespace_revert
@ -152,11 +151,6 @@ timing_enter afterboot
timing_exit afterboot
if [[ $SPDK_TEST_CRYPTO -eq 1 || $SPDK_TEST_REDUCE -eq 1 ]]; then
# Make sure that memory is distributed across all NUMA nodes - by default, all goes to
# node0, but if QAT devices are attached to a different node, all of their VFs will end
# up under that node too and memory needs to be available there for the tests.
CLEAR_HUGE=yes HUGE_EVEN_ALLOC=yes ./scripts/setup.sh
./scripts/setup.sh status
if [[ $SPDK_TEST_USE_IGB_UIO -eq 1 ]]; then
./scripts/qat_setup.sh igb_uio
else
@ -193,9 +187,18 @@ if [ $SPDK_RUN_FUNCTIONAL_TEST -eq 1 ]; then
run_test "blockdev_general" test/bdev/blockdev.sh
run_test "bdev_raid" test/bdev/bdev_raid.sh
run_test "bdevperf_config" test/bdev/bdevperf/test_config.sh
if [[ $(uname -s) == Linux ]]; then
run_test "spdk_dd" test/dd/dd.sh
run_test "reactor_set_interrupt" test/interrupt/reactor_set_interrupt.sh
fi
if [[ $(uname -s) == Linux ]]; then
if [[ $SPDK_TEST_BLOCKDEV -eq 1 || $SPDK_TEST_URING -eq 1 ]]; then
# The crypto job also includes the SPDK_TEST_BLOCKDEV in its configuration hence the
# dd tests are executed there as well. However, these tests can take a significant
# amount of time to complete (up to 4min) on a physical system leading to a potential
# job timeout. Avoid that by skipping these tests - this should not affect the coverage
# since dd tests are still run as part of the vg jobs.
if [[ $SPDK_TEST_CRYPTO -eq 0 ]]; then
run_test "spdk_dd" test/dd/dd.sh
fi
fi
fi
@ -207,9 +210,6 @@ if [ $SPDK_RUN_FUNCTIONAL_TEST -eq 1 ]; then
run_test "blockdev_nvme" test/bdev/blockdev.sh "nvme"
run_test "blockdev_nvme_gpt" test/bdev/blockdev.sh "gpt"
run_test "nvme" test/nvme/nvme.sh
if [[ $SPDK_TEST_NVME_PMR -eq 1 ]]; then
run_test "nvme_pmr" test/nvme/nvme_pmr.sh
fi
if [[ $SPDK_TEST_NVME_CUSE -eq 1 ]]; then
run_test "nvme_cuse" test/nvme/cuse/nvme_cuse.sh
fi

215
configure vendored
View File

@ -7,7 +7,8 @@ trap 'echo -e "\n\nConfiguration failed\n\n" >&2' ERR
rootdir=$(readlink -f $(dirname $0))
source "$rootdir/scripts/common.sh"
function usage() {
function usage()
{
echo "'configure' configures SPDK to compile on supported platforms."
echo ""
echo "Usage: ./configure [OPTION]..."
@ -59,7 +60,7 @@ function usage() {
echo " virtio Build vhost initiator and virtio-pci bdev modules."
echo " No path required."
echo " vfio-user Build custom vfio-user transport for NVMf target and NVMe initiator."
echo " example: /usr/src/libvfio-user"
echo " No path required."
echo " pmdk Build persistent memory bdev."
echo " example: /usr/share/pmdk"
echo " reduce Build vbdev compression module."
@ -96,8 +97,6 @@ function usage() {
echo " No path required."
echo " raid5 Build with bdev_raid module RAID5 support."
echo " No path required."
echo " wpdk Build using WPDK to provide support for Windows (experimental)."
echo " The argument must be a directory containing lib and include."
echo ""
echo "Environment variables:"
echo ""
@ -133,18 +132,14 @@ for i in "$@"; do
done
# Detect the compiler toolchain
$rootdir/scripts/detect_cc.sh --cc="$CC" --cxx="$CXX" --lto="${CONFIG[LTO]}" --ld="$LD" --cross-prefix="${CONFIG[CROSS_PREFIX]}" > $rootdir/mk/cc.mk
$rootdir/scripts/detect_cc.sh --cc="$CC" --cxx="$CXX" --lto="${CONFIG[LTO]}" --ld="$LD" --cross-prefix="${CONFIG[CROSS_PREFIX]}" > $rootdir/mk/cc.mk
CC=$(grep "DEFAULT_CC=" "$rootdir/mk/cc.mk" | sed s/DEFAULT_CC=//)
CC_TYPE=$(grep "CC_TYPE=" "$rootdir/mk/cc.mk" | cut -d "=" -f 2)
CC=$(cat $rootdir/mk/cc.mk | grep "DEFAULT_CC=" | sed s/DEFAULT_CC=//)
CC_TYPE=$(cat $rootdir/mk/cc.mk | grep "CC_TYPE=" | cut -d "=" -f 2)
arch=$($CC -dumpmachine)
sys_name=$(uname -s)
if [[ $arch == *mingw* ]] || [[ $arch == *windows* ]]; then
sys_name=Windows
fi
# Sanitize default configuration. All parameters set by user explicit should fail
# Force no ISA-L if non-x86 or non-aarch64 architecture
if [[ "${CONFIG[ISAL]}" = "y" ]]; then
@ -154,7 +149,7 @@ if [[ "${CONFIG[ISAL]}" = "y" ]]; then
fi
fi
if [[ $sys_name != "Linux" ]]; then
if [[ $sys_name == "FreeBSD" ]]; then
# Vhost, rte_vhost library and virtio are only supported on Linux.
CONFIG[VHOST]="n"
CONFIG[VIRTIO]="n"
@ -163,7 +158,7 @@ fi
#check nasm only on x86
if [[ $arch == x86_64* ]]; then
ver=$(nasm -v 2> /dev/null | awk '{print $3}')
ver=$(nasm -v 2>/dev/null | awk '{print $3}')
if lt "$ver" 2.14; then
# ISA-L, compression & crypto require NASM version 2.14 or newer.
CONFIG[ISAL]=n
@ -188,7 +183,7 @@ function check_dir() {
for i in "$@"; do
case "$i" in
-h | --help)
-h|--help)
usage
exit 0
;;
@ -282,10 +277,6 @@ for i in "$@"; do
--without-dpdk)
CONFIG[DPDK_DIR]=
;;
--with-wpdk=*)
check_dir "$i"
CONFIG[WPDK_DIR]=$(readlink -f ${i#*=})
;;
--with-env=*)
CONFIG[ENV]="${i#*=}"
;;
@ -350,12 +341,6 @@ for i in "$@"; do
;;
--with-vfio-user)
CONFIG[VFIO_USER]=y
CONFIG[VFIO_USER_DIR]=""
;;
--with-vfio-user=*)
CONFIG[VFIO_USER]=y
check_dir "$i"
CONFIG[VFIO_USER_DIR]=$(readlink -f ${i#*=})
;;
--without-vfio-user)
CONFIG[VFIO_USER]=n
@ -459,14 +444,13 @@ for i in "$@"; do
echo "Unrecognized option $i"
usage
exit 1
;;
esac
done
if [[ $arch == x86_64* ]]; then
BUILD_CMD=("$CC" -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS "-march=native")
BUILD_CMD=($CC -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS -march=native)
else
BUILD_CMD=("$CC" -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS)
BUILD_CMD=($CC -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS)
fi
BUILD_CMD+=(-I/usr/local/include -L/usr/local/lib)
@ -496,7 +480,7 @@ if [[ "${CONFIG[IDXD]}" = "y" ]]; then
cpu_vendor=$(sysctl -a | grep hw.model | cut -c 1-15)
else
intel="GenuineIntel"
cpu_vendor=$(grep -i 'vendor' /proc/cpuinfo --max-count=1)
cpu_vendor=$(grep -i 'vendor' /proc/cpuinfo --max-count=1)
fi
if [[ "$cpu_vendor" != *"$intel"* ]]; then
echo "ERROR: IDXD cannot be used due to CPU incompatiblity."
@ -513,8 +497,8 @@ if [[ "${CONFIG[ISAL]}" = "y" ]]; then
fi
if [[ "${CONFIG[ISAL]}" = "n" ]] && [[ "${CONFIG[REDUCE]}" = "y" ]]; then
echo "ERROR Conflicting options: --with-reduce is not compatible with --without-isal."
exit 1
echo "ERROR Conflicting options: --with-reduce is not compatible with --without-isal."
exit 1
fi
if [ -z "${CONFIG[ENV]}" ]; then
@ -549,23 +533,6 @@ else
CONFIG[VIRTIO]="n"
fi
if [[ $sys_name == "Windows" ]]; then
if [ -z "${CONFIG[WPDK_DIR]}" ]; then
if [ ! -f "$rootdir"/wpdk/Makefile ]; then
echo "WPDK not found; please specify --with-wpdk=<path>. See https://wpdk.github.io."
exit 1
else
CONFIG[WPDK_DIR]="${rootdir}/wpdk/build"
echo "Using default WPDK in ${CONFIG[WPDK_DIR]}"
fi
fi
else
if [ -n "${CONFIG[WPDK_DIR]}" ]; then
echo "ERROR: --with-wpdk is only supported for Windows"
exit 1
fi
fi
if [ "${CONFIG[VTUNE]}" = "y" ]; then
if [ -z "${CONFIG[VTUNE_DIR]}" ]; then
echo "When VTune is enabled, you must specify the VTune directory using --with-vtune=path"
@ -573,7 +540,7 @@ if [ "${CONFIG[VTUNE]}" = "y" ]; then
fi
fi
if [[ "${CONFIG[ASAN]}" = "y" && "${CONFIG[TSAN]}" = "y" ]]; then
if [ "${CONFIG[ASAN]}" = "y" -a "${CONFIG[TSAN]}" = "y" ]; then
echo "ERROR: ASAN and TSAN cannot be enabled at the same time."
exit 1
fi
@ -586,7 +553,7 @@ if [[ $sys_name == "FreeBSD" ]]; then
fi
fi
if [[ $sys_name != "Linux" ]]; then
if [[ $sys_name == "FreeBSD" ]]; then
if [[ "${CONFIG[VHOST]}" == "y" ]]; then
echo "Vhost is only supported on Linux."
exit 1
@ -598,22 +565,22 @@ if [[ $sys_name != "Linux" ]]; then
fi
if [ "${CONFIG[RDMA]}" = "y" ]; then
if [[ ! "${CONFIG[RDMA_PROV]}" == "verbs" ]] && [[ ! "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]]; then
echo "Invalid RDMA provider specified, must be \"verbs\" or \"mlx5_dv\""
exit 1
fi
if [[ ! "${CONFIG[RDMA_PROV]}" == "verbs" ]] && [[ ! "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]]; then
echo "Invalid RDMA provider specified, must be \"verbs\" or \"mlx5_dv\""
exit 1
fi
if ! echo -e '#include <infiniband/verbs.h>\n#include <rdma/rdma_verbs.h>\n' \
'int main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -libverbs -lrdmacm - 2> /dev/null; then
echo "--with-rdma requires libverbs and librdmacm."
echo "Please install then re-run this script."
| ${BUILD_CMD[@]} -libverbs -lrdmacm - 2>/dev/null; then
echo --with-rdma requires libverbs and librdmacm.
echo Please install then re-run this script.
exit 1
fi
if echo -e '#include <infiniband/verbs.h>\n' \
'int main(void) { return !!IBV_WR_SEND_WITH_INV; }\n' \
| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
| ${BUILD_CMD[@]} -c - 2>/dev/null; then
CONFIG[RDMA_SEND_WITH_INVAL]="y"
else
CONFIG[RDMA_SEND_WITH_INVAL]="n"
@ -635,7 +602,7 @@ than or equal to 4.14 will see significantly reduced performance.
if echo -e '#include <rdma/rdma_cma.h>\n' \
'int main(void) { return !!RDMA_OPTION_ID_ACK_TIMEOUT; }\n' \
| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
| ${BUILD_CMD[@]} -c - 2>/dev/null; then
CONFIG[RDMA_SET_ACK_TIMEOUT]="y"
else
CONFIG[RDMA_SET_ACK_TIMEOUT]="n"
@ -643,18 +610,18 @@ than or equal to 4.14 will see significantly reduced performance.
fi
if [ "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]; then
if ! echo -e '#include <spdk/stdinc.h>\n' \
'#include <infiniband/mlx5dv.h>\n' \
'#include <rdma/rdma_cma.h>\n' \
'int main(void) { return rdma_establish(NULL) || ' \
'!!IBV_QP_INIT_ATTR_SEND_OPS_FLAGS || !!MLX5_OPCODE_RDMA_WRITE; }\n' \
| "${BUILD_CMD[@]}" -lmlx5 -I${rootdir}/include -c - 2> /dev/null; then
echo "mlx5_dv provider is not supported"
exit 1
fi
if ! echo -e '#include <spdk/stdinc.h>\n' \
'#include <infiniband/mlx5dv.h>\n' \
'#include <rdma/rdma_cma.h>\n' \
'int main(void) { return rdma_establish(NULL) || ' \
'!!IBV_QP_INIT_ATTR_SEND_OPS_FLAGS || !!MLX5_OPCODE_RDMA_WRITE; }\n' \
| ${BUILD_CMD[@]} -lmlx5 -I${rootdir}/include -c - 2>/dev/null; then
echo "mlx5_dv provider is not supported"
exit 1
fi
fi
echo "Using '${CONFIG[RDMA_PROV]}' RDMA provider"
echo "Using "${CONFIG[RDMA_PROV]}" RDMA provider"
fi
if [[ "${CONFIG[FC]}" = "y" ]]; then
@ -678,29 +645,45 @@ if [[ "${CONFIG[ISAL]}" = "y" ]] || [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
fi
fi
if [[ "${CONFIG[ISAL]}" = "y" ]]; then
if [ ! -f "$rootdir"/isa-l/autogen.sh ]; then
echo "ISA-L was not found; To install ISA-L run:"
echo " git submodule update --init"
exit 1
fi
cd $rootdir/isa-l
ISAL_LOG=$rootdir/isa-l/spdk-isal.log
echo -n "Configuring ISA-L (logfile: $ISAL_LOG)..."
./autogen.sh &> $ISAL_LOG
./configure CFLAGS="-fPIC -g -O2" --enable-shared=no >> $ISAL_LOG 2>&1
echo "done."
cd $rootdir
fi
if [[ "${CONFIG[PMDK]}" = "y" ]]; then
if ! echo -e '#include <libpmemblk.h>\nint main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -lpmemblk - 2> /dev/null; then
echo "--with-pmdk requires libpmemblk."
echo "Please install then re-run this script."
| ${BUILD_CMD[@]} -lpmemblk - 2>/dev/null; then
echo --with-pmdk requires libpmemblk.
echo Please install then re-run this script.
exit 1
fi
fi
if [[ "${CONFIG[REDUCE]}" = "y" ]]; then
if ! echo -e '#include <libpmem.h>\nint main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -lpmem - 2> /dev/null; then
echo "--with-reduce requires libpmem."
echo "Please install then re-run this script."
| ${BUILD_CMD[@]} -lpmem - 2>/dev/null; then
echo --with-reduce requires libpmem.
echo Please install then re-run this script.
exit 1
fi
fi
if [[ "${CONFIG[NVME_CUSE]}" = "y" ]]; then
if ! echo -e '#define FUSE_USE_VERSION 31\n#include <fuse3/cuse_lowlevel.h>\n#include <fuse3/fuse_lowlevel.h>\n#include <fuse3/fuse_opt.h>\nint main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -lfuse3 -D_FILE_OFFSET_BITS=64 - 2> /dev/null; then
echo "--with-cuse requires libfuse3."
echo "Please install then re-run this script."
| ${BUILD_CMD[@]} -lfuse3 -D_FILE_OFFSET_BITS=64 - 2>/dev/null; then
echo --with-cuse requires libfuse3.
echo Please install then re-run this script.
exit 1
fi
fi
@ -708,9 +691,9 @@ fi
if [[ "${CONFIG[RBD]}" = "y" ]]; then
if ! echo -e '#include <rbd/librbd.h>\n#include <rados/librados.h>\n' \
'int main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -lrados -lrbd - 2> /dev/null; then
echo "--with-rbd requires librados and librbd."
echo "Please install then re-run this script."
| ${BUILD_CMD[@]} -lrados -lrbd - 2>/dev/null; then
echo --with-rbd requires librados and librbd.
echo Please install then re-run this script.
exit 1
fi
fi
@ -722,39 +705,39 @@ if [[ "${CONFIG[ISCSI_INITIATOR]}" = "y" ]]; then
'#error\n' \
'#endif\n' \
'int main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -L/usr/lib64/iscsi -liscsi - 2> /dev/null; then
echo "--with-iscsi-initiator requires libiscsi with"
echo "LIBISCSI_API_VERSION >= 20150621."
echo "Please install then re-run this script."
| ${BUILD_CMD[@]} -L/usr/lib64/iscsi -liscsi - 2>/dev/null; then
echo --with-iscsi-initiator requires libiscsi with
echo 'LIBISCSI_API_VERSION >= 20150621.'
echo Please install then re-run this script.
exit 1
fi
fi
if [[ "${CONFIG[ASAN]}" = "y" ]]; then
if ! echo -e 'int main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -fsanitize=address - 2> /dev/null; then
echo "--enable-asan requires libasan."
echo "Please install then re-run this script."
| ${BUILD_CMD[@]} -fsanitize=address - 2>/dev/null; then
echo --enable-asan requires libasan.
echo Please install then re-run this script.
exit 1
fi
fi
if [[ "${CONFIG[UBSAN]}" = "y" ]]; then
if ! echo -e 'int main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -fsanitize=undefined - 2> /dev/null; then
echo "--enable-ubsan requires libubsan."
echo "Please install then re-run this script."
echo "If installed, please check that the GCC version is at least 6.4"
echo "and synchronize CC accordingly."
| ${BUILD_CMD[@]} -fsanitize=undefined - 2>/dev/null; then
echo --enable-ubsan requires libubsan.
echo Please install then re-run this script.
echo If installed, please check that the GCC version is at least 6.4 \
and synchronize CC accordingly.
exit 1
fi
fi
if [[ "${CONFIG[TSAN]}" = "y" ]]; then
if ! echo -e 'int main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -fsanitize=thread - 2> /dev/null; then
echo "--enable-tsan requires libtsan."
echo "Please install then re-run this script."
| ${BUILD_CMD[@]} -fsanitize=thread - 2>/dev/null; then
echo --enable-tsan requires libtsan.
echo Please install then re-run this script.
exit 1
fi
fi
@ -785,11 +768,6 @@ if [[ "${CONFIG[URING]}" = "y" ]]; then
echo "${CONFIG[URING_PATH]}: directory not found"
exit 1
fi
elif ! echo -e '#include <liburing.h>\nint main(void) { return 0; }\n' \
| "${BUILD_CMD[@]}" -luring - 2> /dev/null; then
echo "--with-uring requires liburing."
echo "Please build and install then re-run this script."
exit 1
fi
fi
@ -802,50 +780,29 @@ if [[ "${CONFIG[FUSE]}" = "y" ]]; then
fi
if [ "${CONFIG[CET]}" = "y" ]; then
if ! echo -e 'int main(void) { return 0; }\n' | "${BUILD_CMD[@]}" -fcf-protection - 2> /dev/null; then
echo "--enable-cet requires compiler/linker that supports CET."
echo "Please install then re-run this script."
if ! echo -e 'int main(void) { return 0; }\n' | ${BUILD_CMD[@]} -fcf-protection - 2>/dev/null; then
echo --enable-cet requires compiler/linker that supports CET.
echo Please install then re-run this script.
exit 1
fi
fi
if [[ "${CONFIG[ISAL]}" = "y" ]]; then
if [ ! -f "$rootdir"/isa-l/autogen.sh ]; then
echo "ISA-L was not found; To install ISA-L run:"
echo " git submodule update --init"
exit 1
fi
cd $rootdir/isa-l
ISAL_LOG=$rootdir/isa-l/spdk-isal.log
if [[ -n "${CONFIG[CROSS_PREFIX]}" ]]; then
ISAL_OPTS=("--host=${CONFIG[CROSS_PREFIX]}")
else
ISAL_OPTS=()
fi
echo -n "Configuring ISA-L (logfile: $ISAL_LOG)..."
./autogen.sh &> $ISAL_LOG
./configure CFLAGS="-fPIC -g -O2" "${ISAL_OPTS[@]}" --enable-shared=no >> $ISAL_LOG 2>&1
echo "done."
cd $rootdir
fi
# We are now ready to generate final configuration. But first do sanity
# check to see if all keys in CONFIG array have its reflection in CONFIG file.
if (($(grep -cE "^\s*CONFIG_[[:alnum:]_]+=" "$rootdir/CONFIG") != ${#CONFIG[@]})); then
if [ $(egrep -c "^\s*CONFIG_[[:alnum:]_]+=" $rootdir/CONFIG) -ne ${#CONFIG[@]} ]; then
echo ""
echo "BUG: Some configuration options are not present in CONFIG file. Please update this file."
echo "Missing options in CONFIG (+) file and in current config (-): "
diff -u --label "CONFIG file" --label "CONFIG[@]" \
<(sed -r -e '/^\s*$/d; /^\s*#.*/d; s/(CONFIG_[[:alnum:]_]+)=.*/\1/g' CONFIG | sort) \
<(printf "CONFIG_%s\n" "${!CONFIG[@]}" | sort)
<(printf "CONFIG_%s\n" ${!CONFIG[@]} | sort)
exit 1
fi
echo -n "Creating mk/config.mk..."
cp -f $rootdir/CONFIG $rootdir/mk/config.mk
for key in "${!CONFIG[@]}"; do
sed -i.bak -r "s#[[:space:]]*CONFIG_${key}=.*#CONFIG_${key}\?=${CONFIG[$key]}#g" $rootdir/mk/config.mk
for key in ${!CONFIG[@]}; do
sed -i.bak -r "s#^\s*CONFIG_${key}=.*#CONFIG_${key}\?=${CONFIG[$key]}#g" $rootdir/mk/config.mk
done
# On FreeBSD sed -i 'SUFFIX' - SUFFIX is mandatory. So no way but to delete the backed file.
rm -f $rootdir/mk/config.mk.bak
@ -863,7 +820,7 @@ echo "done."
# Create .sh with build config for easy sourcing|lookup during the tests.
for conf in "${!CONFIG[@]}"; do
echo "CONFIG_$conf=${CONFIG[$conf]}"
done > "$rootdir/test/common/build_config.sh"
done >"$rootdir/test/common/build_config.sh"
if [[ $sys_name == "FreeBSD" ]]; then
echo "Type 'gmake' to build."

View File

@ -1,42 +0,0 @@
# ABI and API Deprecation {#deprecation}
This document details the policy for maintaining stability of SPDK ABI and API.
Major ABI version can change at most once for each quarterly SPDK release.
ABI versions are managed separately for each library and follow [Semantic Versoning](https://semver.org/).
API and ABI deprecation notices shall be posted in the next section.
Each entry must describe what will be removed and can suggest the future use or alternative.
Specific future SPDK release for the removal must be provided.
ABI cannot be removed without providing deprecation notice for at least single SPDK release.
# Deprecation Notices {#deprecation-notices}
## net
The net library is deprecated and will be removed in the 21.07 release.
## nvmf
The following APIs have been deprecated and will be removed in SPDK 21.07:
- `spdk_nvmf_poll_group_get_stat` (function in `nvmf.h`),
- `spdk_nvmf_transport_poll_group_get_stat` (function in `nvmf.h`),
- `spdk_nvmf_transport_poll_group_free_stat`(function in `nvmf.h`),
- `spdk_nvmf_rdma_device_stat` (struct in `nvmf.h`),
- `spdk_nvmf_transport_poll_group_stat` (struct in `nvmf.h`),
- `poll_group_get_stat` (transport op in `nvmf_transport.h`),
- `poll_group_free_stat` (transport op in `nvmf_transport.h`).
Please use `spdk_nvmf_poll_group_dump_stat` and `poll_group_dump_stat` instead.
## rpc
Parameter `enable-zerocopy-send` of RPC `sock_impl_set_options` is deprecated and will be removed in SPDK 21.07,
use `enable-zerocopy-send-server` or `enable-zerocopy-send-client` instead.
Parameter `disable-zerocopy-send` of RPC `sock_impl_set_options` is deprecated and will be removed in SPDK 21.07,
use `disable-zerocopy-send-server` or `disable-zerocopy-send-client` instead.
## rpm
`pkg/spdk.spec` is considered to be deprecated and scheduled for removal in SPDK 21.07.
Please use `rpmbuild/spdk.spec` instead and see
[RPM documentation](https://spdk.io/doc/rpm.html) for more details.

View File

@ -234,7 +234,7 @@ ALIASES =
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
# TCL_SUBST =
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
@ -813,7 +813,6 @@ INPUT += \
compression.md \
concurrency.md \
containers.md \
../deprecation.md \
event.md \
ftl.md \
gdb_macros.md \
@ -836,7 +835,6 @@ INPUT += \
peer_2_peer.md \
pkgconfig.md \
porting.md \
rpm.md \
scheduler.md \
shfmt.md \
spdkcli.md \
@ -1105,7 +1103,7 @@ ALPHABETICAL_INDEX = YES
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
# COLS_IN_ALPHA_INDEX = 5
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
@ -1666,7 +1664,7 @@ EXTRA_SEARCH_MAPPINGS =
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@ -2170,7 +2168,7 @@ EXTERNAL_PAGES = YES
# interpreter (i.e. the result of 'which perl').
# The default file (with absolute path) is: /usr/bin/perl.
# PERL_PATH = /usr/bin/perl
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
@ -2192,7 +2190,7 @@ CLASS_DIAGRAMS = YES
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
# MSCGEN_PATH =
MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The

View File

@ -66,14 +66,14 @@ To use the IOAT engine, use the RPC [`ioat_scan_accel_engine`](https://spdk.io/d
To use the DSA engine, use the RPC [`idxd_scan_accel_engine`](https://spdk.io/doc/jsonrpc.html) with an optional parameter of `-c` and provide a configuration number of either 0 or 1. These pre-defined configurations determine how the DSA engine will be setup in terms
of work queues and engines. The DSA engine is very flexible allowing for various configurations of these elements to either account for different quality of service requirements or to isolate hardware paths where the back end media is of varying latency (i.e. persistent memory vs DRAM). The pre-defined configurations are as follows:
0: A single work queue backed with four DSA engines. This is a generic configuration
that enables the hardware to best determine which engine to use as it pulls in new
operations.
0: Four separate work queues each backed with one DSA engine. This is a generic
configuration that provides 4 portals to submit operations to each with a
single engine behind it providing some level of isolation as operations are
submitted round-robin.
1: Two separate work queues each backed with two DSA engines. This is another
generic configuration that is documented in the specification and allows the
application to partition submissions across two work queues. This would be useful
when different priorities might be desired per group.
1: Two separate work queues each backed with two DSA engines. This is another
generic configuration that provides 2 portals to submit operations to and
lets the DSA hardware decide which engine to select based on loading.
There are several other configurations that are possible that include quality
of service parameters on the work queues that are not currently utilized by

View File

@ -312,8 +312,10 @@ To remove `Cache1`:
During removal OCF-cache will be stopped and all cached data will be written to the core device.
Note that OCF has a per-device RAM requirement. More details can be found in the
[OCF documentation](https://open-cas.github.io/guide_system_requirements.html).
Note that OCF has a per-device RAM requirement
of about 56000 + _cache device size_ * 58 / _cache line size_ (in bytes).
To get more information on OCF
please visit [OCF documentation](https://open-cas.github.io/).
# Malloc bdev {#bdev_config_malloc}
@ -369,22 +371,15 @@ This command will remove NVMe bdev named Nvme0.
## NVMe bdev character device {#bdev_config_nvme_cuse}
This feature is considered as experimental. You must configure with --with-nvme-cuse
option to enable this RPC.
This feature is considered as experimental.
Example commands
`rpc.py bdev_nvme_cuse_register -n Nvme3
`rpc.py bdev_nvme_cuse_register -n Nvme0 -p spdk/nvme0`
This command will register a character device under /dev/spdk associated with Nvme3
controller. If there are namespaces created on Nvme3 controller, a namespace
character device is also created for each namespace.
For example, the first controller registered will have a character device path of
/dev/spdk/nvmeX, where X is replaced with a unique integer to differentiate it from
other controllers. Note that this 'nvmeX' name here has no correlation to the name
associated with the controller in SPDK. Namespace character devices will have a path
of /dev/spdk/nvmeXnY, where Y is the namespace ID.
This command will register /dev/spdk/nvme0 character device associated with Nvme0
controller. If there are namespaces created on Nvme0 controller, for each namespace
device /dev/spdk/nvme0nX is created.
Cuse devices are removed from system, when NVMe controller is detached or unregistered
with command:

View File

@ -14,24 +14,24 @@ make
~~~
Clone the RocksDB repository from the SPDK GitHub fork into a separate directory.
Make sure you check out the `6.15.fb` branch.
Make sure you check out the `spdk-v5.14.3` branch.
~~~{.sh}
cd ..
git clone -b 6.15.fb https://github.com/spdk/rocksdb.git
git clone -b spdk-v5.14.3 https://github.com/spdk/rocksdb.git
~~~
Build RocksDB. Only the `db_bench` benchmarking tool is integrated with BlobFS.
~~~{.sh}
cd rocksdb
make db_bench SPDK_DIR=relative_path/to/spdk
make db_bench SPDK_DIR=path/to/spdk
~~~
Or you can also add `DEBUG_LEVEL=0` for a release build (need to turn on `USE_RTTI`).
~~~{.sh}
export USE_RTTI=1 && make db_bench DEBUG_LEVEL=0 SPDK_DIR=relative_path/to/spdk
export USE_RTTI=1 && make db_bench DEBUG_LEVEL=0 SPDK_DIR=path/to/spdk
~~~
Create an NVMe section in the configuration file using SPDK's `gen_nvme.sh` script.

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,4 +1,4 @@
# Storage Performance Development Kit {#mainpage}
# Storage Performance Development Kit {#index}
# Introduction

View File

@ -4,5 +4,4 @@
- @subpage getting_started
- @subpage vagrant
- @subpage changelog
- @subpage deprecation
- [Source Code (GitHub)](https://github.com/spdk/spdk)

File diff suppressed because it is too large Load Diff

View File

@ -191,23 +191,3 @@ shim/implementation library system.
# two libraries
gcc -o my_app ./my_app.c -lspdk -lcustom_env_shim -lcustom_env_implementation
~~~
# SPDK Static Objects {#static_objects}
SPDK static objects are compiled by default even when no parameters are supplied to the build system.
Unlike SPDK shared objects, the filename does not contain any versioning semantics. Linking against
static objects is similar to shared objects but will always require the use of `-Wl,--whole-archive`
as argument. This is due to the use of constructor functions in SPDK such as those to register
NVMe transports.
Due to the lack of versioning semantics, it is not recommended to install static libraries system wide.
Instead the path to these static libraries should be added as argument at compile time using
`-L/path/to/static/libs`. The use of static objects instead of shared objects can also be forced
through `-Wl,-Bsatic`, otherwise some compilers might prefer to use the shared objects if both
are available.
~~~{.sh}
gcc -o my_app ./my_app.c -L/path/to/static/libs -Wl,--whole-archive -Wl,-Bstatic -lpassthru_external
-lspdk_event_bdev -lspdk_bdev -lspdk_bdev_malloc -lspdk_log -lspdk_thread -lspdk_util -lspdk_event
-lspdk_env_dpdk -Wl,--no-whole-archive -Wl,-Bdynamic -pthread -ldpdk
~~~

View File

@ -106,14 +106,16 @@ using 1GB hugepages or by pre-reserving memory at application startup with `--me
option. All pre-reserved memory will be registered as a single region, but won't be returned to the
system until the SPDK application is terminated.
Another known issue occurs when using the E810 NICs in RoCE mode. Specifically, the NVMe-oF target
sometimes cannot destroy a qpair, because its posted work requests don't get flushed. It can cause
the NVMe-oF target application unable to terminate cleanly.
## TCP transport support {#nvmf_tcp_transport}
The transport is built into the nvmf_tgt by default, and it does not need any special libraries.
## Configuring the SPDK NVMe over Fabrics Target {#nvmf_config}
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.
## 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.
@ -141,12 +143,6 @@ cd ../spdk
make
~~~
## Configuring the SPDK NVMe over Fabrics Target {#nvmf_config}
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 RPCs {#nvmf_config_rpc}
Start the nvmf_tgt application with elevated privileges. Once the target is started,

View File

@ -68,7 +68,7 @@ system. This is used for access control.
A user of the NVMe-oF target library begins by creating a target using
spdk_nvmf_tgt_create(), setting up a set of addresses on which to accept
connections by calling spdk_nvmf_tgt_listen_ext(), then creating a subsystem
connections by calling spdk_nvmf_tgt_listen(), then creating a subsystem
using spdk_nvmf_subsystem_create().
Subsystems begin in an inactive state and must be activated by calling
@ -78,7 +78,7 @@ calling spdk_nvmf_subsystem_pause() and resumed by calling
spdk_nvmf_subsystem_resume().
Namespaces may be added to the subsystem by calling
spdk_nvmf_subsystem_add_ns_ext() when the subsystem is inactive or paused.
spdk_nvmf_subsystem_add_ns() when the subsystem is inactive or paused.
Namespaces are bdevs. See @ref bdev for more information about the SPDK bdev
layer. A bdev may be obtained by calling spdk_bdev_get_by_name().

View File

@ -1,12 +1,5 @@
# Performance Reports {#performance_reports}
## Release 21.01
- [SPDK 21.01 NVMe Bdev Performance Report](https://ci.spdk.io/download/performance-reports/SPDK_nvme_bdev_perf_report_2101.pdf)
- [SPDK 21.01 NVMe-oF TCP Performance Report](https://ci.spdk.io/download/performance-reports/SPDK_tcp_perf_report_2101.pdf)
- [SPDK 21.01 NVMe-oF RDMA Performance Report](https://ci.spdk.io/download/performance-reports/SPDK_rdma_perf_report_2101.pdf)
- [SPDK 21.01 Vhost Performance Report](https://ci.spdk.io/download/performance-reports/SPDK_vhost_perf_report_2101.pdf)
## Release 20.10
- [SPDK 20.10 NVMe Bdev Performance Report](https://ci.spdk.io/download/performance-reports/SPDK_nvme_bdev_perf_report_2010.pdf)

View File

@ -28,10 +28,9 @@ PKG_CONFIG_PATH=/path/to/spdk/build/lib/pkgconfig pkg-config --libs spdk_syslibs
Note that SPDK libraries use constructor functions liberally, so you must surround
the library list with extra linker options to ensure these functions are not dropped
from the resulting application binary. With shared libraries this is achieved through
the `-Wl,--no-as-needed` parameters while with static libraries `-Wl,--whole-archive`
is used. Here is an example Makefile snippet that shows how to use pkg-config to link
an application that uses the SPDK nvme shared library:
from the resulting application binary. Here is an example Makefile snippet that
shows how to use pkg-config to link an application that uses the SPDK nvme shared
library:
~~~
PKG_CONFIG_PATH = $(SPDK_DIR)/build/lib/pkgconfig

View File

@ -1,49 +0,0 @@
# RPMs {#rpms}
# In this document {#rpms_toc}
* @ref building_rpms
# Building SPDK RPMs {#building_rpms}
To build basic set of RPM packages out of the SPDK repo simply run:
~~~{.sh}
# rpmbuild/rpm.sh
~~~
Additional configuration options can be passed directly as arguments:
~~~{.sh}
# rpmbuild/rpm.sh --with-shared --with-dpdk=/path/to/dpdk/build
~~~
There are several options that may be passed via environment as well:
- DEPS - Install all needed dependencies for building RPM packages.
Default: "yes"
- MAKEFLAGS - Flags passed to make
- RPM_RELEASE - Target release version of the RPM packages. Default: 1
- REQUIREMENTS - Extra set of RPM dependencies if deemed as needed
- SPDK_VERSION - SPDK version. Default: currently checked out tag
~~~{.sh}
# DEPS=no MAKEFLAGS="-d -j1" rpmbuild/rpm.sh --with-shared
~~~
By default, all RPM packages should be created under $HOME directory of the
target user:
~~~{.sh}
# printf '%s\n' /root/rpmbuild/RPMS/x86_64/*
/root/rpmbuild/RPMS/x86_64/spdk-devel-v21.01-1.x86_64.rpm
/root/rpmbuild/RPMS/x86_64/spdk-dpdk-libs-v21.01-1.x86_64.rpm
/root/rpmbuild/RPMS/x86_64/spdk-libs-v21.01-1.x86_64.rpm
/root/rpmbuild/RPMS/x86_64/spdk-v21.01-1.x86_64.rpm
#
~~~
- spdk - provides all the binaries, common tooling, etc.
- spdk-devel - provides development files
- spdk-libs - provides target lib, .pc files (--with-shared)
- spdk-dpdk-libs - provides dpdk lib files (--with-shared|--with-dpdk)

View File

@ -5,7 +5,7 @@ The spdk_top application is designed to resemble the standard top in that it pro
Why doesn't the classic top utility work for SPDK? SPDK uses a polled-mode design; a reactor thread running on each CPU core assigned to an SPDK application schedules SPDK lightweight threads and pollers to run on the CPU core. Therefore, the standard Linux top utility is not effective for analyzing the CPU usage for polled-mode applications like SPDK because it just reports that they are using 100% of the CPU resources assigned to them. The spdk_top utility was developed to analyze and report the CPU cycles used to do real work vs just polling for work. The utility relies on instrumentation added to pollers to track when they are doing work vs. polling for work. The spdk_top utility gets the fine grained metrics from the pollers, analyzes and report the metrics on a per poller, thread and core basis. This information enables users to identify CPU cores that are busy doing real work so that they can determine if the application needs more or less CPU resources.
# Run spdk_top
Before running spdk_top you need to run the SPDK application whose performance you want to analyze using spdk_top.
Before running spdk_top you need to run the SPDK application whose performance you want to analyze using spdk_top. For example, the nvmf_tgt application was running when we used the spdk_top to capture the screen shots in this documentation.
Run the spdk_top application
@ -13,53 +13,33 @@ Run the spdk_top application
./build/bin/spdk_top
~~~
# Bottom menu
Menu at the bottom of SPDK top window shows many options for changing displayed data. Each menu item has a key associated with it in square brackets.
* Quit - quits the SPDK top application.
* TAB selection - allows to select THREADS/POLLERS/CORES tabs.
* Previous page/Next page - scrolls up/down to the next set of rows displayed. Indicator in the bottom-left corner shows current page and number of all available pages.
* Columns - enables/disables chosen columns in a column pop-up window.
* Sorting - allows to sort displayed data by column in a sorting pop-up.
* Refresh rate - takes user input from 0 to 255 and changes refresh rate to that value in seconds.
* Item details - displays details pop-up window for highlighted data row. Selection is changed by pressing UP and DOWN arrow keys.
* Total/Interval - changes displayed values in all tabs to either Total time (measured since start of SPDK application) or Interval time (measured since last refresh).
The spdk_top application has 3 tabs: the cores, threads and pollers tabs.
# Threads Tab
The threads tab displays a line item for each spdk thread. The information displayed shows:
The threads tab displays a line item for each spdk thread that includes information such as which CPU core the spdk thread is running on, how many pollers the thread is running and how many microseconds was the thread busy/idle. The pollers are grouped into active, timed and pause pollers. To learn more about spdk threads see @ref concurrency.
* Thread name - name of SPDK thread.
* Core - core on which the thread is currently running.
* Active/Timed/Paused pollers - number of pollers grouped by type on this thread.
* Idle/Busy - how many microseconds the thread was idle/busy.
\n
By pressing ENTER key a pop-up window appears, showing above and a list of pollers running on selected thread (with poller name, type, run count and period).
Pop-up then can be closed by pressing ESC key.
To learn more about spdk threads see @ref concurrency.
![Threads Tab](img/spdk_top_page1_threads.png)
# Pollers Tab
The pollers tab displays a line item for each poller. The information displayed shows:
The pollers tab displays a line item for each poller and a running counter of the number of times the poller has run so that you can see which pollers are running most frequently.
* Poller name - name of currently selected poller.
* Type - type of poller (Active/Paused/Timed).
* On thread - thread on which the poller is running.
* Run count - how many times poller was run.
* Period - poller period in microseconds. If period equals 0 then it is not displayed.
* Status - whether poller is currently Busy (red color) or Idle (blue color).
\n
Poller pop-up window can be displayed by pressing ENTER on a selected data row and displays above information.
Pop-up can be closed by pressing ESC key.
![Pollers Tab](img/spdk_top_page2_pollers.png)
# Cores Tab
The cores tab provides insights into how the application is using the CPU cores assigned to it. The information displayed for each core shows:
The cores tab provides insights into how the application is using the CPU cores assigned to it.
It has a line item for each CPU core assigned to the application which shows the number of threads and poller
running on the CPU core. The tab also indicates how busy/idle the each CPU core was in the last 1 second.
The busy column displays how many microseconds the CPU core was doing actual work in the last 1 second.
The idle column displays how many microseconds the CPU core was idle in the last 1 second,
including the time when the CPU core ran pollers but did not find any work.
* Core - core number.
* Thread count - number of threads currently running on core.
* Poller count - total number of pollers running on core.
* Idle/Busy - how many microseconds core was idle (including time when core ran pollers but did not find any work) or doing actual work.
![Cores Tab](img/spdk_top_page3_cores.png)
\n
Pressing ENTER key makes a pop-up window appear, showing above information, along with a list of threads running on selected core. Cores details window allows to select a thread and display thread details pop-up on top of it. To close both pop-ups use ESC key.
# Refresh Rate
You can control how often the spdk_top application refreshes the data displayed by hitting the 'r' key on your keyboard and specifying a value between 0 and 255 seconds.
# Sorting
You can sort the data displayed by hitting the 's' key on your keyboard and selecting a column to sort by in the sub menu that is displayed.
# Filtering
You can filter out any column by hitting the 'c' key on your keyboard and unselecting the column in the menu that is displayed.

2
dpdk

@ -1 +1 @@
Subproject commit 4f93dbc0c0ab3804abaa20123030ad7fccf78709
Subproject commit 707692e67d0c6c685c42f5dd48f8f112bde6b381

View File

@ -45,10 +45,6 @@ DPDK_KMODS = true
endif
DPDK_OPTS += -Denable_kmods=$(DPDK_KMODS)
ifeq ($(CONFIG_DEBUG),y)
DPDK_OPTS += --buildtype=debug
endif
# the drivers we use
DPDK_DRIVERS = bus bus/pci bus/vdev mempool/ring
@ -73,16 +69,16 @@ endif
DPDK_OPTS += -Dmachine=$(TARGET_ARCHITECTURE)
ifneq ($(CONFIG_CROSS_PREFIX),)
ifeq ($(findstring mingw,$(CONFIG_CROSS_PREFIX)),mingw)
DPDK_OPTS += --cross-file $(SPDK_ROOT_DIR)/dpdk/config/x86/cross-mingw
else
$(error Automatic DPDK cross build is not supported. Please compile DPDK manually \
with e.g. `meson build --cross-file config/arm/arm64_armv8_linux_gcc`)
endif
endif
DPDK_CFLAGS += -fPIC
ifeq ($(CONFIG_DEBUG),y)
DPDK_CFLAGS += -O0 -g
endif
ifeq ($(CONFIG_WERROR),y)
DPDK_CFLAGS += -Werror
else
@ -121,7 +117,7 @@ DPDK_ALL_DRIVER_DIRS = $(shell find $(SPDK_ROOT_DIR)/dpdk/drivers -mindepth 1 -t
DPDK_ALL_DRIVERS = $(DPDK_ALL_DRIVER_DIRS:$(SPDK_ROOT_DIR)/dpdk/drivers/%=%)
DPDK_DISABLED_DRVERS = $(filter-out $(DPDK_DRIVERS),$(DPDK_ALL_DRIVERS))
ifneq ($(OS),FreeBSD)
ifeq ($(OS),Linux)
SED_INPLACE_FLAG = "-i"
MESON_PREFIX = $(SPDK_ROOT_DIR)/dpdk/build
else
@ -137,7 +133,7 @@ ifeq ($(MAKE_PID),)
MAKE_PID := $(shell echo $$PPID)
endif
MAKE_NUMJOBS := $(shell ps T | sed -nE 's/[[:space:]]*$(MAKE_PID)[[:space:]].* (-j|--jobs=)( *[0-9]+).*/\1\2/p')
MAKE_NUMJOBS := $(shell ps T | sed -nE 's/\s*$(MAKE_PID)\s.* (-j|--jobs=)( *[0-9]+).*/\1\2/p')
all: $(SPDK_ROOT_DIR)/dpdk/build-tmp
$(Q)# DPDK doesn't handle nested make calls, so unset MAKEFLAGS

View File

@ -45,15 +45,12 @@
#define ALIGN_4K 0x1000
static uint64_t g_tsc_rate;
static uint64_t g_tsc_us_rate;
static uint64_t g_tsc_end;
static int g_rc;
static int g_xfer_size_bytes = 4096;
static int g_queue_depth = 32;
static int g_ops_per_batch = 0;
static int g_threads_per_core = 1;
static int g_time_in_sec = 5;
static uint32_t g_crc32c_seed = 0;
static uint32_t g_crc32c_chained_count = 1;
static int g_fail_percent_goal = 0;
static uint8_t g_fill_pattern = 255;
static bool g_verify = false;
@ -67,15 +64,8 @@ uint64_t g_capabilites;
struct worker_thread;
static void accel_done(void *ref, int status);
struct display_info {
int core;
int thread;
};
struct ap_task {
void *src;
struct iovec *iovs;
uint32_t iov_cnt;
void *dst;
void *dst2;
struct worker_thread *worker;
@ -84,14 +74,6 @@ struct ap_task {
TAILQ_ENTRY(ap_task) link;
};
struct accel_batch {
int status;
int cmd_count;
struct spdk_accel_batch *batch;
struct worker_thread *worker;
TAILQ_ENTRY(accel_batch) link;
};
struct worker_thread {
struct spdk_io_channel *ch;
uint64_t xfer_completed;
@ -106,11 +88,6 @@ struct worker_thread {
struct spdk_poller *is_draining_poller;
struct spdk_poller *stop_poller;
void *task_base;
struct accel_batch *batch_base;
struct display_info display;
TAILQ_HEAD(, accel_batch) in_prep_batches;
TAILQ_HEAD(, accel_batch) in_use_batches;
TAILQ_HEAD(, accel_batch) to_submit_batches;
};
static void
@ -122,7 +99,6 @@ dump_user_config(struct spdk_app_opts *opts)
printf("Workload Type: %s\n", g_workload_type);
if (g_workload_selection == ACCEL_CRC32C) {
printf("CRC-32C seed: %u\n", g_crc32c_seed);
printf("vector size: %u\n", g_crc32c_chained_count);
} else if (g_workload_selection == ACCEL_FILL) {
printf("Fill pattern: 0x%x\n", g_fill_pattern);
} else if ((g_workload_selection == ACCEL_COMPARE) && g_fail_percent_goal > 0) {
@ -130,13 +106,7 @@ dump_user_config(struct spdk_app_opts *opts)
}
printf("Transfer size: %u bytes\n", g_xfer_size_bytes);
printf("Queue depth: %u\n", g_queue_depth);
printf("# threads/core: %u\n", g_threads_per_core);
printf("Run time: %u seconds\n", g_time_in_sec);
if (g_ops_per_batch > 0) {
printf("Batching: %u operations\n", g_ops_per_batch);
} else {
printf("Batching: Disabled\n");
}
printf("Verify: %s\n\n", g_verify ? "Yes" : "No");
}
@ -145,9 +115,7 @@ usage(void)
{
printf("accel_perf options:\n");
printf("\t[-h help message]\n");
printf("\t[-q queue depth per core]\n");
printf("\t[-C for crc32c workload, use this value to configre the io vector size to test (default 1)\n");
printf("\t[-T number of threads per core\n");
printf("\t[-q queue depth]\n");
printf("\t[-n number of channels]\n");
printf("\t[-o transfer size in bytes]\n");
printf("\t[-t time in seconds]\n");
@ -156,25 +124,15 @@ usage(void)
printf("\t[-P for compare workload, percentage of operations that should miscompare (percent, default 0)\n");
printf("\t[-f for fill workload, use this BYTE value (default 255)\n");
printf("\t[-y verify result if this switch is on]\n");
printf("\t[-b batch this number of operations at a time (default 0 = disabled)]\n");
}
static int
parse_args(int argc, char *argv)
{
switch (argc) {
case 'b':
g_ops_per_batch = spdk_strtol(optarg, 10);
break;
case 'C':
g_crc32c_chained_count = spdk_strtol(optarg, 10);
break;
case 'f':
g_fill_pattern = (uint8_t)spdk_strtol(optarg, 10);
break;
case 'T':
g_threads_per_core = spdk_strtol(optarg, 10);
break;
case 'o':
g_xfer_size_bytes = spdk_strtol(optarg, 10);
break;
@ -211,24 +169,20 @@ parse_args(int argc, char *argv)
usage();
return 1;
}
return 0;
}
static int dump_result(void);
static void
unregister_worker(void *arg1)
{
struct worker_thread *worker = arg1;
free(worker->task_base);
free(worker->batch_base);
spdk_put_io_channel(worker->ch);
pthread_mutex_lock(&g_workers_lock);
assert(g_num_workers >= 1);
if (--g_num_workers == 0) {
pthread_mutex_unlock(&g_workers_lock);
g_rc = dump_result();
spdk_app_stop(0);
}
pthread_mutex_unlock(&g_workers_lock);
@ -238,7 +192,6 @@ static int
_get_task_data_bufs(struct ap_task *task)
{
uint32_t align = 0;
uint32_t i = 0;
/* For dualcast, the DSA HW requires 4K alignment on destination addresses but
* we do this for all engines to keep it simple.
@ -247,38 +200,12 @@ _get_task_data_bufs(struct ap_task *task)
align = ALIGN_4K;
}
if (g_workload_selection == ACCEL_CRC32C) {
assert(g_crc32c_chained_count > 0);
task->iov_cnt = g_crc32c_chained_count;
task->iovs = calloc(task->iov_cnt, sizeof(struct iovec));
if (!task->iovs) {
fprintf(stderr, "cannot allocated task->iovs fot task=%p\n", task);
return -ENOMEM;
}
for (i = 0; i < task->iov_cnt; i++) {
task->iovs[i].iov_base = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL);
if (task->iovs[i].iov_base == NULL) {
return -ENOMEM;
}
memset(task->iovs[i].iov_base, DATA_PATTERN, g_xfer_size_bytes);
task->iovs[i].iov_len = g_xfer_size_bytes;
}
} else {
task->src = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL);
if (task->src == NULL) {
fprintf(stderr, "Unable to alloc src buffer\n");
return -ENOMEM;
}
/* For fill, set the entire src buffer so we can check if verify is enabled. */
if (g_workload_selection == ACCEL_FILL) {
memset(task->src, g_fill_pattern, g_xfer_size_bytes);
} else {
memset(task->src, DATA_PATTERN, g_xfer_size_bytes);
}
task->src = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL);
if (task->src == NULL) {
fprintf(stderr, "Unable to alloc src buffer\n");
return -ENOMEM;
}
memset(task->src, DATA_PATTERN, g_xfer_size_bytes);
task->dst = spdk_dma_zmalloc(g_xfer_size_bytes, align, NULL);
if (task->dst == NULL) {
@ -293,6 +220,11 @@ _get_task_data_bufs(struct ap_task *task)
memset(task->dst, ~DATA_PATTERN, g_xfer_size_bytes);
}
/* For fill, set the entire src buffer so we can check if verify is enabled. */
if (g_workload_selection == ACCEL_FILL) {
memset(task->src, g_fill_pattern, g_xfer_size_bytes);
}
if (g_workload_selection == ACCEL_DUALCAST) {
task->dst2 = spdk_dma_zmalloc(g_xfer_size_bytes, align, NULL);
if (task->dst2 == NULL) {
@ -323,7 +255,8 @@ _get_task(struct worker_thread *worker)
return task;
}
/* Submit one operation using the same ap task that just completed. */
static void accel_done(void *ref, int status);
static void
_submit_single(struct worker_thread *worker, struct ap_task *task)
{
@ -343,9 +276,9 @@ _submit_single(struct worker_thread *worker, struct ap_task *task)
g_xfer_size_bytes, accel_done, task);
break;
case ACCEL_CRC32C:
rc = spdk_accel_submit_crc32cv(worker->ch, (uint32_t *)task->dst,
task->iovs, task->iov_cnt, g_crc32c_seed,
accel_done, task);
rc = spdk_accel_submit_crc32c(worker->ch, (uint32_t *)task->dst,
task->src, g_crc32c_seed,
g_xfer_size_bytes, accel_done, task);
break;
case ACCEL_COMPARE:
random_num = rand() % 100;
@ -375,15 +308,10 @@ _submit_single(struct worker_thread *worker, struct ap_task *task)
}
static int
_batch_prep_cmd(struct worker_thread *worker, struct ap_task *task,
struct accel_batch *worker_batch)
_batch_prep_cmd(struct worker_thread *worker, struct ap_task *task, struct spdk_accel_batch *batch)
{
struct spdk_accel_batch *batch = worker_batch->batch;
int rc = 0;
worker_batch->cmd_count++;
assert(worker_batch->cmd_count <= g_ops_per_batch);
switch (g_workload_selection) {
case ACCEL_COPY:
rc = spdk_accel_batch_prep_copy(worker->ch, batch, task->dst,
@ -403,8 +331,8 @@ _batch_prep_cmd(struct worker_thread *worker, struct ap_task *task,
g_xfer_size_bytes, accel_done, task);
break;
case ACCEL_CRC32C:
rc = spdk_accel_batch_prep_crc32cv(worker->ch, batch, (uint32_t *)task->dst,
task->iovs, task->iov_cnt, g_crc32c_seed, accel_done, task);
rc = spdk_accel_batch_prep_crc32c(worker->ch, batch, (uint32_t *)task->dst,
task->src, g_crc32c_seed, g_xfer_size_bytes, accel_done, task);
break;
default:
assert(false);
@ -415,162 +343,23 @@ _batch_prep_cmd(struct worker_thread *worker, struct ap_task *task,
}
static void
_free_task_buffers(struct ap_task *task)
_free_task(struct ap_task *task)
{
uint32_t i;
if (g_workload_selection == ACCEL_CRC32C) {
if (task->iovs) {
for (i = 0; i < task->iov_cnt; i++) {
if (task->iovs[i].iov_base) {
spdk_dma_free(task->iovs[i].iov_base);
}
}
free(task->iovs);
}
} else {
spdk_dma_free(task->src);
}
spdk_dma_free(task->src);
spdk_dma_free(task->dst);
if (g_workload_selection == ACCEL_DUALCAST) {
spdk_dma_free(task->dst2);
}
}
static void _batch_done(void *cb_arg);
static void
_build_batch(struct worker_thread *worker, struct ap_task *task)
{
struct accel_batch *worker_batch = NULL;
int rc;
assert(!TAILQ_EMPTY(&worker->in_prep_batches));
worker_batch = TAILQ_FIRST(&worker->in_prep_batches);
/* If an accel batch hasn't been created yet do so now. */
if (worker_batch->batch == NULL) {
worker_batch->batch = spdk_accel_batch_create(worker->ch);
if (worker_batch->batch == NULL) {
fprintf(stderr, "error unable to create new batch\n");
return;
}
}
/* Prep the command re-using the last completed command's task */
rc = _batch_prep_cmd(worker, task, worker_batch);
if (rc) {
fprintf(stderr, "error preping command for batch\n");
goto error;
}
/* If this batch is full move it to the to_submit list so it gets
* submitted as batches complete.
*/
if (worker_batch->cmd_count == g_ops_per_batch) {
TAILQ_REMOVE(&worker->in_prep_batches, worker_batch, link);
TAILQ_INSERT_TAIL(&worker->to_submit_batches, worker_batch, link);
}
return;
error:
spdk_accel_batch_cancel(worker->ch, worker_batch->batch);
}
static void batch_done(void *cb_arg, int status);
static void
_drain_batch(struct worker_thread *worker)
{
struct accel_batch *worker_batch, *tmp;
int rc;
/* submit any batches that were being built up. */
TAILQ_FOREACH_SAFE(worker_batch, &worker->in_prep_batches, link, tmp) {
if (worker_batch->cmd_count == 0) {
continue;
}
worker->current_queue_depth += worker_batch->cmd_count + 1;
TAILQ_REMOVE(&worker->in_prep_batches, worker_batch, link);
TAILQ_INSERT_TAIL(&worker->in_use_batches, worker_batch, link);
rc = spdk_accel_batch_submit(worker->ch, worker_batch->batch, batch_done, worker_batch);
if (rc == 0) {
worker_batch->cmd_count = 0;
} else {
fprintf(stderr, "error sending final batch\n");
worker->current_queue_depth -= worker_batch->cmd_count + 1;
break;
}
}
}
static void
_batch_done(void *cb_arg)
{
struct accel_batch *worker_batch = (struct accel_batch *)cb_arg;
struct worker_thread *worker = worker_batch->worker;
int rc;
assert(TAILQ_EMPTY(&worker->in_use_batches) == 0);
if (worker_batch->status) {
SPDK_ERRLOG("error %d\n", worker_batch->status);
}
worker->current_queue_depth--;
TAILQ_REMOVE(&worker->in_use_batches, worker_batch, link);
TAILQ_INSERT_TAIL(&worker->in_prep_batches, worker_batch, link);
worker_batch->batch = NULL;
worker_batch->cmd_count = 0;
if (!worker->is_draining) {
worker_batch = TAILQ_FIRST(&worker->to_submit_batches);
if (worker_batch != NULL) {
assert(worker_batch->cmd_count == g_ops_per_batch);
/* Add one for the batch command itself. */
worker->current_queue_depth += g_ops_per_batch + 1;
TAILQ_REMOVE(&worker->to_submit_batches, worker_batch, link);
TAILQ_INSERT_TAIL(&worker->in_use_batches, worker_batch, link);
rc = spdk_accel_batch_submit(worker->ch, worker_batch->batch, batch_done, worker_batch);
if (rc) {
fprintf(stderr, "error ending batch\n");
worker->current_queue_depth -= g_ops_per_batch + 1;
return;
}
}
} else {
_drain_batch(worker);
}
}
static void
batch_done(void *cb_arg, int status)
{
struct accel_batch *worker_batch = (struct accel_batch *)cb_arg;
struct ap_task *task = (struct ap_task *)cb_arg;
struct worker_thread *worker = task->worker;
assert(worker_batch->worker);
worker_batch->status = status;
spdk_thread_send_msg(worker_batch->worker->thread, _batch_done, worker_batch);
}
static uint32_t
_update_crc32c_iov(struct iovec *iov, int iovcnt, uint32_t crc32c)
{
int i;
for (i = 0; i < iovcnt; i++) {
assert(iov[i].iov_base != NULL);
assert(iov[i].iov_len != 0);
crc32c = spdk_crc32c_update(iov[i].iov_base, iov[i].iov_len, crc32c);
}
return crc32c;
worker->current_queue_depth--;
TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link);
}
static void
@ -586,7 +375,8 @@ _accel_done(void *arg1)
if (g_verify && task->status == 0) {
switch (g_workload_selection) {
case ACCEL_CRC32C:
sw_crc32c = _update_crc32c_iov(task->iovs, task->iov_cnt, ~g_crc32c_seed);
/* calculate sw CRC-32C and compare to sw aceel result. */
sw_crc32c = spdk_crc32c_update(task->src, g_xfer_size_bytes, ~g_crc32c_seed);
if (*(uint32_t *)task->dst != sw_crc32c) {
SPDK_NOTICELOG("CRC-32C miscompare\n");
worker->xfer_failed++;
@ -626,7 +416,7 @@ _accel_done(void *arg1)
assert(task->status != 0);
worker->injected_miscompares++;
} else if (task->status) {
/* Expected to pass but the accel engine reported an error (ex: COMPARE operation). */
/* Expected to pass but API reported error. */
worker->xfer_failed++;
}
@ -634,16 +424,8 @@ _accel_done(void *arg1)
worker->current_queue_depth--;
if (!worker->is_draining) {
if (g_ops_per_batch == 0) {
_submit_single(worker, task);
worker->current_queue_depth++;
} else {
_build_batch(worker, task);
}
} else if (g_ops_per_batch > 0) {
_drain_batch(worker);
} else {
TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link);
_submit_single(worker, task);
worker->current_queue_depth++;
}
}
@ -656,8 +438,8 @@ dump_result(void)
uint64_t total_xfer_per_sec, total_bw_in_MiBps;
struct worker_thread *worker = g_workers;
printf("\nCore,Thread Transfers Bandwidth Failed Miscompares\n");
printf("------------------------------------------------------------------------\n");
printf("\nCore Transfers Bandwidth Failed Miscompares\n");
printf("-----------------------------------------------------------------\n");
while (worker != NULL) {
uint64_t xfer_per_sec = worker->xfer_completed / g_time_in_sec;
@ -669,8 +451,8 @@ dump_result(void)
total_miscompared += worker->injected_miscompares;
if (xfer_per_sec) {
printf("%u,%u%17" PRIu64 "/s%9" PRIu64 " MiB/s%7" PRIu64 " %11" PRIu64 "\n",
worker->display.core, worker->display.thread, xfer_per_sec,
printf("%10d%12" PRIu64 "/s%8" PRIu64 " MiB/s%11" PRIu64 " %11" PRIu64 "\n",
worker->core, xfer_per_sec,
bw_in_MiBps, worker->xfer_failed, worker->injected_miscompares);
}
@ -681,34 +463,26 @@ dump_result(void)
total_bw_in_MiBps = (total_completed * g_xfer_size_bytes) /
(g_time_in_sec * 1024 * 1024);
printf("=========================================================================\n");
printf("Total:%15" PRIu64 "/s%9" PRIu64 " MiB/s%6" PRIu64 " %11" PRIu64"\n\n",
printf("==================================================================\n");
printf("Total:%16" PRIu64 "/s%8" PRIu64 " MiB/s%11" PRIu64 " %11" PRIu64"\n\n",
total_xfer_per_sec, total_bw_in_MiBps, total_failed, total_miscompared);
return total_failed ? 1 : 0;
}
static inline void
_free_task_buffers_in_pool(struct worker_thread *worker)
{
struct ap_task *task;
assert(worker);
while ((task = TAILQ_FIRST(&worker->tasks_pool))) {
TAILQ_REMOVE(&worker->tasks_pool, task, link);
_free_task_buffers(task);
}
}
static int
_check_draining(void *arg)
{
struct worker_thread *worker = arg;
struct ap_task *task;
assert(worker);
if (worker->current_queue_depth == 0) {
_free_task_buffers_in_pool(worker);
while ((task = TAILQ_FIRST(&worker->tasks_pool))) {
TAILQ_REMOVE(&worker->tasks_pool, task, link);
_free_task(task);
}
spdk_poller_unregister(&worker->is_draining_poller);
unregister_worker(worker);
}
@ -732,83 +506,36 @@ _worker_stop(void *arg)
return 0;
}
static void
_init_thread_done(void *ctx)
{
}
static void
_init_thread(void *arg1)
{
struct worker_thread *worker;
struct ap_task *task;
int i, rc, num_batches;
int max_per_batch;
int i, rc, max_per_batch, batch_count, num_tasks;
int remaining = g_queue_depth;
int num_tasks = g_queue_depth;
struct accel_batch *tmp;
struct accel_batch *worker_batch = NULL;
struct display_info *display = arg1;
struct spdk_accel_batch *batch, *new_batch;
worker = calloc(1, sizeof(*worker));
if (worker == NULL) {
fprintf(stderr, "Unable to allocate worker\n");
free(display);
return;
}
worker->display.core = display->core;
worker->display.thread = display->thread;
free(display);
worker->core = spdk_env_get_current_core();
worker->thread = spdk_get_thread();
pthread_mutex_lock(&g_workers_lock);
g_num_workers++;
worker->next = g_workers;
g_workers = worker;
pthread_mutex_unlock(&g_workers_lock);
worker->ch = spdk_accel_engine_get_io_channel();
max_per_batch = spdk_accel_batch_get_max(worker->ch);
assert(max_per_batch > 0);
num_tasks = g_queue_depth + spdk_divide_round_up(g_queue_depth, max_per_batch);
TAILQ_INIT(&worker->tasks_pool);
if (g_ops_per_batch > 0) {
max_per_batch = spdk_accel_batch_get_max(worker->ch);
assert(max_per_batch > 0);
if (g_ops_per_batch > max_per_batch) {
fprintf(stderr, "Reducing requested batch amount to max supported of %d\n", max_per_batch);
g_ops_per_batch = max_per_batch;
}
if (g_ops_per_batch > g_queue_depth) {
fprintf(stderr, "Batch amount > queue depth, resetting to %d\n", g_queue_depth);
g_ops_per_batch = g_queue_depth;
}
TAILQ_INIT(&worker->in_prep_batches);
TAILQ_INIT(&worker->to_submit_batches);
TAILQ_INIT(&worker->in_use_batches);
/* A worker_batch will live on one of 3 lists:
* IN_PREP: as individual IOs complete new ones are built on on a
* worker_batch on this list until it reaches g_ops_per_batch.
* TO_SUBMIT: as batches are built up on IO completion they are moved
* to this list once they are full. This list is used in
* batch completion to start new batches.
* IN_USE: the worker_batch is outstanding and will be moved to in prep
* list when the batch is completed.
*
* So we need enough to cover Q depth loading and then one to replace
* each one of those and for when everything is outstanding there needs
* to be one extra batch to build up while the last batch is completing
* IO but before it's completed the batch command.
*/
num_batches = (g_queue_depth / g_ops_per_batch * 2) + 1;
worker->batch_base = calloc(num_batches, sizeof(struct accel_batch));
worker_batch = worker->batch_base;
for (i = 0; i < num_batches; i++) {
worker_batch->worker = worker;
TAILQ_INSERT_TAIL(&worker->in_prep_batches, worker_batch, link);
worker_batch++;
}
}
worker->task_base = calloc(num_tasks, sizeof(struct ap_task));
if (worker->task_base == NULL) {
fprintf(stderr, "Could not allocate task base.\n");
@ -829,53 +556,66 @@ _init_thread(void *arg1)
worker->stop_poller = SPDK_POLLER_REGISTER(_worker_stop, worker,
g_time_in_sec * 1000000ULL);
/* If batching is enabled load up to the full Q depth before
* processing any completions, then ping pong between two batches,
* one processing and one being built up for when the other completes.
*/
if (g_ops_per_batch > 0) {
do {
worker_batch = TAILQ_FIRST(&worker->in_prep_batches);
if (worker_batch == NULL) {
goto error;
}
g_workers = worker;
pthread_mutex_lock(&g_workers_lock);
g_num_workers++;
pthread_mutex_unlock(&g_workers_lock);
worker_batch->batch = spdk_accel_batch_create(worker->ch);
if (worker_batch->batch == NULL) {
raise(SIGINT);
/* Batching is only possible if there is at least 2 operations. */
if (g_queue_depth > 1) {
/* Outter loop sets up each batch command, inner loop populates the
* batch descriptors.
*/
do {
new_batch = spdk_accel_batch_create(worker->ch);
if (new_batch == NULL) {
break;
}
for (i = 0; i < g_ops_per_batch; i++) {
batch = new_batch;
batch_count = 0;
do {
task = _get_task(worker);
if (task == NULL) {
goto error;
}
rc = _batch_prep_cmd(worker, task, worker_batch);
rc = _batch_prep_cmd(worker, task, batch);
if (rc) {
fprintf(stderr, "error preping command\n");
goto error;
}
}
remaining--;
batch_count++;
} while (batch_count < max_per_batch && remaining > 0);
/* for the batch operation itself. */
task->worker->current_queue_depth++;
TAILQ_REMOVE(&worker->in_prep_batches, worker_batch, link);
TAILQ_INSERT_TAIL(&worker->in_use_batches, worker_batch, link);
rc = spdk_accel_batch_submit(worker->ch, worker_batch->batch, batch_done, worker_batch);
if (rc) {
fprintf(stderr, "error ending batch\n");
/* Now send the batch command. */
task = _get_task(worker);
if (task == NULL) {
goto error;
}
assert(remaining >= g_ops_per_batch);
remaining -= g_ops_per_batch;
} while (remaining > 0);
rc = spdk_accel_batch_submit(worker->ch, batch, batch_done, task);
if (rc) {
fprintf(stderr, "error ending batch %d\n", rc);
goto error;
}
/* We can't build a batch unless it has 2 descriptors (per spec). */
} while (remaining > 1);
/* If there are no more left, we're done. */
if (remaining == 0) {
return;
}
}
/* Submit as singles when no batching is enabled or we ran out of batches. */
/* For engines that don't support batch or for the odd event that
* a batch ends with only one descriptor left.
*/
for (i = 0; i < remaining; i++) {
task = _get_task(worker);
if (task == NULL) {
goto error;
@ -885,15 +625,10 @@ _init_thread(void *arg1)
}
return;
error:
if (worker_batch && worker_batch->batch) {
TAILQ_FOREACH_SAFE(worker_batch, &worker->in_use_batches, link, tmp) {
spdk_accel_batch_cancel(worker->ch, worker_batch->batch);
TAILQ_REMOVE(&worker->in_use_batches, worker_batch, link);
}
while ((task = TAILQ_FIRST(&worker->tasks_pool))) {
TAILQ_REMOVE(&worker->tasks_pool, task, link);
_free_task(task);
}
_free_task_buffers_in_pool(worker);
free(worker->batch_base);
free(worker->task_base);
free(worker);
spdk_app_stop(-1);
@ -915,12 +650,6 @@ static void
accel_perf_start(void *arg1)
{
struct spdk_io_channel *accel_ch;
struct spdk_cpuset tmp_cpumask = {};
char thread_name[32];
uint32_t i;
int j;
struct spdk_thread *thread;
struct display_info *display;
accel_ch = spdk_accel_engine_get_io_channel();
g_capabilites = spdk_accel_get_capabilities(accel_ch);
@ -932,29 +661,13 @@ accel_perf_start(void *arg1)
}
g_tsc_rate = spdk_get_ticks_hz();
g_tsc_us_rate = g_tsc_rate / (1000 * 1000);
g_tsc_end = spdk_get_ticks() + g_time_in_sec * g_tsc_rate;
printf("Running for %d seconds...\n", g_time_in_sec);
fflush(stdout);
/* Create worker threads for each core that was specified. */
SPDK_ENV_FOREACH_CORE(i) {
for (j = 0; j < g_threads_per_core; j++) {
snprintf(thread_name, sizeof(thread_name), "ap_worker_%u_%u", i, j);
spdk_cpuset_zero(&tmp_cpumask);
spdk_cpuset_set_cpu(&tmp_cpumask, i, true);
thread = spdk_thread_create(thread_name, &tmp_cpumask);
display = calloc(1, sizeof(*display));
if (display == NULL) {
fprintf(stderr, "Unable to allocate memory\n");
spdk_app_stop(-1);
return;
}
display->core = i;
display->thread = j;
spdk_thread_send_msg(thread, _init_thread, display);
}
}
spdk_for_each_thread(_init_thread, NULL, _init_thread_done);
}
int
@ -962,13 +675,14 @@ main(int argc, char **argv)
{
struct spdk_app_opts opts = {};
struct worker_thread *worker, *tmp;
int rc = 0;
pthread_mutex_init(&g_workers_lock, NULL);
spdk_app_opts_init(&opts, sizeof(opts));
opts.reactor_mask = "0x1";
if (spdk_app_parse_args(argc, argv, &opts, "C:o:q:t:yw:P:f:b:T:", NULL, parse_args,
if (spdk_app_parse_args(argc, argv, &opts, "o:q:t:yw:P:f:", NULL, parse_args,
usage) != SPDK_APP_PARSE_ARGS_SUCCESS) {
g_rc = -1;
rc = -1;
goto cleanup;
}
@ -978,28 +692,16 @@ main(int argc, char **argv)
(g_workload_selection != ACCEL_COMPARE) &&
(g_workload_selection != ACCEL_DUALCAST)) {
usage();
g_rc = -1;
goto cleanup;
}
if (g_ops_per_batch > 0 && (g_queue_depth % g_ops_per_batch > 0)) {
fprintf(stdout, "batch size must be a multiple of queue depth\n");
usage();
g_rc = -1;
goto cleanup;
}
if (g_workload_selection == ACCEL_CRC32C &&
g_crc32c_chained_count == 0) {
usage();
g_rc = -1;
rc = -1;
goto cleanup;
}
dump_user_config(&opts);
g_rc = spdk_app_start(&opts, accel_perf_start, NULL);
if (g_rc) {
rc = spdk_app_start(&opts, accel_perf_start, NULL);
if (rc) {
SPDK_ERRLOG("ERROR starting application\n");
} else {
dump_result();
}
pthread_mutex_destroy(&g_workers_lock);
@ -1012,5 +714,5 @@ main(int argc, char **argv)
}
cleanup:
spdk_app_fini();
return g_rc;
return rc;
}

View File

@ -59,7 +59,7 @@ struct spdk_fio_options {
char *conf;
char *json_conf;
unsigned mem_mb;
int mem_single_seg;
bool mem_single_seg;
};
struct spdk_fio_request {
@ -789,7 +789,6 @@ static struct fio_option options[] = {
.type = FIO_OPT_BOOL,
.off1 = offsetof(struct spdk_fio_options, mem_single_seg),
.help = "If set to 1, SPDK will use just a single hugetlbfs file",
.def = "0",
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_INVALID,
},

View File

@ -38,7 +38,7 @@
#include "spdk/event.h"
#include "spdk/log.h"
#include "spdk/string.h"
#include "spdk/bdev_zone.h"
#include "spdk/bdev_module.h"
static char *g_bdev_name = "Malloc0";
@ -191,50 +191,6 @@ hello_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
}
static void
reset_zone_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{
struct hello_context_t *hello_context = cb_arg;
/* Complete the I/O */
spdk_bdev_free_io(bdev_io);
if (!success) {
SPDK_ERRLOG("bdev io reset zone error: %d\n", EIO);
spdk_put_io_channel(hello_context->bdev_io_channel);
spdk_bdev_close(hello_context->bdev_desc);
spdk_app_stop(-1);
return;
}
hello_write(hello_context);
}
static void
hello_reset_zone(void *arg)
{
struct hello_context_t *hello_context = arg;
int rc = 0;
rc = spdk_bdev_zone_management(hello_context->bdev_desc, hello_context->bdev_io_channel,
0, SPDK_BDEV_ZONE_RESET, reset_zone_complete, hello_context);
if (rc == -ENOMEM) {
SPDK_NOTICELOG("Queueing io\n");
/* In case we cannot perform I/O now, queue I/O */
hello_context->bdev_io_wait.bdev = hello_context->bdev;
hello_context->bdev_io_wait.cb_fn = hello_reset_zone;
hello_context->bdev_io_wait.cb_arg = hello_context;
spdk_bdev_queue_io_wait(hello_context->bdev, hello_context->bdev_io_channel,
&hello_context->bdev_io_wait);
} else if (rc) {
SPDK_ERRLOG("%s error while resetting zone: %d\n", spdk_strerror(-rc), rc);
spdk_put_io_channel(hello_context->bdev_io_channel);
spdk_bdev_close(hello_context->bdev_desc);
spdk_app_stop(-1);
}
}
/*
* Our initial event that kicks off everything from main().
*/
@ -294,12 +250,6 @@ hello_start(void *arg1)
}
snprintf(hello_context->buff, blk_size, "%s", "Hello World!\n");
if (spdk_bdev_is_zoned(hello_context->bdev)) {
hello_reset_zone(hello_context);
/* If bdev is zoned, the callback, reset_zone_complete, will call hello_write() */
return;
}
hello_write(hello_context);
}

View File

@ -1,15 +0,0 @@
from rpc.client import print_json
def reactor_set_interrupt_mode(args):
params = {'lcore': args.lcore, 'disable_interrupt': args.disable_interrupt}
return args.client.call('reactor_set_interrupt_mode', params)
def spdk_rpc_plugin_initialize(subparsers):
p = subparsers.add_parser('reactor_set_interrupt_mode',
help="""Set reactor to interrupt or back to poll mode.""")
p.add_argument('lcore', type=int, help='lcore of the reactor')
p.add_argument('-d', '--disable-interrupt', dest='disable_interrupt', action='store_true',
help='Set reactor back to poll mode')
p.set_defaults(func=reactor_set_interrupt_mode)

View File

@ -35,70 +35,6 @@
#include "spdk/conf.h"
#include "spdk/event.h"
#include "spdk/vhost.h"
#include "spdk/json.h"
#include "spdk/jsonrpc.h"
#include "spdk/rpc.h"
#include "spdk/env.h"
#include "spdk_internal/event.h"
struct rpc_reactor_set_interrupt_mode {
int32_t lcore;
bool disable_interrupt;
};
static const struct spdk_json_object_decoder rpc_reactor_set_interrupt_mode_decoders[] = {
{"lcore", offsetof(struct rpc_reactor_set_interrupt_mode, lcore), spdk_json_decode_int32},
{"disable_interrupt", offsetof(struct rpc_reactor_set_interrupt_mode, disable_interrupt), spdk_json_decode_bool},
};
static void
rpc_reactor_set_interrupt_mode_cb(void *cb_arg)
{
struct spdk_jsonrpc_request *request = cb_arg;
SPDK_NOTICELOG("complete reactor switch\n");
spdk_jsonrpc_send_bool_response(request, true);
}
static void
rpc_reactor_set_interrupt_mode(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_reactor_set_interrupt_mode req = {};
int rc;
if (spdk_json_decode_object(params, rpc_reactor_set_interrupt_mode_decoders,
SPDK_COUNTOF(rpc_reactor_set_interrupt_mode_decoders),
&req)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"spdk_json_decode_object failed");
return;
}
SPDK_NOTICELOG("RPC Start to %s interrupt mode on reactor %d.\n",
req.disable_interrupt ? "disable" : "enable", req.lcore);
if (req.lcore >= (int64_t)spdk_env_get_first_core() &&
req.lcore <= (int64_t)spdk_env_get_last_core()) {
rc = spdk_reactor_set_interrupt_mode(req.lcore, !req.disable_interrupt,
rpc_reactor_set_interrupt_mode_cb, request);
if (rc) {
goto err;
}
} else {
goto err;
}
return;
err:
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"Invalid parameters");
}
/* private */ SPDK_RPC_REGISTER("reactor_set_interrupt_mode", rpc_reactor_set_interrupt_mode,
SPDK_RPC_RUNTIME)
static void
interrupt_tgt_usage(void)

View File

@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
DIRS-y += hello_world identify perf reconnect nvme_manage arbitration \
hotplug cmb_copy abort pmr_persistence
hotplug cmb_copy abort
DIRS-$(CONFIG_FIO_PLUGIN) += fio_plugin

View File

@ -642,7 +642,7 @@ parse_args(int argc, char **argv)
long int val;
int rc;
while ((op = getopt(argc, argv, "a:c:i:o:q:r:s:t:w:GM:T:")) != -1) {
while ((op = getopt(argc, argv, "a:c:i:o:q:r:s:t:w:M:")) != -1) {
switch (op) {
case 'a':
case 'i':

View File

@ -139,17 +139,6 @@ then you can reset all zones before fio start running its jobs by using the engi
--initial_zone_reset=1
## Zone Append
When running FIO against a Zoned Namespace you need to specify --iodepth=1 to avoid
"Zone Invalid Write: The write to a zone was not at the write pointer." I/O errors.
However, if your controller supports Zone Append, you can use the engine option:
--zone_append=1
To send zone append commands instead of write commands to the controller.
When using zone append, you will be able to specify a --iodepth greater than 1.
## Shared Memory Increase
If your device has a lot of zones, fio can give you errors such as:

View File

@ -9,6 +9,7 @@ ramp_time=0
runtime=2
iodepth=128
rw=randrw
bs=4k
[test]
numjobs=1

View File

@ -93,8 +93,6 @@ struct spdk_fio_options {
char *digest_enable;
int enable_vmd;
int initial_zone_reset;
int zone_append;
int print_qid_mappings;
};
struct spdk_fio_request {
@ -132,7 +130,6 @@ struct spdk_fio_qpair {
struct spdk_nvme_qpair *qpair;
struct spdk_nvme_ns *ns;
uint32_t io_flags;
bool zone_append_enabled;
bool nvme_pi_enabled;
/* True for DIF and false for DIX, and this is valid only if nvme_pi_enabled is true. */
bool extended_lba;
@ -290,35 +287,13 @@ pcu(struct spdk_nvme_qpair *qpair, int *completed)
}
#endif
static inline uint32_t
_nvme_get_host_buffer_sector_size(struct spdk_nvme_ns *ns, uint32_t io_flags)
{
bool md_excluded_from_xfer = false;
uint32_t md_size;
uint32_t ns_flags;
ns_flags = spdk_nvme_ns_get_flags(ns);
md_size = spdk_nvme_ns_get_md_size(ns);
/* For extended LBA format, if the metadata size is 8 bytes and PRACT is
* enabled(controller inserts/strips PI), we should reduce metadata size
* from block size.
*/
md_excluded_from_xfer = ((io_flags & SPDK_NVME_IO_FLAGS_PRACT) &&
(ns_flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) &&
(ns_flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) &&
(md_size == 8));
return md_excluded_from_xfer ? spdk_nvme_ns_get_sector_size(ns) :
spdk_nvme_ns_get_extended_sector_size(ns);
}
static void
attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
{
struct thread_data *td = cb_ctx;
struct spdk_fio_thread *fio_thread = td->io_ops_data;
struct spdk_nvme_io_qpair_opts qpopts;
struct spdk_fio_ctrlr *fio_ctrlr;
struct spdk_fio_qpair *fio_qpair;
struct spdk_nvme_ns *ns;
@ -327,7 +302,6 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
uint32_t ns_id;
char *p;
long int tmp;
uint32_t block_size;
struct spdk_fio_options *fio_options = td->eo;
p = strstr(f->file_name, "ns=");
@ -397,7 +371,20 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
return;
}
f->engine_data = fio_qpair;
spdk_nvme_ctrlr_get_default_io_qpair_opts(fio_ctrlr->ctrlr, &qpopts, sizeof(qpopts));
qpopts.delay_cmd_submit = true;
if (fio_options->enable_wrr) {
qpopts.qprio = fio_options->wrr_priority;
}
fio_qpair->qpair = spdk_nvme_ctrlr_alloc_io_qpair(fio_ctrlr->ctrlr, &qpopts, sizeof(qpopts));
if (!fio_qpair->qpair) {
SPDK_ERRLOG("Cannot allocate nvme io_qpair any more\n");
g_error = true;
free(fio_qpair);
return;
}
fio_qpair->ns = ns;
fio_qpair->f = f;
fio_qpair->fio_ctrlr = fio_ctrlr;
@ -413,57 +400,14 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
fio_qpair->extended_lba ? "extended lba" : "separate metadata");
}
block_size = _nvme_get_host_buffer_sector_size(ns, fio_qpair->io_flags);
if (td->o.bs[DDIR_READ] % block_size != 0 || td->o.bs[DDIR_WRITE] % block_size != 0) {
if (spdk_nvme_ns_supports_extended_lba(ns)) {
SPDK_ERRLOG("--bs has to be a multiple of (LBA data size + Metadata size)\n");
} else {
SPDK_ERRLOG("--bs has to be a multiple of LBA data size\n");
}
if (spdk_nvme_ns_supports_extended_lba(ns) &&
(td->o.bs[DDIR_READ] % spdk_nvme_ns_get_extended_sector_size(ns) != 0 ||
td->o.bs[DDIR_WRITE] % spdk_nvme_ns_get_extended_sector_size(ns) != 0)) {
SPDK_ERRLOG("--bs has to be equal to LBA data size + Metadata size\n");
g_error = true;
return;
}
if (fio_options->zone_append && spdk_nvme_ns_get_csi(ns) == SPDK_NVME_CSI_ZNS) {
if (spdk_nvme_ctrlr_get_flags(ctrlr) & SPDK_NVME_CTRLR_ZONE_APPEND_SUPPORTED) {
fprintf(stdout, "Using zone appends instead of writes on: '%s'\n",
fio_qpair->f->file_name);
fio_qpair->zone_append_enabled = true;
} else {
SPDK_WARNLOG("Falling back to writes on: '%s' - ns lacks zone append cmd\n",
fio_qpair->f->file_name);
}
}
if (fio_options->initial_zone_reset == 1 && spdk_nvme_ns_get_csi(ns) == SPDK_NVME_CSI_ZNS) {
#if FIO_HAS_ZBD
struct spdk_nvme_qpair *tmp_qpair;
int completed = 0, err;
/* qpair has not been allocated yet (it gets allocated in spdk_fio_open()).
* Create a temporary qpair in order to perform the initial zone reset.
*/
assert(!fio_qpair->qpair);
tmp_qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
if (!tmp_qpair) {
SPDK_ERRLOG("Cannot allocate a temporary qpair\n");
g_error = true;
return;
}
err = spdk_nvme_zns_reset_zone(ns, tmp_qpair, 0x0, true, pcu_cb, &completed);
if (err || pcu(tmp_qpair, &completed) || completed < 0) {
log_err("spdk/nvme: warn: initial_zone_reset: err: %d, cpl: %d\n",
err, completed);
}
spdk_nvme_ctrlr_free_io_qpair(tmp_qpair);
#else
log_err("spdk/nvme: ZBD/ZNS is not supported\n");
#endif
}
f->real_file_size = spdk_nvme_ns_get_size(fio_qpair->ns);
if (f->real_file_size <= 0) {
g_error = true;
@ -653,35 +597,39 @@ static int spdk_fio_setup(struct thread_data *td)
g_td_count++;
pthread_mutex_unlock(&g_mutex);
if (fio_options->initial_zone_reset == 1) {
#if FIO_HAS_ZBD
struct spdk_fio_qpair *fio_qpair;
TAILQ_FOREACH(fio_qpair, &fio_thread->fio_qpair, link) {
const struct spdk_nvme_zns_ns_data *zns_data;
int completed = 0, err;
if (!fio_qpair->ns) {
continue;
}
zns_data = spdk_nvme_zns_ns_get_data(fio_qpair->ns);
if (!zns_data) {
continue;
}
err = spdk_nvme_zns_reset_zone(fio_qpair->ns, fio_qpair->qpair, 0x0, true,
pcu_cb, &completed);
if (err || pcu(fio_qpair->qpair, &completed) || completed < 0) {
log_err("spdk/nvme: warn: initial_zone_reset: err: %d, cpl: %d\n",
err, completed);
}
}
#else
log_err("spdk/nvme: ZBD/ZNS is not supported\n");
#endif
}
return rc;
}
static int spdk_fio_open(struct thread_data *td, struct fio_file *f)
{
struct spdk_fio_qpair *fio_qpair = f->engine_data;
struct spdk_fio_ctrlr *fio_ctrlr = fio_qpair->fio_ctrlr;
struct spdk_fio_options *fio_options = td->eo;
struct spdk_nvme_io_qpair_opts qpopts;
spdk_nvme_ctrlr_get_default_io_qpair_opts(fio_ctrlr->ctrlr, &qpopts, sizeof(qpopts));
qpopts.delay_cmd_submit = true;
if (fio_options->enable_wrr) {
qpopts.qprio = fio_options->wrr_priority;
}
fio_qpair->qpair = spdk_nvme_ctrlr_alloc_io_qpair(fio_ctrlr->ctrlr, &qpopts, sizeof(qpopts));
if (!fio_qpair->qpair) {
SPDK_ERRLOG("Cannot allocate nvme io_qpair any more\n");
g_error = true;
free(fio_qpair);
return -1;
}
if (fio_options->print_qid_mappings == 1) {
log_info("job %s: %s qid %d\n", td->o.name, f->file_name,
spdk_nvme_qpair_get_id(fio_qpair->qpair));
}
return 0;
}
@ -740,12 +688,6 @@ static void spdk_fio_io_u_free(struct thread_data *td, struct io_u *io_u)
}
}
static inline uint64_t
fio_offset_to_zslba(unsigned long long offset, struct spdk_nvme_ns *ns)
{
return (offset / spdk_nvme_zns_ns_get_zone_size(ns)) * spdk_nvme_zns_ns_get_zone_size_sectors(ns);
}
static int
fio_extended_lba_setup_pi(struct spdk_fio_qpair *fio_qpair, struct io_u *io_u)
{
@ -915,10 +857,6 @@ static void spdk_fio_completion_cb(void *ctx, const struct spdk_nvme_cpl *cpl)
}
}
if (spdk_nvme_cpl_is_error(cpl)) {
fio_req->io->error = EIO;
}
assert(fio_thread->iocq_count < fio_thread->iocq_size);
fio_thread->iocq[fio_thread->iocq_count++] = fio_req->io;
}
@ -1003,7 +941,16 @@ spdk_fio_queue(struct thread_data *td, struct io_u *io_u)
}
fio_req->fio_qpair = fio_qpair;
block_size = _nvme_get_host_buffer_sector_size(ns, fio_qpair->io_flags);
block_size = spdk_nvme_ns_get_extended_sector_size(ns);
if ((fio_qpair->io_flags & g_spdk_pract_flag) && (spdk_nvme_ns_get_md_size(ns) == 8)) {
/* If metadata size = 8 bytes, PI is stripped (read) or inserted (write), and
* so reduce metadata size from block size. (If metadata size > 8 bytes, PI
* is passed (read) or replaced (write). So block size is not necessary to
* change.)
*/
block_size = spdk_nvme_ns_get_sector_size(ns);
}
lba = io_u->offset / block_size;
lba_count = io_u->xfer_buflen / block_size;
@ -1035,31 +982,15 @@ spdk_fio_queue(struct thread_data *td, struct io_u *io_u)
break;
case DDIR_WRITE:
if (!g_spdk_enable_sgl) {
if (!fio_qpair->zone_append_enabled) {
rc = spdk_nvme_ns_cmd_write_with_md(ns, fio_qpair->qpair, io_u->buf, md_buf, lba,
lba_count,
spdk_fio_completion_cb, fio_req,
fio_qpair->io_flags, dif_ctx->apptag_mask, dif_ctx->app_tag);
} else {
uint64_t zslba = fio_offset_to_zslba(io_u->offset, fio_qpair->ns);
rc = spdk_nvme_zns_zone_append_with_md(ns, fio_qpair->qpair, io_u->buf, md_buf, zslba,
lba_count,
spdk_fio_completion_cb, fio_req,
fio_qpair->io_flags, dif_ctx->apptag_mask, dif_ctx->app_tag);
}
rc = spdk_nvme_ns_cmd_write_with_md(ns, fio_qpair->qpair, io_u->buf, md_buf, lba,
lba_count,
spdk_fio_completion_cb, fio_req,
fio_qpair->io_flags, dif_ctx->apptag_mask, dif_ctx->app_tag);
} else {
if (!fio_qpair->zone_append_enabled) {
rc = spdk_nvme_ns_cmd_writev_with_md(ns, fio_qpair->qpair, lba,
lba_count, spdk_fio_completion_cb, fio_req, fio_qpair->io_flags,
spdk_nvme_io_reset_sgl, spdk_nvme_io_next_sge, md_buf,
dif_ctx->apptag_mask, dif_ctx->app_tag);
} else {
uint64_t zslba = fio_offset_to_zslba(io_u->offset, fio_qpair->ns);
rc = spdk_nvme_zns_zone_appendv_with_md(ns, fio_qpair->qpair, zslba,
lba_count, spdk_fio_completion_cb, fio_req, fio_qpair->io_flags,
spdk_nvme_io_reset_sgl, spdk_nvme_io_next_sge, md_buf,
dif_ctx->apptag_mask, dif_ctx->app_tag);
}
rc = spdk_nvme_ns_cmd_writev_with_md(ns, fio_qpair->qpair, lba,
lba_count, spdk_fio_completion_cb, fio_req, fio_qpair->io_flags,
spdk_nvme_io_reset_sgl, spdk_nvme_io_next_sge, md_buf,
dif_ctx->apptag_mask, dif_ctx->app_tag);
}
break;
default:
@ -1157,13 +1088,11 @@ spdk_fio_get_zoned_model(struct thread_data *td, struct fio_file *f, enum zbd_zo
struct spdk_fio_qpair *fio_qpair = NULL;
const struct spdk_nvme_zns_ns_data *zns_data = NULL;
*model = ZBD_IGNORE;
if (f->filetype != FIO_TYPE_FILE && \
f->filetype != FIO_TYPE_BLOCK && \
f->filetype != FIO_TYPE_CHAR) {
log_info("spdk/nvme: ignoring filetype: %d\n", f->filetype);
return 0;
log_info("spdk/nvme: unsupported filetype: %d\n", f->filetype);
return -EINVAL;
}
fio_qpair = get_fio_qpair(fio_thread, f);
@ -1227,7 +1156,6 @@ spdk_fio_report_zones(struct thread_data *td, struct fio_file *f, uint64_t offse
struct spdk_fio_qpair *fio_qpair = NULL;
const struct spdk_nvme_zns_ns_data *zns = NULL;
struct spdk_nvme_zns_zone_report *report;
struct spdk_nvme_qpair *tmp_qpair;
uint32_t report_nzones = 0, report_nzones_max, report_nbytes, mdts_nbytes;
uint64_t zsze_nbytes, ns_nzones, lba_nbytes;
int completed = 0, err;
@ -1243,17 +1171,6 @@ spdk_fio_report_zones(struct thread_data *td, struct fio_file *f, uint64_t offse
return -EINVAL;
}
/* qpair has not been allocated yet (it gets allocated in spdk_fio_open()).
* Create a temporary qpair in order to perform report zones.
*/
assert(!fio_qpair->qpair);
tmp_qpair = spdk_nvme_ctrlr_alloc_io_qpair(fio_qpair->fio_ctrlr->ctrlr, NULL, 0);
if (!tmp_qpair) {
log_err("spdk/nvme: cannot allocate a temporary qpair\n");
return -EIO;
}
/** Retrieve device parameters */
mdts_nbytes = spdk_nvme_ns_get_max_io_xfer_size(fio_qpair->ns);
lba_nbytes = spdk_nvme_ns_get_sector_size(fio_qpair->ns);
@ -1264,17 +1181,16 @@ spdk_fio_report_zones(struct thread_data *td, struct fio_file *f, uint64_t offse
report_nzones_max = (mdts_nbytes - sizeof(*report)) / sizeof(report->descs[0]);
report_nzones_max = spdk_min(spdk_min(report_nzones_max, nr_zones), ns_nzones);
report_nbytes = sizeof(report->descs[0]) * report_nzones_max + sizeof(*report);
report = calloc(1, report_nbytes);
report = spdk_dma_zmalloc(report_nbytes, NVME_IO_ALIGN, NULL);
if (!report) {
log_err("spdk/nvme: failed report_zones(): ENOMEM\n");
err = -ENOMEM;
goto exit;
return -ENOMEM;
}
err = spdk_nvme_zns_report_zones(fio_qpair->ns, tmp_qpair, report, report_nbytes,
err = spdk_nvme_zns_report_zones(fio_qpair->ns, fio_qpair->qpair, report, report_nbytes,
offset / lba_nbytes, SPDK_NVME_ZRA_LIST_ALL, true, pcu_cb,
&completed);
if (err || pcu(tmp_qpair, &completed) || completed < 0) {
if (err || pcu(fio_qpair->qpair, &completed) || completed < 0) {
log_err("spdk/nvme: report_zones(): err: %d, cpl: %d\n", err, completed);
err = err ? err : -EIO;
goto exit;
@ -1332,8 +1248,7 @@ spdk_fio_report_zones(struct thread_data *td, struct fio_file *f, uint64_t offse
}
exit:
spdk_nvme_ctrlr_free_io_qpair(tmp_qpair);
free(report);
spdk_dma_free(report);
return err ? err : (int)report_nzones;
}
@ -1628,26 +1543,6 @@ static struct fio_option options[] = {
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_INVALID,
},
{
.name = "zone_append",
.lname = "Use zone append instead of write",
.type = FIO_OPT_INT,
.off1 = offsetof(struct spdk_fio_options, zone_append),
.def = "0",
.help = "Use zone append instead of write (zone_append=1 or zone_append=0)",
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_INVALID,
},
{
.name = "print_qid_mappings",
.lname = "Print job-to-qid mappings",
.type = FIO_OPT_INT,
.off1 = offsetof(struct spdk_fio_options, print_qid_mappings),
.def = "0",
.help = "Print job-to-qid mappings (0=disable, 1=enable)",
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_INVALID,
},
{
.name = NULL,
},

View File

@ -50,7 +50,6 @@
#define MAX_DISCOVERY_LOG_ENTRIES ((uint64_t)1000)
#define NUM_CHUNK_INFO_ENTRIES 8
#define MAX_OCSSD_PU 128
#define MAX_ZONE_DESC_ENTRIES 8
static int outstanding_commands;
@ -86,9 +85,9 @@ static uint64_t g_discovery_page_numrec;
static struct spdk_ocssd_geometry_data geometry_data;
static struct spdk_ocssd_chunk_information_entry *g_ocssd_chunk_info_page;
static struct spdk_ocssd_chunk_information_entry g_ocssd_chunk_info_page[NUM_CHUNK_INFO_ENTRIES ];
static int64_t g_zone_report_limit = 8;
static bool g_zone_report_full = false;
static bool g_hex_dump = false;
@ -109,8 +108,6 @@ static int g_controllers_found = 0;
static bool g_vmd = false;
static bool g_ocssd_verbose = false;
static void
hex_dump(const void *data, size_t size)
{
@ -228,10 +225,7 @@ get_features(struct spdk_nvme_ctrlr *ctrlr)
SPDK_OCSSD_FEAT_MEDIA_FEEDBACK,
};
/* Submit only one GET FEATURES at a time. There is a known issue #1799
* with Google Cloud Platform NVMe SSDs that do not handle overlapped
* GET FEATURES commands correctly.
*/
/* Submit several GET FEATURES commands and wait for them to complete */
outstanding_commands = 0;
for (i = 0; i < SPDK_COUNTOF(features_to_get); i++) {
if (!spdk_nvme_ctrlr_is_ocssd_supported(ctrlr) &&
@ -243,12 +237,11 @@ get_features(struct spdk_nvme_ctrlr *ctrlr)
} else {
printf("get_feature(0x%02X) failed to submit command\n", features_to_get[i]);
}
while (outstanding_commands) {
spdk_nvme_ctrlr_process_admin_completions(ctrlr);
}
}
while (outstanding_commands) {
spdk_nvme_ctrlr_process_admin_completions(ctrlr);
}
}
static int
@ -549,34 +542,15 @@ get_ocssd_chunk_info_log_page(struct spdk_nvme_ns *ns)
{
struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns);
int nsid = spdk_nvme_ns_get_id(ns);
uint32_t num_entry = geometry_data.num_grp * geometry_data.num_pu * geometry_data.num_chk;
uint32_t xfer_size = spdk_nvme_ns_get_max_io_xfer_size(ns);
uint32_t buf_size = 0;
uint64_t buf_offset = 0;
outstanding_commands = 0;
assert(num_entry != 0);
if (!g_ocssd_verbose) {
num_entry = spdk_min(num_entry, NUM_CHUNK_INFO_ENTRIES);
}
g_ocssd_chunk_info_page = calloc(num_entry, sizeof(struct spdk_ocssd_chunk_information_entry));
assert(g_ocssd_chunk_info_page != NULL);
buf_size = num_entry * sizeof(struct spdk_ocssd_chunk_information_entry);
while (buf_size > 0) {
xfer_size = spdk_min(buf_size, xfer_size);
if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_OCSSD_LOG_CHUNK_INFO,
nsid, (void *) g_ocssd_chunk_info_page + buf_offset,
xfer_size, buf_offset, get_log_page_completion, NULL) == 0) {
outstanding_commands++;
} else {
printf("get_ocssd_chunk_info_log_page() failed\n");
return -1;
}
buf_size -= xfer_size;
buf_offset += xfer_size;
if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_OCSSD_LOG_CHUNK_INFO,
nsid, &g_ocssd_chunk_info_page, sizeof(g_ocssd_chunk_info_page), 0,
get_log_page_completion, NULL) == 0) {
outstanding_commands++;
} else {
printf("get_ocssd_chunk_info_log_page() failed\n");
return -1;
}
while (outstanding_commands) {
@ -674,16 +648,6 @@ print_ascii_string(const void *buf, size_t size)
}
}
/* Underline a "line" with the given marker, e.g. print_uline("=", printf(...)); */
static void
print_uline(char marker, int line_len)
{
for (int i = 1; i < line_len; ++i) {
putchar(marker);
}
putchar('\n');
}
static void
print_ocssd_chunk_info(struct spdk_ocssd_chunk_information_entry *chk_info, int chk_num)
{
@ -713,45 +677,6 @@ print_ocssd_chunk_info(struct spdk_ocssd_chunk_information_entry *chk_info, int
}
}
static void
print_ocssd_chunk_info_verbose(struct spdk_ocssd_chunk_information_entry *chk_info)
{
uint32_t pu, chk, i;
uint32_t cnt_free, cnt_closed, cnt_open, cnt_offline;
uint32_t max_pu = spdk_min(MAX_OCSSD_PU, (geometry_data.num_grp * geometry_data.num_pu));
char cs_str[MAX_OCSSD_PU + 1], cs;
assert(chk_info != NULL);
printf("OCSSD Chunk Info Verbose\n");
printf("======================\n");
printf("%4s %-*s %3s %3s %3s %3s\n", "band", max_pu, "chunk state", "fr", "cl", "op", "of");
for (chk = 0; chk < geometry_data.num_chk; chk++) {
cnt_free = cnt_closed = cnt_open = cnt_offline = 0;
for (pu = 0; pu < max_pu; pu++) {
i = (pu * geometry_data.num_chk) + chk;
if (chk_info[i].cs.free) {
cnt_free++;
cs = 'f';
} else if (chk_info[i].cs.closed) {
cnt_closed++;
cs = 'c';
} else if (chk_info[i].cs.open) {
cnt_open++;
cs = 'o';
} else if (chk_info[i].cs.offline) {
cnt_offline++;
cs = 'l';
} else {
cs = '.';
}
cs_str[pu] = cs;
}
cs_str[pu] = 0;
printf("%4d %s %3d %3d %3d %3d\n", chk, cs_str, cnt_free, cnt_closed, cnt_open, cnt_offline);
}
}
static void
print_ocssd_geometry(struct spdk_ocssd_geometry_data *geometry_data)
{
@ -802,7 +727,7 @@ get_and_print_zns_zone_report(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *q
{
struct spdk_nvme_zns_zone_report *report_buf;
size_t report_bufsize;
uint64_t zone_size_lba = spdk_nvme_zns_ns_get_zone_size_sectors(ns);
uint64_t zone_size_lba = spdk_nvme_zns_ns_get_zone_size(ns) / spdk_nvme_ns_get_sector_size(ns);
uint64_t total_zones = spdk_nvme_zns_ns_get_num_zones(ns);
uint64_t max_zones_per_buf, zones_to_print, i;
uint64_t handled_zones = 0;
@ -811,16 +736,21 @@ get_and_print_zns_zone_report(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *q
outstanding_commands = 0;
report_bufsize = spdk_nvme_ns_get_max_io_xfer_size(ns);
report_buf = calloc(1, report_bufsize);
report_buf = malloc(report_bufsize);
if (!report_buf) {
printf("Zone report allocation failed!\n");
exit(1);
}
zones_to_print = g_zone_report_limit ? spdk_min(total_zones, (uint64_t)g_zone_report_limit) : \
total_zones;
print_uline('=', printf("NVMe ZNS Zone Report (first %zu of %zu)\n", zones_to_print, total_zones));
if (g_zone_report_full) {
zones_to_print = total_zones;
printf("NVMe ZNS Zone Report\n");
printf("====================\n");
} else {
zones_to_print = spdk_min(total_zones, MAX_ZONE_DESC_ENTRIES);
printf("NVMe ZNS Zone Report Glance\n");
printf("===========================\n");
}
while (handled_zones < zones_to_print) {
memset(report_buf, 0, report_bufsize);
@ -896,24 +826,6 @@ print_zns_ns_data(const struct spdk_nvme_zns_ns_data *nsdata_zns)
printf("\n");
}
static const char *
csi_name(enum spdk_nvme_csi csi)
{
switch (csi) {
case SPDK_NVME_CSI_NVM:
return "NVM";
case SPDK_NVME_CSI_KV:
return "KV";
case SPDK_NVME_CSI_ZNS:
return "ZNS";
default:
if (csi >= 0x30 && csi <= 0x3f) {
return "Vendor specific";
}
return "Unknown";
}
}
static void
print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
{
@ -925,7 +837,6 @@ print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
uint32_t flags;
char uuid_str[SPDK_UUID_STRING_LEN];
uint32_t blocksize;
enum spdk_nvme_dealloc_logical_block_read_value dlfeat_read_value;
cdata = spdk_nvme_ctrlr_get_data(ctrlr);
nsdata = spdk_nvme_ns_get_data(ns);
@ -942,16 +853,13 @@ print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
/* This function is only called for active namespaces. */
assert(spdk_nvme_ns_is_active(ns));
printf("Command Set Identifier: %s (%02Xh)\n",
csi_name(spdk_nvme_ns_get_csi(ns)), spdk_nvme_ns_get_csi(ns));
printf("Deallocate: %s\n",
(flags & SPDK_NVME_NS_DEALLOCATE_SUPPORTED) ? "Supported" : "Not Supported");
printf("Deallocated/Unwritten Error: %s\n",
nsdata->nsfeat.dealloc_or_unwritten_error ? "Supported" : "Not Supported");
dlfeat_read_value = spdk_nvme_ns_get_dealloc_logical_block_read_value(ns);
printf("Deallocated Read Value: %s\n",
dlfeat_read_value == SPDK_NVME_DEALLOC_READ_00 ? "All 0x00" :
dlfeat_read_value == SPDK_NVME_DEALLOC_READ_FF ? "All 0xFF" :
nsdata->dlfeat.bits.read_value == SPDK_NVME_DEALLOC_READ_00 ? "All 0x00" :
nsdata->dlfeat.bits.read_value == SPDK_NVME_DEALLOC_READ_FF ? "All 0xFF" :
"Unknown");
printf("Deallocate in Write Zeroes: %s\n",
nsdata->dlfeat.bits.write_zero_deallocate ? "Supported" : "Not Supported");
@ -1048,11 +956,7 @@ print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
get_ocssd_geometry(ns, &geometry_data);
print_ocssd_geometry(&geometry_data);
get_ocssd_chunk_info_log_page(ns);
if (g_ocssd_verbose) {
print_ocssd_chunk_info_verbose(g_ocssd_chunk_info_page);
} else {
print_ocssd_chunk_info(g_ocssd_chunk_info_page, NUM_CHUNK_INFO_ENTRIES);
}
print_ocssd_chunk_info(g_ocssd_chunk_info_page, NUM_CHUNK_INFO_ENTRIES);
} else if (spdk_nvme_ns_get_csi(ns) == SPDK_NVME_CSI_ZNS) {
struct spdk_nvme_qpair *qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
if (qpair == NULL) {
@ -1170,7 +1074,6 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
union spdk_nvme_cap_register cap;
union spdk_nvme_vs_register vs;
union spdk_nvme_cmbsz_register cmbsz;
union spdk_nvme_pmrcap_register pmrcap;
uint8_t str[512];
uint32_t i, j;
struct spdk_nvme_error_information_entry *error_entry;
@ -1178,14 +1081,11 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
struct spdk_pci_device *pci_dev;
struct spdk_pci_id pci_id;
uint32_t nsid;
uint64_t pmrsz;
struct spdk_nvme_ana_group_descriptor *desc;
cap = spdk_nvme_ctrlr_get_regs_cap(ctrlr);
vs = spdk_nvme_ctrlr_get_regs_vs(ctrlr);
cmbsz = spdk_nvme_ctrlr_get_regs_cmbsz(ctrlr);
pmrcap = spdk_nvme_ctrlr_get_regs_pmrcap(ctrlr);
pmrsz = spdk_nvme_ctrlr_get_pmrsz(ctrlr);
if (!spdk_nvme_ctrlr_is_discovery(ctrlr)) {
/*
@ -1298,9 +1198,6 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
(uint64_t)1 << (12 + cap.bits.mpsmin));
printf("Memory Page Size Maximum: %" PRIu64 " bytes\n",
(uint64_t)1 << (12 + cap.bits.mpsmax));
printf("Persistent Memory Region: %s\n",
cap.bits.pmrs ? "Supported" : "Not Supported");
printf("Optional Asynchronous Events Supported\n");
printf(" Namespace Attribute Notices: %s\n",
cdata->oaes.ns_attribute_notices ? "Supported" : "Not Supported");
@ -1336,20 +1233,6 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
}
printf("\n");
printf("Persistent Memory Region Support\n");
printf("================================\n");
if (cap.bits.pmrs != 0) {
printf("Supported: Yes\n");
printf("Total Size: %" PRIu64 " bytes\n", pmrsz);
printf("Read data and metadata in PMR %s\n",
pmrcap.bits.rds ? "Supported" : "Not Supported");
printf("Write data and metadata in PMR: %s\n",
pmrcap.bits.wds ? "Supported" : "Not Supported");
} else {
printf("Supported: No\n");
}
printf("\n");
printf("Admin Command Set Attributes\n");
printf("============================\n");
printf("Security Send/Receive: %s\n",
@ -2050,7 +1933,8 @@ usage(const char *program_name)
printf(" -d DPDK huge memory size in MB\n");
printf(" -g use single file descriptor for DPDK memory segments\n");
printf(" -x print hex dump of raw data\n");
printf(" -z For NVMe Zoned Namespaces, dump the full zone report (-z) or the first N entries (-z N)\n");
printf(" -z For NVMe Zoned Namespaces, dump the full zone report\n");
printf(" -v verbose (enable warnings)\n");
printf(" -V enumerate VMD\n");
printf(" -H show this usage\n");
}
@ -2064,7 +1948,7 @@ parse_args(int argc, char **argv)
spdk_nvme_trid_populate_transport(&g_trid, SPDK_NVME_TRANSPORT_PCIE);
snprintf(g_trid.subnqn, sizeof(g_trid.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
while ((op = getopt(argc, argv, "d:gi:op:r:xz::HL:V")) != -1) {
while ((op = getopt(argc, argv, "d:gi:p:r:xzHL:V")) != -1) {
switch (op) {
case 'd':
g_dpdk_mem = spdk_strtol(optarg, 10);
@ -2083,9 +1967,6 @@ parse_args(int argc, char **argv)
return g_shm_id;
}
break;
case 'o':
g_ocssd_verbose = true;
break;
case 'p':
g_main_core = spdk_strtol(optarg, 10);
if (g_main_core < 0) {
@ -2100,7 +1981,6 @@ parse_args(int argc, char **argv)
return 1;
}
assert(optarg != NULL);
hostnqn = strcasestr(optarg, "hostnqn:");
if (hostnqn) {
size_t len;
@ -2121,18 +2001,7 @@ parse_args(int argc, char **argv)
g_hex_dump = true;
break;
case 'z':
if (optarg == NULL && argv[optind] != NULL && argv[optind][0] != '-') {
g_zone_report_limit = spdk_strtol(argv[optind], 10);
++optind;
} else if (optarg) {
g_zone_report_limit = spdk_strtol(optarg, 10);
} else {
g_zone_report_limit = 0;
}
if (g_zone_report_limit < 0) {
fprintf(stderr, "Invalid Zone Report limit\n");
return g_zone_report_limit;
}
g_zone_report_full = true;
break;
case 'L':
rc = spdk_log_set_flag(optarg);

View File

@ -136,11 +136,6 @@ struct ns_worker_stats {
uint64_t total_tsc;
uint64_t min_tsc;
uint64_t max_tsc;
uint64_t last_tsc;
uint64_t busy_tsc;
uint64_t idle_tsc;
uint64_t last_busy_tsc;
uint64_t last_idle_tsc;
};
struct ns_worker_ctx {
@ -208,14 +203,13 @@ struct ns_fn_table {
int (*submit_io)(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
struct ns_entry *entry, uint64_t offset_in_ios);
int64_t (*check_io)(struct ns_worker_ctx *ns_ctx);
void (*check_io)(struct ns_worker_ctx *ns_ctx);
void (*verify_io)(struct perf_task *task, struct ns_entry *entry);
int (*init_ns_worker_ctx)(struct ns_worker_ctx *ns_ctx);
void (*cleanup_ns_worker_ctx)(struct ns_worker_ctx *ns_ctx);
void (*dump_transport_stats)(uint32_t lcore, struct ns_worker_ctx *ns_ctx);
};
static uint32_t g_io_unit_size = (UINT32_MAX & (~0x03));
@ -237,8 +231,6 @@ static pthread_barrier_t g_worker_sync_barrier;
static uint64_t g_tsc_rate;
static bool g_monitor_perf_cores = false;
static uint32_t g_io_align = 0x200;
static bool g_io_align_specified;
static uint32_t g_io_size_bytes;
@ -252,11 +244,14 @@ static int g_queue_depth;
static int g_nr_io_queues_per_ns = 1;
static int g_nr_unused_io_queues;
static int g_time_in_sec;
static uint64_t g_elapsed_time_in_usec;
static int g_warmup_time_in_sec;
static uint32_t g_max_completions;
static int g_dpdk_mem;
static bool g_dpdk_mem_single_seg = false;
static int g_shm_id = -1;
static uint32_t g_disable_sq_cmb;
static bool g_use_uring;
static bool g_no_pci;
static bool g_warn;
static bool g_header_digest;
static bool g_data_digest;
@ -290,11 +285,11 @@ static uint32_t g_quiet_count = 1;
__count++; \
}
static bool g_dump_transport_stats;
static pthread_mutex_t g_stats_mutex;
static const char *g_core_mask;
#define MAX_ALLOWED_PCI_DEVICE_NUM 128
static struct spdk_pci_addr g_allowed_pci_addr[MAX_ALLOWED_PCI_DEVICE_NUM];
static uint32_t g_allowed_pci_addr_num;
struct trid_entry {
struct spdk_nvme_transport_id trid;
@ -335,7 +330,6 @@ perf_set_sock_zcopy(const char *impl_name, bool enable)
}
sock_opts.enable_zerocopy_send = enable;
sock_opts.enable_zerocopy_send_client = enable;
if (spdk_sock_impl_set_opts(impl_name, &sock_opts, opts_size)) {
fprintf(stderr, "Failed to %s zcopy send for sock impl %s: error %d (%s)\n",
@ -453,10 +447,10 @@ uring_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
return 0;
}
static int64_t
static void
uring_check_io(struct ns_worker_ctx *ns_ctx)
{
int i, to_complete, to_submit, count = 0, ret = 0;
int i, count, to_complete, to_submit, ret = 0;
struct perf_task *task;
to_submit = ns_ctx->u.uring.io_pending;
@ -466,7 +460,7 @@ uring_check_io(struct ns_worker_ctx *ns_ctx)
* It will automatically call spdk_io_uring_enter appropriately. */
ret = io_uring_submit(&ns_ctx->u.uring.ring);
if (ret < 0) {
return -1;
return;
}
ns_ctx->u.uring.io_pending = 0;
ns_ctx->u.uring.io_inflight += to_submit;
@ -487,7 +481,6 @@ uring_check_io(struct ns_worker_ctx *ns_ctx)
task_complete(task);
}
}
return count;
}
static void
@ -587,7 +580,7 @@ aio_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
}
}
static int64_t
static void
aio_check_io(struct ns_worker_ctx *ns_ctx)
{
int count, i;
@ -605,7 +598,6 @@ aio_check_io(struct ns_worker_ctx *ns_ctx)
for (i = 0; i < count; i++) {
task_complete(ns_ctx->u.aio.events[i].data);
}
return count;
}
static void
@ -892,18 +884,16 @@ perf_disconnect_cb(struct spdk_nvme_qpair *qpair, void *ctx)
}
static int64_t
static void
nvme_check_io(struct ns_worker_ctx *ns_ctx)
{
int64_t rc;
rc = spdk_nvme_poll_group_process_completions(ns_ctx->u.nvme.group, g_max_completions,
perf_disconnect_cb);
rc = spdk_nvme_poll_group_process_completions(ns_ctx->u.nvme.group, 0, perf_disconnect_cb);
if (rc < 0) {
fprintf(stderr, "NVMe io qpair process completion error\n");
exit(1);
}
return rc;
}
static void
@ -960,7 +950,7 @@ nvme_init_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
opts.delay_cmd_submit = true;
opts.create_only = true;
ns_ctx->u.nvme.group = spdk_nvme_poll_group_create(NULL, NULL);
ns_ctx->u.nvme.group = spdk_nvme_poll_group_create(NULL);
if (ns_ctx->u.nvme.group == NULL) {
goto poll_group_failed;
}
@ -1017,84 +1007,6 @@ nvme_cleanup_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
free(ns_ctx->u.nvme.qpair);
}
static void
nvme_dump_rdma_statistics(struct spdk_nvme_transport_poll_group_stat *stat)
{
struct spdk_nvme_rdma_device_stat *device_stats;
uint32_t i;
printf("RDMA transport:\n");
for (i = 0; i < stat->rdma.num_devices; i++) {
device_stats = &stat->rdma.device_stats[i];
printf("\tdev name: %s\n", device_stats->name);
printf("\tpolls: %"PRIu64"\n", device_stats->polls);
printf("\tidle_polls: %"PRIu64"\n", device_stats->idle_polls);
printf("\tcompletions: %"PRIu64"\n", device_stats->completions);
printf("\tqueued_requests: %"PRIu64"\n", device_stats->queued_requests);
printf("\ttotal_send_wrs: %"PRIu64"\n", device_stats->total_send_wrs);
printf("\tsend_doorbell_updates: %"PRIu64"\n", device_stats->send_doorbell_updates);
printf("\ttotal_recv_wrs: %"PRIu64"\n", device_stats->total_recv_wrs);
printf("\trecv_doorbell_updates: %"PRIu64"\n", device_stats->recv_doorbell_updates);
printf("\t---------------------------------\n");
}
}
static void
nvme_dump_pcie_statistics(struct spdk_nvme_transport_poll_group_stat *stat)
{
struct spdk_nvme_pcie_stat *pcie_stat;
pcie_stat = &stat->pcie;
printf("PCIE transport:\n");
printf("\tpolls: %"PRIu64"\n", pcie_stat->polls);
printf("\tidle_polls: %"PRIu64"\n", pcie_stat->idle_polls);
printf("\tcompletions: %"PRIu64"\n", pcie_stat->completions);
printf("\tcq_doorbell_updates: %"PRIu64"\n", pcie_stat->cq_doorbell_updates);
printf("\tsubmitted_requests: %"PRIu64"\n", pcie_stat->submitted_requests);
printf("\tsq_doobell_updates: %"PRIu64"\n", pcie_stat->sq_doobell_updates);
printf("\tqueued_requests: %"PRIu64"\n", pcie_stat->queued_requests);
}
static void
nvme_dump_transport_stats(uint32_t lcore, struct ns_worker_ctx *ns_ctx)
{
struct spdk_nvme_poll_group *group;
struct spdk_nvme_poll_group_stat *stat = NULL;
uint32_t i;
int rc;
group = ns_ctx->u.nvme.group;
if (group == NULL) {
return;
}
rc = spdk_nvme_poll_group_get_stats(group, &stat);
if (rc) {
fprintf(stderr, "Can't get transport stats, error %d\n", rc);
return;
}
printf("\n====================\n");
printf("lcore %u, ns %s statistics:\n", lcore, ns_ctx->entry->name);
for (i = 0; i < stat->num_transports; i++) {
switch (stat->transport_stat[i]->trtype) {
case SPDK_NVME_TRANSPORT_RDMA:
nvme_dump_rdma_statistics(stat->transport_stat[i]);
break;
case SPDK_NVME_TRANSPORT_PCIE:
nvme_dump_pcie_statistics(stat->transport_stat[i]);
break;
default:
fprintf(stderr, "Unknown transport statistics %d %s\n", stat->transport_stat[i]->trtype,
spdk_nvme_transport_id_trtype_str(stat->transport_stat[i]->trtype));
}
}
spdk_nvme_poll_group_free_stats(group, stat);
}
static const struct ns_fn_table nvme_fn_table = {
.setup_payload = nvme_setup_payload,
.submit_io = nvme_submit_io,
@ -1102,7 +1014,6 @@ static const struct ns_fn_table nvme_fn_table = {
.verify_io = nvme_verify_io,
.init_ns_worker_ctx = nvme_init_ns_worker_ctx,
.cleanup_ns_worker_ctx = nvme_cleanup_ns_worker_ctx,
.dump_transport_stats = nvme_dump_transport_stats
};
static int
@ -1373,10 +1284,6 @@ submit_single_io(struct perf_task *task)
if (spdk_unlikely(rc != 0)) {
RATELIMIT_LOG("starting I/O failed\n");
spdk_dma_free(task->iovs[0].iov_base);
free(task->iovs);
spdk_dma_free(task->md_iov.iov_base);
free(task);
} else {
ns_ctx->current_queue_depth++;
}
@ -1497,11 +1404,6 @@ print_periodic_performance(bool warmup)
double mb_this_second;
struct worker_thread *worker;
struct ns_worker_ctx *ns_ctx;
uint64_t busy_tsc;
uint64_t idle_tsc;
uint64_t core_busy_tsc = 0;
uint64_t core_idle_tsc = 0;
double core_busy_perc = 0;
if (!isatty(STDOUT_FILENO)) {
/* Don't print periodic stats if output is not going
@ -1509,60 +1411,29 @@ print_periodic_performance(bool warmup)
*/
return;
}
io_this_second = 0;
TAILQ_FOREACH(worker, &g_workers, link) {
busy_tsc = 0;
idle_tsc = 0;
TAILQ_FOREACH(ns_ctx, &worker->ns_ctx, link) {
io_this_second += ns_ctx->stats.io_completed - ns_ctx->stats.last_io_completed;
ns_ctx->stats.last_io_completed = ns_ctx->stats.io_completed;
if (g_monitor_perf_cores) {
busy_tsc += ns_ctx->stats.busy_tsc - ns_ctx->stats.last_busy_tsc;
idle_tsc += ns_ctx->stats.idle_tsc - ns_ctx->stats.last_idle_tsc;
ns_ctx->stats.last_busy_tsc = ns_ctx->stats.busy_tsc;
ns_ctx->stats.last_idle_tsc = ns_ctx->stats.idle_tsc;
}
}
if (g_monitor_perf_cores) {
core_busy_tsc += busy_tsc;
core_idle_tsc += idle_tsc;
core_busy_perc += (double)core_busy_tsc / (core_idle_tsc + core_busy_tsc) * 100;
}
}
mb_this_second = (double)io_this_second * g_io_size_bytes / (1024 * 1024);
printf("%s%9ju IOPS, %8.2f MiB/s", warmup ? "[warmup] " : "", io_this_second, mb_this_second);
if (g_monitor_perf_cores) {
printf("%3d Core(s): %6.2f%% Busy", g_num_workers, core_busy_perc);
}
printf("\r");
printf("%s%9ju IOPS, %8.2f MiB/s\r", warmup ? "[warmup] " : "", io_this_second, mb_this_second);
fflush(stdout);
}
static void
perf_dump_transport_statistics(struct worker_thread *worker)
{
struct ns_worker_ctx *ns_ctx;
TAILQ_FOREACH(ns_ctx, &worker->ns_ctx, link) {
if (ns_ctx->entry->fn_table->dump_transport_stats) {
ns_ctx->entry->fn_table->dump_transport_stats(worker->lcore, ns_ctx);
}
}
}
static int
work_fn(void *arg)
{
uint64_t tsc_start, tsc_end, tsc_current, tsc_next_print;
uint64_t tsc_end, tsc_current, tsc_next_print;
struct worker_thread *worker = (struct worker_thread *) arg;
struct ns_worker_ctx *ns_ctx = NULL;
uint32_t unfinished_ns_ctx;
bool warmup = false;
int rc;
int64_t check_rc;
uint64_t check_now;
/* Allocate queue pairs for each namespace. */
TAILQ_FOREACH(ns_ctx, &worker->ns_ctx, link) {
@ -1580,8 +1451,7 @@ work_fn(void *arg)
return 1;
}
tsc_start = spdk_get_ticks();
tsc_current = tsc_start;
tsc_current = spdk_get_ticks();
tsc_next_print = tsc_current + g_tsc_rate;
if (g_warmup_time_in_sec) {
@ -1603,15 +1473,7 @@ work_fn(void *arg)
* to replace each I/O that is completed.
*/
TAILQ_FOREACH(ns_ctx, &worker->ns_ctx, link) {
check_now = spdk_get_ticks();
check_rc = ns_ctx->entry->fn_table->check_io(ns_ctx);
if (check_rc > 0) {
ns_ctx->stats.busy_tsc += check_now - ns_ctx->stats.last_tsc;
} else {
ns_ctx->stats.idle_tsc += check_now - ns_ctx->stats.last_tsc;
}
ns_ctx->stats.last_tsc = check_now;
ns_ctx->entry->fn_table->check_io(ns_ctx);
}
tsc_current = spdk_get_ticks();
@ -1643,20 +1505,6 @@ work_fn(void *arg)
}
}
/* Capture the actual elapsed time when we break out of the main loop. This will account
* for cases where we exit prematurely due to a signal. We only need to capture it on
* one core, so use the main core.
*/
if (worker->lcore == g_main_core) {
g_elapsed_time_in_usec = (tsc_current - tsc_start) * SPDK_SEC_TO_USEC / g_tsc_rate;
}
if (g_dump_transport_stats) {
pthread_mutex_lock(&g_stats_mutex);
perf_dump_transport_statistics(worker);
pthread_mutex_unlock(&g_stats_mutex);
}
/* drain the io of each ns_ctx in round robin to make the fairness */
do {
unfinished_ns_ctx = 0;
@ -1668,17 +1516,15 @@ work_fn(void *arg)
if (ns_ctx->current_queue_depth > 0) {
ns_ctx->entry->fn_table->check_io(ns_ctx);
if (ns_ctx->current_queue_depth > 0) {
if (ns_ctx->current_queue_depth == 0) {
cleanup_ns_worker_ctx(ns_ctx);
} else {
unfinished_ns_ctx++;
}
}
}
} while (unfinished_ns_ctx > 0);
TAILQ_FOREACH(ns_ctx, &worker->ns_ctx, link) {
cleanup_ns_worker_ctx(ns_ctx);
}
return 0;
}
@ -1689,28 +1535,28 @@ static void usage(char *program_name)
printf(" [Kernel device(s)]...");
#endif
printf("\n");
printf("\t[-b, --allowed-pci-addr <addr> allowed local PCIe device address]\n");
printf("\t[-b allowed local PCIe device address]\n");
printf("\t Example: -b 0000:d8:00.0 -b 0000:d9:00.0\n");
printf("\t[-q, --io-depth <val> io depth]\n");
printf("\t[-o, --io-size <val> io size in bytes]\n");
printf("\t[-O, --io-unit-size io unit size in bytes (4-byte aligned) for SPDK driver. default: same as io size]\n");
printf("\t[-P, --num-qpairs <val> number of io queues per namespace. default: 1]\n");
printf("\t[-U, --num-unused-qpairs <val> number of unused io queues per controller. default: 0]\n");
printf("\t[-w, --io-pattern <pattern> io pattern type, must be one of\n");
printf("\t[-q io depth]\n");
printf("\t[-o io size in bytes]\n");
printf("\t[-O io unit size in bytes (4-byte aligned) for SPDK driver. default: same as io size]\n");
printf("\t[-P number of io queues per namespace. default: 1]\n");
printf("\t[-U number of unused io queues per controller. default: 0]\n");
printf("\t[-w io pattern type, must be one of\n");
printf("\t\t(read, write, randread, randwrite, rw, randrw)]\n");
printf("\t[-M, --rwmixread <0-100> rwmixread (100 for reads, 0 for writes)]\n");
printf("\t[-L, --enable-sw-latency-tracking enable latency tracking via sw, default: disabled]\n");
printf("\t[-M rwmixread (100 for reads, 0 for writes)]\n");
printf("\t[-L enable latency tracking via sw, default: disabled]\n");
printf("\t\t-L for latency summary, -LL for detailed histogram\n");
printf("\t[-l, --enable-ssd-latency-tracking enable latency tracking via ssd (if supported), default: disabled]\n");
printf("\t[-t, --time <sec> time in seconds]\n");
printf("\t[-a, --warmup-time <sec> warmup time in seconds]\n");
printf("\t[-c, --core-mask <mask> core mask for I/O submission/completion.]\n");
printf("\t[-l enable latency tracking via ssd (if supported), default: disabled]\n");
printf("\t[-t time in seconds]\n");
printf("\t[-a warmup time in seconds]\n");
printf("\t[-c core mask for I/O submission/completion.]\n");
printf("\t\t(default: 1)\n");
printf("\t[-D, --disable-sq-cmb disable submission queue in controller memory buffer, default: enabled]\n");
printf("\t[-H, --enable-tcp-hdgst enable header digest for TCP transport, default: disabled]\n");
printf("\t[-I, --enable-tcp-ddgst enable data digest for TCP transport, default: disabled]\n");
printf("\t[-N, --no-shst-notification no shutdown notification process for controllers, default: disabled]\n");
printf("\t[-r, --transport <fmt> Transport ID for local PCIe NVMe or NVMeoF]\n");
printf("\t[-D disable submission queue in controller memory buffer, default: enabled]\n");
printf("\t[-H enable header digest for TCP transport, default: disabled]\n");
printf("\t[-I enable data digest for TCP transport, default: disabled]\n");
printf("\t[-N no shutdown notification process for controllers, default: disabled]\n");
printf("\t[-r Transport ID for local PCIe NVMe or NVMeoF]\n");
printf("\t Format: 'key:value [key:value] ...'\n");
printf("\t Keys:\n");
printf("\t trtype Transport type (e.g. PCIe, RDMA)\n");
@ -1718,42 +1564,37 @@ static void usage(char *program_name)
printf("\t traddr Transport address (e.g. 0000:04:00.0 for PCIe or 192.168.100.8 for RDMA)\n");
printf("\t trsvcid Transport service identifier (e.g. 4420)\n");
printf("\t subnqn Subsystem NQN (default: %s)\n", SPDK_NVMF_DISCOVERY_NQN);
printf("\t ns NVMe namespace ID (all active namespaces are used by default)\n");
printf("\t hostnqn Host NQN\n");
printf("\t Example: -r 'trtype:PCIe traddr:0000:04:00.0' for PCIe or\n");
printf("\t -r 'trtype:RDMA adrfam:IPv4 traddr:192.168.100.8 trsvcid:4420' for NVMeoF\n");
printf("\t Note: can be specified multiple times to test multiple disks/targets.\n");
printf("\t[-e, --metadata <fmt> metadata configuration]\n");
printf("\t[-e metadata configuration]\n");
printf("\t Keys:\n");
printf("\t PRACT Protection Information Action bit (PRACT=1 or PRACT=0)\n");
printf("\t PRCHK Control of Protection Information Checking (PRCHK=GUARD|REFTAG|APPTAG)\n");
printf("\t Example: -e 'PRACT=0,PRCHK=GUARD|REFTAG|APPTAG'\n");
printf("\t -e 'PRACT=1,PRCHK=GUARD'\n");
printf("\t[-k, --keepalive <ms> keep alive timeout period in millisecond]\n");
printf("\t[-s, --hugemem-size <MB> DPDK huge memory size in MB.]\n");
printf("\t[-g, --mem-single-seg use single file descriptor for DPDK memory segments]\n");
printf("\t[-C, --max-completion-per-poll <val> max completions per poll]\n");
printf("\t[-k keep alive timeout period in millisecond]\n");
printf("\t[-s DPDK huge memory size in MB.]\n");
printf("\t[-g use single file descriptor for DPDK memory segments]\n");
printf("\t[-C max completions per poll]\n");
printf("\t\t(default: 0 - unlimited)\n");
printf("\t[-i, --shmem-grp-id <id> shared memory group ID]\n");
printf("\t[-Q, --skip-errors log I/O errors every N times (default: 1)\n");
printf("\t[-i shared memory group ID]\n");
printf("\t[-Q log I/O errors every N times (default: 1)\n");
printf("\t");
spdk_log_usage(stdout, "-T");
printf("\t[-V, --enable-vmd enable VMD enumeration]\n");
printf("\t[-z, --disable-zcopy <impl> disable zero copy send for the given sock implementation. Default for posix impl]\n");
printf("\t[-Z, --enable-zcopy <impl> enable zero copy send for the given sock implementation]\n");
printf("\t[-A, --buffer-alignment IO buffer alignment. Must be power of 2 and not less than cache line (%u)]\n",
printf("\t[-V enable VMD enumeration]\n");
printf("\t[-z disable zero copy send for the given sock implementation. Default for posix impl]\n");
printf("\t[-Z enable zero copy send for the given sock implementation]\n");
printf("\t[-A IO buffer alignment. Must be power of 2 and not less than cache line (%u)]\n",
SPDK_CACHE_LINE_SIZE);
printf("\t[-S, --default-sock-impl <impl> set the default sock impl, e.g. \"posix\"]\n");
printf("\t[-m, --cpu-usage display real-time overall cpu usage on used cores]\n");
printf("\t[-S set the default sock impl, e.g. \"posix\"]\n");
#ifdef SPDK_CONFIG_URING
printf("\t[-R, --enable-uring enable using liburing to drive kernel devices (Default: libaio)]\n");
printf("\t[-R enable using liburing to drive kernel devices (Default: libaio)]\n");
#endif
#ifdef DEBUG
printf("\t[-G, --enable-debug enable debug logging]\n");
printf("\t[-G enable debug logging]\n");
#else
printf("\t[-G, --enable-debug enable debug logging (flag disabled, must reconfigure with --enable-debug)\n");
printf("\t[--transport-stats dump transport statistics]\n");
printf("\t[--iova-mode <mode> specify DPDK IOVA mode: va|pa]\n");
printf("\t[-G enable debug logging (flag disabled, must reconfigure with --enable-debug)\n");
#endif
}
@ -1827,7 +1668,7 @@ print_performance(void)
TAILQ_FOREACH(worker, &g_workers, link) {
TAILQ_FOREACH(ns_ctx, &worker->ns_ctx, link) {
if (ns_ctx->stats.io_completed != 0) {
io_per_second = (double)ns_ctx->stats.io_completed * 1000 * 1000 / g_elapsed_time_in_usec;
io_per_second = (double)ns_ctx->stats.io_completed / g_time_in_sec;
mb_per_second = io_per_second * g_io_size_bytes / (1024 * 1024);
average_latency = ((double)ns_ctx->stats.total_tsc / ns_ctx->stats.io_completed) * 1000 * 1000 /
g_tsc_rate;
@ -2061,23 +1902,23 @@ add_trid(const char *trid_str)
}
static int
add_allowed_pci_device(const char *bdf_str, struct spdk_env_opts *env_opts)
add_allowed_pci_device(const char *bdf_str)
{
int rc;
if (env_opts->num_pci_addr >= MAX_ALLOWED_PCI_DEVICE_NUM) {
if (g_allowed_pci_addr_num >= MAX_ALLOWED_PCI_DEVICE_NUM) {
fprintf(stderr, "Currently we only support allowed PCI device num=%d\n",
MAX_ALLOWED_PCI_DEVICE_NUM);
return -1;
}
rc = spdk_pci_addr_parse(&env_opts->pci_allowed[env_opts->num_pci_addr], bdf_str);
rc = spdk_pci_addr_parse(&g_allowed_pci_addr[g_allowed_pci_addr_num], bdf_str);
if (rc < 0) {
fprintf(stderr, "Failed to parse the given bdf_str=%s\n", bdf_str);
return -1;
}
env_opts->num_pci_addr++;
g_allowed_pci_addr_num++;
return 0;
}
@ -2171,155 +2012,77 @@ parse_metadata(const char *metacfg_str)
return 0;
}
#define PERF_GETOPT_SHORT "a:b:c:e:gi:lmo:q:r:k:s:t:w:z:A:C:DGHILM:NO:P:Q:RS:T:U:VZ:"
static const struct option g_perf_cmdline_opts[] = {
#define PERF_WARMUP_TIME 'a'
{"warmup-time", required_argument, NULL, PERF_WARMUP_TIME},
#define PERF_ALLOWED_PCI_ADDR 'b'
{"allowed-pci-addr", required_argument, NULL, PERF_ALLOWED_PCI_ADDR},
#define PERF_CORE_MASK 'c'
{"core-mask", required_argument, NULL, PERF_CORE_MASK},
#define PERF_METADATA 'e'
{"metadata", required_argument, NULL, PERF_METADATA},
#define PERF_MEM_SINGL_SEG 'g'
{"mem-single-seg", no_argument, NULL, PERF_MEM_SINGL_SEG},
#define PERF_SHMEM_GROUP_ID 'i'
{"shmem-grp-id", required_argument, NULL, PERF_SHMEM_GROUP_ID},
#define PERF_ENABLE_SSD_LATENCY_TRACING 'l'
{"enable-ssd-latency-tracking", no_argument, NULL, PERF_ENABLE_SSD_LATENCY_TRACING},
#define PERF_CPU_USAGE 'm'
{"cpu-usage", no_argument, NULL, PERF_CPU_USAGE},
#define PERF_IO_SIZE 'o'
{"io-size", required_argument, NULL, PERF_IO_SIZE},
#define PERF_IO_DEPTH 'q'
{"io-depth", required_argument, NULL, PERF_IO_DEPTH},
#define PERF_TRANSPORT 'r'
{"transport", required_argument, NULL, PERF_TRANSPORT},
#define PERF_KEEPALIVE 'k'
{"keepalive", required_argument, NULL, PERF_KEEPALIVE},
#define PERF_HUGEMEM_SIZE 's'
{"hugemem-size", required_argument, NULL, PERF_HUGEMEM_SIZE},
#define PERF_TIME 't'
{"time", required_argument, NULL, PERF_TIME},
#define PERF_IO_PATTERN 'w'
{"io-pattern", required_argument, NULL, PERF_IO_PATTERN},
#define PERF_DISABLE_ZCOPY 'z'
{"disable-zcopy", required_argument, NULL, PERF_DISABLE_ZCOPY},
#define PERF_BUFFER_ALIGNMENT 'A'
{"buffer-alignment", required_argument, NULL, PERF_BUFFER_ALIGNMENT},
#define PERF_MAX_COMPLETIONS_PER_POLL 'C'
{"max-completion-per-poll", required_argument, NULL, PERF_MAX_COMPLETIONS_PER_POLL},
#define PERF_DISABLE_SQ_CMB 'D'
{"disable-sq-cmb", no_argument, NULL, PERF_DISABLE_SQ_CMB},
#define PERF_ENABLE_DEBUG 'G'
{"enable-debug", no_argument, NULL, PERF_ENABLE_DEBUG},
#define PERF_ENABLE_TCP_HDGST 'H'
{"enable-tcp-hdgst", no_argument, NULL, PERF_ENABLE_TCP_HDGST},
#define PERF_ENABLE_TCP_DDGST 'I'
{"enable-tcp-ddgst", no_argument, NULL, PERF_ENABLE_TCP_DDGST},
#define PERF_ENABLE_SW_LATENCY_TRACING 'L'
{"enable-sw-latency-tracking", no_argument, NULL, PERF_ENABLE_SW_LATENCY_TRACING},
#define PERF_RW_MIXREAD 'M'
{"rwmixread", required_argument, NULL, PERF_RW_MIXREAD},
#define PERF_NO_SHST_NOTIFICATION 'N'
{"no-shst-notification", no_argument, NULL, PERF_NO_SHST_NOTIFICATION},
#define PERF_IO_UNIT_SIZE 'O'
{"io-unit-size", required_argument, NULL, PERF_IO_UNIT_SIZE},
#define PERF_IO_QUEUES_PER_NS 'P'
{"num-qpairs", required_argument, NULL, PERF_IO_QUEUES_PER_NS},
#define PERF_SKIP_ERRRORS 'Q'
{"skip-errors", required_argument, NULL, PERF_SKIP_ERRRORS},
#define PERF_ENABLE_URING 'R'
{"enable-uring", no_argument, NULL, PERF_ENABLE_URING},
#define PERF_DEFAULT_SOCK_IMPL 'S'
{"default-sock-impl", required_argument, NULL, PERF_DEFAULT_SOCK_IMPL},
#define PERF_LOG_FLAG 'T'
{"logflag", required_argument, NULL, PERF_LOG_FLAG},
#define PERF_NUM_UNUSED_IO_QPAIRS 'U'
{"num-unused-qpairs", required_argument, NULL, PERF_NUM_UNUSED_IO_QPAIRS},
#define PERF_ENABLE_VMD 'V'
{"enable-vmd", no_argument, NULL, PERF_ENABLE_VMD},
#define PERF_ENABLE_ZCOPY 'Z'
{"enable-zcopy", required_argument, NULL, PERF_ENABLE_ZCOPY},
#define PERF_TRANSPORT_STATISTICS 257
{"transport-stats", no_argument, NULL, PERF_TRANSPORT_STATISTICS},
#define PERF_IOVA_MODE 258
{"iova-mode", required_argument, NULL, PERF_IOVA_MODE},
/* Should be the last element */
{0, 0, 0, 0}
};
static int
parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
parse_args(int argc, char **argv)
{
int op, long_idx;
int op;
long int val;
int rc;
while ((op = getopt_long(argc, argv, PERF_GETOPT_SHORT, g_perf_cmdline_opts, &long_idx)) != -1) {
while ((op = getopt(argc, argv,
"a:b:c:e:gi:lo:q:r:k:s:t:w:z:A:C:DGHILM:NO:P:Q:RS:T:U:VZ:")) != -1) {
switch (op) {
case PERF_WARMUP_TIME:
case PERF_BUFFER_ALIGNMENT:
case PERF_SHMEM_GROUP_ID:
case PERF_MAX_COMPLETIONS_PER_POLL:
case PERF_IO_QUEUES_PER_NS:
case PERF_IO_SIZE:
case PERF_IO_UNIT_SIZE:
case PERF_IO_DEPTH:
case PERF_KEEPALIVE:
case PERF_HUGEMEM_SIZE:
case PERF_TIME:
case PERF_RW_MIXREAD:
case PERF_NUM_UNUSED_IO_QPAIRS:
case PERF_SKIP_ERRRORS:
case 'a':
case 'A':
case 'i':
case 'C':
case 'P':
case 'o':
case 'O':
case 'q':
case 'k':
case 's':
case 't':
case 'M':
case 'Q':
case 'U':
val = spdk_strtol(optarg, 10);
if (val < 0) {
fprintf(stderr, "Converting a string to integer failed\n");
return val;
}
switch (op) {
case PERF_WARMUP_TIME:
case 'a':
g_warmup_time_in_sec = val;
break;
case PERF_SHMEM_GROUP_ID:
env_opts->shm_id = val;
case 'i':
g_shm_id = val;
break;
case PERF_MAX_COMPLETIONS_PER_POLL:
case 'C':
g_max_completions = val;
break;
case PERF_IO_QUEUES_PER_NS:
case 'P':
g_nr_io_queues_per_ns = val;
break;
case PERF_IO_SIZE:
case 'o':
g_io_size_bytes = val;
break;
case PERF_IO_UNIT_SIZE:
case 'O':
g_io_unit_size = val;
break;
case PERF_IO_DEPTH:
case 'q':
g_queue_depth = val;
break;
case PERF_KEEPALIVE:
case 'k':
g_keep_alive_timeout_in_ms = val;
break;
case PERF_HUGEMEM_SIZE:
env_opts->mem_size = val;
case 's':
g_dpdk_mem = val;
break;
case PERF_TIME:
case 't':
g_time_in_sec = val;
break;
case PERF_RW_MIXREAD:
case 'M':
g_rw_percentage = val;
g_mix_specified = true;
break;
case PERF_SKIP_ERRRORS:
case 'Q':
g_quiet_count = val;
break;
case PERF_NUM_UNUSED_IO_QPAIRS:
case 'U':
g_nr_unused_io_queues = val;
break;
case PERF_BUFFER_ALIGNMENT:
case 'A':
g_io_align = val;
if (!spdk_u32_is_pow2(g_io_align) || g_io_align < SPDK_CACHE_LINE_SIZE) {
fprintf(stderr, "Wrong alignment %u. Must be power of 2 and not less than cache lize (%u)\n",
@ -2331,43 +2094,40 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
break;
}
break;
case PERF_ALLOWED_PCI_ADDR:
if (add_allowed_pci_device(optarg, env_opts)) {
case 'b':
if (add_allowed_pci_device(optarg)) {
usage(argv[0]);
return 1;
}
break;
case PERF_CORE_MASK:
env_opts->core_mask = optarg;
case 'c':
g_core_mask = optarg;
break;
case PERF_METADATA:
case 'e':
if (parse_metadata(optarg)) {
usage(argv[0]);
return 1;
}
break;
case PERF_MEM_SINGL_SEG:
env_opts->hugepage_single_segments = true;
case 'g':
g_dpdk_mem_single_seg = true;
break;
case PERF_ENABLE_SSD_LATENCY_TRACING:
case 'l':
g_latency_ssd_tracking_enable = true;
break;
case PERF_CPU_USAGE:
g_monitor_perf_cores = true;
break;
case PERF_TRANSPORT:
case 'r':
if (add_trid(optarg)) {
usage(argv[0]);
return 1;
}
break;
case PERF_IO_PATTERN:
case 'w':
g_workload_type = optarg;
break;
case PERF_DISABLE_SQ_CMB:
case 'D':
g_disable_sq_cmb = 1;
break;
case PERF_ENABLE_DEBUG:
case 'G':
#ifndef DEBUG
fprintf(stderr, "%s must be configured with --enable-debug for -G flag\n",
argv[0]);
@ -2378,19 +2138,19 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
spdk_log_set_print_level(SPDK_LOG_DEBUG);
break;
#endif
case PERF_ENABLE_TCP_HDGST:
case 'H':
g_header_digest = 1;
break;
case PERF_ENABLE_TCP_DDGST:
case 'I':
g_data_digest = 1;
break;
case PERF_ENABLE_SW_LATENCY_TRACING:
case 'L':
g_latency_sw_tracking_level++;
break;
case PERF_NO_SHST_NOTIFICATION:
case 'N':
g_no_shn_notification = true;
break;
case PERF_ENABLE_URING:
case 'R':
#ifndef SPDK_CONFIG_URING
fprintf(stderr, "%s must be rebuilt with CONFIG_URING=y for -R flag.\n",
argv[0]);
@ -2399,7 +2159,7 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
#endif
g_use_uring = true;
break;
case PERF_LOG_FLAG:
case 'T':
rc = spdk_log_set_flag(optarg);
if (rc < 0) {
fprintf(stderr, "unknown flag\n");
@ -2410,28 +2170,22 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
spdk_log_set_print_level(SPDK_LOG_DEBUG);
#endif
break;
case PERF_ENABLE_VMD:
case 'V':
g_vmd = true;
break;
case PERF_DISABLE_ZCOPY:
case 'z':
perf_set_sock_zcopy(optarg, false);
break;
case PERF_ENABLE_ZCOPY:
case 'Z':
perf_set_sock_zcopy(optarg, true);
break;
case PERF_DEFAULT_SOCK_IMPL:
case 'S':
rc = spdk_sock_set_default_impl(optarg);
if (rc) {
fprintf(stderr, "Failed to set sock impl %s, err %d (%s)\n", optarg, errno, strerror(errno));
return 1;
}
break;
case PERF_TRANSPORT_STATISTICS:
g_dump_transport_stats = true;
break;
case PERF_IOVA_MODE:
env_opts->iova_mode = optarg;
break;
default:
usage(argv[0]);
return 1;
@ -2444,12 +2198,12 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
}
if (!g_queue_depth) {
fprintf(stderr, "missing -q (--io-depth) operand\n");
fprintf(stderr, "missing -q (queue size) operand\n");
usage(argv[0]);
return 1;
}
if (!g_io_size_bytes) {
fprintf(stderr, "missing -o (--io-size) operand\n");
fprintf(stderr, "missing -o (block size) operand\n");
usage(argv[0]);
return 1;
}
@ -2458,17 +2212,17 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
return 1;
}
if (!g_workload_type) {
fprintf(stderr, "missing -w (--io-pattern) operand\n");
fprintf(stderr, "missing -w (io pattern type) operand\n");
usage(argv[0]);
return 1;
}
if (!g_time_in_sec) {
fprintf(stderr, "missing -t (--time) operand\n");
fprintf(stderr, "missing -t (test time in seconds) operand\n");
usage(argv[0]);
return 1;
}
if (!g_quiet_count) {
fprintf(stderr, "-Q (--skip-errors) value must be greater than 0\n");
fprintf(stderr, "-Q value must be greater than 0\n");
usage(argv[0]);
return 1;
}
@ -2481,19 +2235,19 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
if (strcmp(g_workload_type, "read") == 0 || strcmp(g_workload_type, "write") == 0) {
g_rw_percentage = strcmp(g_workload_type, "read") == 0 ? 100 : 0;
if (g_mix_specified) {
fprintf(stderr, "Ignoring -M (--rwmixread) option... Please use -M option"
fprintf(stderr, "Ignoring -M option... Please use -M option"
" only when using rw or randrw.\n");
}
} else if (strcmp(g_workload_type, "rw") == 0) {
if (g_rw_percentage < 0 || g_rw_percentage > 100) {
fprintf(stderr,
"-M (--rwmixread) must be specified to value from 0 to 100 "
"-M must be specified to value from 0 to 100 "
"for rw or randrw.\n");
return 1;
}
} else {
fprintf(stderr,
"-o (--io-pattern) io pattern type must be one of\n"
"io pattern type must be one of\n"
"(read, write, randread, randwrite, rw, randrw)\n");
return 1;
}
@ -2504,11 +2258,11 @@ parse_args(int argc, char **argv, struct spdk_env_opts *env_opts)
} else {
struct trid_entry *trid_entry, *trid_entry_tmp;
env_opts->no_pci = true;
g_no_pci = true;
/* check whether there is local PCIe type */
TAILQ_FOREACH_SAFE(trid_entry, &g_trid_list, tailq, trid_entry_tmp) {
if (trid_entry->trid.trtype == SPDK_NVME_TRANSPORT_PCIE) {
env_opts->no_pci = false;
g_no_pci = false;
break;
}
}
@ -2792,19 +2546,29 @@ int main(int argc, char **argv)
struct spdk_env_opts opts;
pthread_t thread_id = 0;
spdk_env_opts_init(&opts);
opts.name = "perf";
opts.pci_allowed = g_allowed_pci_addr;
rc = parse_args(argc, argv, &opts);
rc = parse_args(argc, argv);
if (rc != 0) {
return rc;
}
/* Transport statistics are printed from each thread.
* To avoid mess in terminal, init and use mutex */
rc = pthread_mutex_init(&g_stats_mutex, NULL);
if (rc != 0) {
fprintf(stderr, "Failed to init mutex\n");
goto cleanup;
spdk_env_opts_init(&opts);
opts.name = "perf";
opts.shm_id = g_shm_id;
if (g_core_mask) {
opts.core_mask = g_core_mask;
}
if (g_dpdk_mem) {
opts.mem_size = g_dpdk_mem;
}
opts.hugepage_single_segments = g_dpdk_mem_single_seg;
if (g_no_pci) {
opts.no_pci = g_no_pci;
}
if (g_allowed_pci_addr_num) {
opts.pci_allowed = g_allowed_pci_addr;
opts.num_pci_addr = g_allowed_pci_addr_num;
}
if (spdk_env_init(&opts) < 0) {
fprintf(stderr, "Unable to initialize SPDK env\n");
@ -2900,8 +2664,6 @@ cleanup:
unregister_controllers();
unregister_workers();
pthread_mutex_destroy(&g_stats_mutex);
if (rc != 0) {
fprintf(stderr, "%s: errors occured\n", argv[0]);
}

View File

@ -1,38 +0,0 @@
#
# BSD LICENSE
#
# Copyright (c) Samsung Electronics Co., Ltd.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Samsung Electronics Co., Ltd. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
APP = pmr_persistence
include $(SPDK_ROOT_DIR)/mk/nvme.libtest.mk

View File

@ -1,419 +0,0 @@
/*-
* BSD LICENSE
*
* Copyright (c) Samsung Electronics Co., Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Samsung Electronics Co., Ltd., nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "spdk/stdinc.h"
#include "spdk/env.h"
#include "spdk/nvme.h"
#include "spdk/string.h"
struct nvme_io {
struct spdk_nvme_ctrlr *ctrlr;
struct spdk_nvme_transport_id trid;
struct spdk_nvme_ns *ns;
unsigned nsid;
unsigned rlba;
unsigned nlbas;
unsigned wlba;
uint32_t lba_size;
unsigned done;
};
struct config {
struct nvme_io pmr_dev;
size_t copy_size;
};
static struct config g_config;
/* Namespaces index from 1. Return 0 to invoke an error */
static unsigned
get_nsid(const struct spdk_nvme_transport_id *trid)
{
if (!strcmp(trid->traddr, g_config.pmr_dev.trid.traddr)) {
return g_config.pmr_dev.nsid;
}
return 0;
}
static void
check_io(void *arg, const struct spdk_nvme_cpl *completion)
{
g_config.pmr_dev.done = 1;
}
static int
pmr_persistence(void)
{
int rc = 0;
void *pmr_buf, *buf;
size_t sz;
struct spdk_nvme_qpair *qpair;
/* Allocate Queue Pair for the Controller with PMR */
qpair = spdk_nvme_ctrlr_alloc_io_qpair(g_config.pmr_dev.ctrlr, NULL, 0);
if (qpair == NULL) {
printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
return -ENOMEM;
}
/* Enable the PMR */
rc = spdk_nvme_ctrlr_enable_pmr(g_config.pmr_dev.ctrlr);
if (rc) {
printf("ERROR: Enabling PMR failed\n");
printf("Are you sure %s has a valid PMR?\n",
g_config.pmr_dev.trid.traddr);
goto free_qpair;
}
/* Allocate buffer from PMR */
pmr_buf = spdk_nvme_ctrlr_map_pmr(g_config.pmr_dev.ctrlr, &sz);
if (pmr_buf == NULL || sz < g_config.copy_size) {
printf("ERROR: PMR buffer allocation failed\n");
rc = -ENOMEM;
goto disable_pmr;
}
/* Clear the done flag */
g_config.pmr_dev.done = 0;
/* Do the write to the PMR IO buffer, reading from rlba */
rc = spdk_nvme_ns_cmd_read(g_config.pmr_dev.ns, qpair, pmr_buf,
g_config.pmr_dev.rlba, g_config.pmr_dev.nlbas,
check_io, NULL, 0);
if (rc != 0) {
fprintf(stderr, "Read I/O to PMR failed\n");
rc = -EIO;
goto unmap_pmr;
}
while (!g_config.pmr_dev.done) {
spdk_nvme_qpair_process_completions(qpair, 0);
}
/* Clear the done flag */
g_config.pmr_dev.done = 0;
pmr_buf = NULL;
/* Free PMR buffer */
rc = spdk_nvme_ctrlr_unmap_pmr(g_config.pmr_dev.ctrlr);
if (rc) {
printf("ERROR: Unmapping PMR failed\n");
goto disable_pmr;
}
/* Disable the PMR */
rc = spdk_nvme_ctrlr_disable_pmr(g_config.pmr_dev.ctrlr);
if (rc) {
printf("ERROR: Disabling PMR failed\n");
goto free_qpair;
}
/* Free the queue */
spdk_nvme_ctrlr_free_io_qpair(qpair);
rc = spdk_nvme_ctrlr_reset(g_config.pmr_dev.ctrlr);
if (rc) {
printf("ERROR: Resetting Controller failed\n");
return rc;
}
/* Allocate Queue Pair for the Controller with PMR */
qpair = spdk_nvme_ctrlr_alloc_io_qpair(g_config.pmr_dev.ctrlr, NULL, 0);
if (qpair == NULL) {
printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
return -ENOMEM;
}
/* Enable the PMR */
rc = spdk_nvme_ctrlr_enable_pmr(g_config.pmr_dev.ctrlr);
if (rc) {
printf("ERROR: Enabling PMR failed\n");
goto free_qpair;
}
/* Allocate buffer from PMR */
pmr_buf = spdk_nvme_ctrlr_map_pmr(g_config.pmr_dev.ctrlr, &sz);
if (pmr_buf == NULL || sz < g_config.copy_size) {
printf("ERROR: PMR buffer allocation failed\n");
rc = -ENOMEM;
goto disable_pmr;
}
/* Do the read from the PMR IO buffer, write to wlba */
rc = spdk_nvme_ns_cmd_write(g_config.pmr_dev.ns, qpair, pmr_buf,
g_config.pmr_dev.wlba, g_config.pmr_dev.nlbas,
check_io, NULL, 0);
if (rc != 0) {
fprintf(stderr, "Read I/O from PMR failed\n");
rc = -EIO;
goto unmap_pmr;
}
while (!g_config.pmr_dev.done) {
spdk_nvme_qpair_process_completions(qpair, 0);
}
/* Clear the done flag */
g_config.pmr_dev.done = 0;
buf = spdk_zmalloc(g_config.copy_size, 0x1000, NULL, SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA);
if (buf == NULL) {
printf("ERROR: Buffer allocation failed\n");
rc = -ENOMEM;
goto unmap_pmr;
}
/* Do the read from wlba to a buffer */
rc = spdk_nvme_ns_cmd_read(g_config.pmr_dev.ns, qpair, buf,
g_config.pmr_dev.wlba, g_config.pmr_dev.nlbas,
check_io, NULL, 0);
if (rc != 0) {
fprintf(stderr, "Read I/O from WLBA failed\n");
rc = -EIO;
goto free_buf;
}
while (!g_config.pmr_dev.done) {
spdk_nvme_qpair_process_completions(qpair, 0);
}
/* Clear the done flag */
g_config.pmr_dev.done = 0;
/* Compare the data in the read buffer to the PMR buffer */
if (memcmp(buf, pmr_buf, g_config.copy_size)) {
printf("PMR Data Not Persistent, after Controller Reset\n");
rc = -EIO;
} else {
printf("PMR Data is Persistent across Controller Reset\n");
}
free_buf:
spdk_free(buf);
unmap_pmr:
/* Free PMR buffer */
spdk_nvme_ctrlr_unmap_pmr(g_config.pmr_dev.ctrlr);
disable_pmr:
/* Disable the PMR */
spdk_nvme_ctrlr_disable_pmr(g_config.pmr_dev.ctrlr);
free_qpair:
/* Free the queue */
spdk_nvme_ctrlr_free_io_qpair(qpair);
return rc;
}
static bool
probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
struct spdk_nvme_ctrlr_opts *opts)
{
/* We will only attach to the Controller specified by the user */
if (spdk_nvme_transport_id_compare(trid, &g_config.pmr_dev.trid)) {
printf("%s - not probed %s!\n", __func__, trid->traddr);
return 0;
}
printf("%s - probed %s!\n", __func__, trid->traddr);
return 1;
}
static void
attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
{
struct spdk_nvme_ns *ns;
ns = spdk_nvme_ctrlr_get_ns(ctrlr, get_nsid(trid));
if (ns == NULL) {
fprintf(stderr, "Could not locate namespace %d on controller %s.\n",
get_nsid(trid), trid->traddr);
exit(-1);
}
g_config.pmr_dev.ctrlr = ctrlr;
g_config.pmr_dev.ns = ns;
g_config.pmr_dev.lba_size = spdk_nvme_ns_get_sector_size(ns);
printf("%s - attached %s!\n", __func__, trid->traddr);
}
static void
usage(char *program_name)
{
printf("%s options (all mandatory)", program_name);
printf("\n");
printf("\t[-p PCIe address of the NVMe Device with PMR support]\n");
printf("\t[-n Namespace ID]\n");
printf("\t[-r Read LBA]\n");
printf("\t[-l Number of LBAs to read]\n");
printf("\t[-w Write LBA]\n");
printf("\n");
}
static int
parse_args(int argc, char **argv)
{
int op;
unsigned num_args = 0;
long int val;
while ((op = getopt(argc, argv, "p:n:r:l:w:")) != -1) {
switch (op) {
case 'p':
snprintf(&g_config.pmr_dev.trid.traddr[0], SPDK_NVMF_TRADDR_MAX_LEN + 1,
"%s", optarg);
g_config.pmr_dev.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
spdk_nvme_transport_id_populate_trstring(&g_config.pmr_dev.trid,
spdk_nvme_transport_id_trtype_str(g_config.pmr_dev.trid.trtype));
num_args++;
break;
case 'n':
case 'r':
case 'l':
case 'w':
val = spdk_strtol(optarg, 10);
if (val < 0) {
fprintf(stderr, "Converting a string to integer failed\n");
return val;
}
switch (op) {
case 'n':
g_config.pmr_dev.nsid = (unsigned)val;
num_args++;
break;
case 'r':
g_config.pmr_dev.rlba = (unsigned)val;
num_args++;
break;
case 'l':
g_config.pmr_dev.nlbas = (unsigned)val;
num_args++;
break;
case 'w':
g_config.pmr_dev.wlba = (unsigned)val;
num_args++;
break;
}
break;
default:
usage(argv[0]);
return 1;
}
}
if (num_args != 5) {
usage(argv[0]);
return 1;
}
return 0;
}
static void
cleanup(void)
{
struct spdk_nvme_detach_ctx *detach_ctx = NULL;
spdk_nvme_detach_async(g_config.pmr_dev.ctrlr, &detach_ctx);
while (detach_ctx && spdk_nvme_detach_poll_async(detach_ctx) == -EAGAIN) {
;
}
}
int main(int argc, char **argv)
{
int rc = 0;
struct spdk_env_opts opts;
/*
* Parse the input arguments. For now we use the following
* format list:
*
* -p <pci id> -n <namespace> -r <Read LBA> -l <number of LBAs> -w <Write LBA>
*
*/
rc = parse_args(argc, argv);
if (rc) {
fprintf(stderr, "Error in parse_args(): %d\n", rc);
return rc;
}
/*
* SPDK relies on an abstraction around the local environment
* named env that handles memory allocation and PCI device operations.
* This library must be initialized first.
*
*/
spdk_env_opts_init(&opts);
opts.name = "pmr_persistence";
opts.shm_id = 0;
if (spdk_env_init(&opts) < 0) {
fprintf(stderr, "Unable to initialize SPDK env\n");
return 1;
}
/*
* PMRs only apply to PCIe attached NVMe controllers so we
* only probe the PCIe bus. This is the default when we pass
* in NULL for the first argument.
*/
rc = spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL);
if (rc) {
fprintf(stderr, "Error in spdk_nvme_probe(): %d\n", rc);
cleanup();
return rc;
}
g_config.copy_size = g_config.pmr_dev.nlbas * g_config.pmr_dev.lba_size;
/*
* Call the pmr_persistence() function which performs the data copy
* to PMR region, resets the Controller and verifies the data persistence
* or returns an error code if it fails.
*/
rc = pmr_persistence();
if (rc) {
fprintf(stderr, "Error in pmr_persistence(): %d\n", rc);
}
cleanup();
return rc;
}

View File

@ -183,8 +183,6 @@ parse_args(int argc, char **argv, struct spdk_env_opts *opts)
opts->no_pci = true;
break;
case 'h':
usage(argv[0]);
exit(EXIT_SUCCESS);
default:
usage(argv[0]);
return 1;
@ -711,13 +709,7 @@ static void
nvmf_subsystem_init_done(int rc, void *cb_arg)
{
fprintf(stdout, "bdev subsystem init successfully\n");
rc = spdk_rpc_initialize(g_rpc_addr);
if (rc) {
spdk_app_stop(rc);
return;
}
spdk_rpc_initialize(g_rpc_addr);
spdk_rpc_set_state(SPDK_RPC_RUNTIME);
g_target_state = NVMF_INIT_TARGET;

View File

@ -315,27 +315,6 @@ int spdk_accel_batch_prep_crc32c(struct spdk_io_channel *ch, struct spdk_accel_b
uint32_t *dst, void *src, uint32_t seed, uint64_t nbytes,
spdk_accel_completion_cb cb_fn, void *cb_arg);
/**
* Synchronous call to prepare a chained crc32c request into a previously initialized batch
* created with spdk_accel_batch_create(). The callback will be called when the crc32c
* completes after the batch has been submitted by an asynchronous call to
* spdk_accel_batch_submit().
*
* \param ch I/O channel associated with this call.
* \param batch Handle provided when the batch was started with spdk_accel_batch_create().
* \param dst Destination to write the CRC-32C to.
* \param iovs The io vector array which stores the src data and len.
* \param iovcnt The size of the iov.
* \param seed Four byte seed value.
* \param cb_fn Called when this operation completes.
* \param cb_arg Callback argument.
*
* \return 0 on success, negative errno on failure.
*/
int spdk_accel_batch_prep_crc32cv(struct spdk_io_channel *ch, struct spdk_accel_batch *batch,
uint32_t *dst, struct iovec *iovs, uint32_t iovcnt, uint32_t seed,
spdk_accel_completion_cb cb_fn, void *cb_arg);
/**
* Submit a CRC-32C calculation request.
*
@ -354,24 +333,6 @@ int spdk_accel_batch_prep_crc32cv(struct spdk_io_channel *ch, struct spdk_accel_
int spdk_accel_submit_crc32c(struct spdk_io_channel *ch, uint32_t *dst, void *src, uint32_t seed,
uint64_t nbytes, spdk_accel_completion_cb cb_fn, void *cb_arg);
/**
* Submit a chained CRC-32C calculation request.
*
* This operation will calculate the 4 byte CRC32-C for the given data.
*
* \param ch I/O channel associated with this call.
* \param dst Destination to write the CRC-32C to.
* \param iovs The io vector array which stores the src data and len.
* \param iovcnt The size of the iov.
* \param seed Four byte seed value.
* \param cb_fn Called when this CRC-32C operation completes.
* \param cb_arg Callback argument.
*
* \return 0 on success, negative errno on failure.
*/
int spdk_accel_submit_crc32cv(struct spdk_io_channel *ch, uint32_t *dst, struct iovec *iovs,
uint32_t iovcnt, uint32_t seed, spdk_accel_completion_cb cb_fn, void *cb_arg);
struct spdk_json_write_ctx;
/**

View File

@ -90,7 +90,7 @@ typedef void (*spdk_bdev_remove_cb_t)(void *remove_ctx);
/**
* Block device event callback.
*
* \param type Event type.
* \param event Event details.
* \param bdev Block device that triggered event.
* \param event_ctx Context for the block device event.
*/
@ -332,6 +332,23 @@ struct spdk_bdev *spdk_bdev_first_leaf(void);
*/
struct spdk_bdev *spdk_bdev_next_leaf(struct spdk_bdev *prev);
/**
* Open a block device for I/O operations (deprecated, please use spdk_bdev_open_ext).
*
* \param bdev Block device to open.
* \param write true is read/write access requested, false if read-only
* \param remove_cb notification callback to be called when the bdev gets
* hotremoved. This will always be called on the same thread that
* spdk_bdev_open() was called on. It can be NULL, in which case the upper
* layer won't be notified about the bdev hotremoval. The descriptor will
* have to be manually closed to make the bdev unregister proceed.
* \param remove_ctx param for remove_cb.
* \param desc output parameter for the descriptor when operation is successful
* \return 0 if operation is successful, suitable errno value otherwise
*/
int spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb,
void *remove_ctx, struct spdk_bdev_desc **desc);
/**
* Open a block device for I/O operations.
*
@ -339,7 +356,7 @@ struct spdk_bdev *spdk_bdev_next_leaf(struct spdk_bdev *prev);
* \param write true is read/write access requested, false if read-only
* \param event_cb notification callback to be called when the bdev triggers
* asynchronous event such as bdev removal. This will always be called on the
* same thread that spdk_bdev_open_ext() was called on. In case of removal event
* same thread that spdk_bdev_open() was called on. In case of removal event
* the descriptor will have to be manually closed to make the bdev unregister
* proceed.
* \param event_ctx param for event_cb.
@ -352,7 +369,7 @@ int spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t e
/**
* Close a previously opened block device.
*
* Must be called on the same thread that the spdk_bdev_open_ext()
* Must be called on the same thread that the spdk_bdev_open()
* was performed on.
*
* \param desc Block device descriptor to close.

View File

@ -85,6 +85,13 @@ struct spdk_bdev_module {
*/
void (*module_fini)(void);
/**
* Function called to return a text string representing the
* module's configuration options for inclusion in a configuration file.
* (Deprecated and shall not be called by bdev layer)
*/
void (*config_text)(FILE *fp);
/**
* Function called to return a text string representing the module-level
* JSON RPCs required to regenerate the current configuration. This will
@ -361,21 +368,11 @@ struct spdk_bdev {
*/
uint64_t zone_size;
/**
* Maximum zone append data transfer size (in blocks).
*/
uint32_t max_zone_append_size;
/**
* Maximum number of open zones.
*/
uint32_t max_open_zones;
/**
* Maximum number of active zones.
*/
uint32_t max_active_zones;
/**
* Optimal number of open zones.
*/
@ -737,6 +734,25 @@ void spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn,
*/
void spdk_bdev_destruct_done(struct spdk_bdev *bdev, int bdeverrno);
/**
* Register a virtual bdev.
*
* This function is deprecated. Users should call spdk_bdev_register instead.
* The bdev layer currently makes no use of the base_bdevs array, so switching
* to spdk_bdev_register results in no loss of functionality.
*
* \param vbdev Virtual bdev to register.
* \param base_bdevs Array of bdevs upon which this vbdev is based.
* \param base_bdev_count Number of bdevs in base_bdevs.
*
* \return 0 on success
* \return -EINVAL if the bdev name is NULL.
* \return -EEXIST if the bdev already exists.
* \return -ENOMEM if allocation of the base_bdevs array or the base bdevs vbdevs array fails.
*/
int spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs,
int base_bdev_count);
/**
* Indicate to the bdev layer that the module is done examining a bdev.
*
@ -1096,6 +1112,35 @@ int spdk_bdev_part_free(struct spdk_bdev_part *part);
void spdk_bdev_part_base_hotremove(struct spdk_bdev_part_base *part_base,
struct bdev_part_tailq *tailq);
/**
* Construct a new spdk_bdev_part_base on top of the provided bdev
* (deprecated. please use spdk_bdev_part_base_construct_ext).
*
* \param bdev The spdk_bdev upon which this base will be built.
* \param remove_cb Function to be called upon hotremove of the bdev.
* \param module The module to which this bdev base belongs.
* \param fn_table Function table for communicating with the bdev backend.
* \param tailq The head of the list of all spdk_bdev_part structures registered to this base's module.
* \param free_fn User provided function to free base related context upon bdev removal or shutdown.
* \param ctx Module specific context for this bdev part base.
* \param channel_size Channel size in bytes.
* \param ch_create_cb Called after a new channel is allocated.
* \param ch_destroy_cb Called upon channel deletion.
*
* \return The part object on top of the bdev if operation is successful, or
* NULL otherwise.
*/
struct spdk_bdev_part_base *spdk_bdev_part_base_construct(struct spdk_bdev *bdev,
spdk_bdev_remove_cb_t remove_cb,
struct spdk_bdev_module *module,
struct spdk_bdev_fn_table *fn_table,
struct bdev_part_tailq *tailq,
spdk_bdev_part_base_free_fn free_fn,
void *ctx,
uint32_t channel_size,
spdk_io_channel_create_cb ch_create_cb,
spdk_io_channel_destroy_cb ch_destroy_cb);
/**
* Construct a new spdk_bdev_part_base on top of the provided bdev.
*

View File

@ -53,20 +53,16 @@ enum spdk_bdev_zone_action {
SPDK_BDEV_ZONE_CLOSE,
SPDK_BDEV_ZONE_FINISH,
SPDK_BDEV_ZONE_OPEN,
SPDK_BDEV_ZONE_RESET,
SPDK_BDEV_ZONE_OFFLINE,
SPDK_BDEV_ZONE_RESET
};
enum spdk_bdev_zone_state {
SPDK_BDEV_ZONE_STATE_EMPTY = 0x0,
SPDK_BDEV_ZONE_STATE_IMP_OPEN = 0x1,
/* OPEN is an alias for IMP_OPEN. OPEN is kept for backwards compatibility. */
SPDK_BDEV_ZONE_STATE_OPEN = SPDK_BDEV_ZONE_STATE_IMP_OPEN,
SPDK_BDEV_ZONE_STATE_FULL = 0x2,
SPDK_BDEV_ZONE_STATE_CLOSED = 0x3,
SPDK_BDEV_ZONE_STATE_READ_ONLY = 0x4,
SPDK_BDEV_ZONE_STATE_OFFLINE = 0x5,
SPDK_BDEV_ZONE_STATE_EXP_OPEN = 0x6,
SPDK_BDEV_ZONE_STATE_EMPTY,
SPDK_BDEV_ZONE_STATE_OPEN,
SPDK_BDEV_ZONE_STATE_FULL,
SPDK_BDEV_ZONE_STATE_CLOSED,
SPDK_BDEV_ZONE_STATE_READ_ONLY,
SPDK_BDEV_ZONE_STATE_OFFLINE
};
struct spdk_bdev_zone_info {
@ -84,30 +80,9 @@ struct spdk_bdev_zone_info {
*/
uint64_t spdk_bdev_get_zone_size(const struct spdk_bdev *bdev);
/**
* Get the number of zones for the given device.
*
* \param bdev Block device to query.
* \return The number of zones.
*/
uint64_t spdk_bdev_get_num_zones(const struct spdk_bdev *bdev);
/**
* Get device maximum zone append data transfer size in logical blocks.
*
* If this value is 0, there is no limit.
*
* \param bdev Block device to query.
* \return Maximum zone append data transfer size for this zoned device in logical blocks.
*/
uint32_t spdk_bdev_get_max_zone_append_size(const struct spdk_bdev *bdev);
/**
* Get device maximum number of open zones.
*
* An open zone is defined as a zone being in zone state
* SPDK_BDEV_ZONE_STATE_IMP_OPEN or SPDK_BDEV_ZONE_STATE_EXP_OPEN.
*
* If this value is 0, there is no limit.
*
* \param bdev Block device to query.
@ -115,20 +90,6 @@ uint32_t spdk_bdev_get_max_zone_append_size(const struct spdk_bdev *bdev);
*/
uint32_t spdk_bdev_get_max_open_zones(const struct spdk_bdev *bdev);
/**
* Get device maximum number of active zones.
*
* An active zone is defined as a zone being in zone state
* SPDK_BDEV_ZONE_STATE_IMP_OPEN, SPDK_BDEV_ZONE_STATE_EXP_OPEN or
* SPDK_BDEV_ZONE_STATE_CLOSED.
*
* If this value is 0, there is no limit.
*
* \param bdev Block device to query.
* \return Maximum number of active zones for this zoned device.
*/
uint32_t spdk_bdev_get_max_active_zones(const struct spdk_bdev *bdev);
/**
* Get device optimal number of open zones.
*
@ -168,7 +129,7 @@ int spdk_bdev_get_zone_info(struct spdk_bdev_desc *desc, struct spdk_io_channel
* \param desc Block device descriptor.
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
* \param zone_id First logical block of a zone.
* \param action Action to perform on a zone (open, close, reset, finish, offline).
* \param action Action to perform on a zone (open, close, reset, finish).
* \param cb Called when the request is complete.
* \param cb_arg Argument passed to cb.
*

View File

@ -127,7 +127,7 @@ typedef void (*spdk_blob_op_with_id_complete)(void *cb_arg, spdk_blob_id blobid,
* Blob operation completion callback with handle.
*
* \param cb_arg Callback argument.
* \param blb Handle to a blob.
* \param bs Handle to a blob.
* \param bserrno 0 if it completed successfully, or negative errno if it failed.
*/
typedef void (*spdk_blob_op_with_handle_complete)(void *cb_arg, struct spdk_blob *blb, int bserrno);

View File

@ -49,6 +49,27 @@ struct spdk_bs_dev;
struct spdk_bdev;
struct spdk_bdev_module;
/**
* Create a blobstore block device from a bdev (deprecated, please use spdk_bdev_create_bs_dev_ext).
*
* \param bdev Bdev to use.
* \param remove_cb Called when the block device is removed.
* \param remove_ctx Argument passed to function remove_cb.
*
* \return a pointer to the blobstore block device on success or NULL otherwise.
*/
struct spdk_bs_dev *spdk_bdev_create_bs_dev(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb,
void *remove_ctx);
/**
* Create a blobstore block device from the descriptor of a bdev (deprecated, please use spdk_bdev_create_bs_dev_ext).
*
* \param desc Descriptor of a bdev. spdk_bdev_open_ext() is recommended to get the desc.
*
* \return a pointer to the blobstore block device on success or NULL otherwise.
*/
struct spdk_bs_dev *spdk_bdev_create_bs_dev_from_desc(struct spdk_bdev_desc *desc);
/**
* Create a blobstore block device from a bdev.
*

View File

@ -112,10 +112,10 @@ typedef void (*fs_request_fn)(void *arg);
* This function will be invoked any time when the filesystem wants to pass a
* message to the main dispatch thread.
*
* \param fn A pointer to the request function.
* \param fs_request_fn A pointer to the request function.
* \param arg Argument to the request function.
*/
typedef void (*fs_send_request_fn)(fs_request_fn fn, void *arg);
typedef void (*fs_send_request_fn)(fs_request_fn, void *arg);
/**
* Initialize a spdk_blobfs_opts structure to the default option values.

View File

@ -76,15 +76,24 @@ struct spdk_env_opts {
const char *core_mask;
int shm_id;
int mem_channel;
int main_core;
union {
int main_core;
int master_core __attribute__((deprecated));
};
int mem_size;
bool no_pci;
bool hugepage_single_segments;
bool unlink_hugepage;
size_t num_pci_addr;
const char *hugedir;
struct spdk_pci_addr *pci_blocked;
struct spdk_pci_addr *pci_allowed;
union {
struct spdk_pci_addr *pci_blocked;
struct spdk_pci_addr *pci_blacklist __attribute__((deprecated));
};
union {
struct spdk_pci_addr *pci_allowed;
struct spdk_pci_addr *pci_whitelist __attribute__((deprecated));
};
const char *iova_mode;
uint64_t base_virtaddr;
@ -999,22 +1008,6 @@ void spdk_pci_device_detach(struct spdk_pci_device *device);
int spdk_pci_device_attach(struct spdk_pci_driver *driver, spdk_pci_enum_cb enum_cb,
void *enum_ctx, struct spdk_pci_addr *pci_address);
/**
* Allow the specified PCI device to be probed by the calling process.
*
* When using spdk_pci_enumerate(), only devices with allowed PCI addresses will
* be probed. By default, this is all PCI addresses, but the pci_allowed
* and pci_blocked environment options can override this behavior.
* This API enables the caller to allow a new PCI address that may have previously
* been blocked.
*
* \param pci_addr PCI address to allow
* \return 0 if successful
* \return -ENOMEM if environment-specific data structures cannot be allocated
* \return -EINVAL if specified PCI address is not valid
*/
int spdk_pci_device_allow(struct spdk_pci_addr *pci_addr);
/**
* Read \c len bytes from the PCI configuration space.
*
@ -1329,60 +1322,10 @@ int spdk_mem_reserve(void *vaddr, size_t len);
* \param vaddr Virtual address to get
* \param offset Virtual address's map offset to the file descriptor
*
* \return negative errno on failure, otherwise return the file descriptor
* \ return negative errno on failure, otherwise return the file descriptor
*/
int spdk_mem_get_fd_and_offset(void *vaddr, uint64_t *offset);
enum spdk_pci_event_type {
SPDK_UEVENT_ADD = 0,
SPDK_UEVENT_REMOVE = 1,
};
struct spdk_pci_event {
enum spdk_pci_event_type action;
struct spdk_pci_addr traddr;
};
typedef void (*spdk_pci_error_handler)(siginfo_t *info, void *ctx);
/**
* Begin listening for PCI bus events. This is used to detect hot-insert and
* hot-remove events. Once the system is listening, events may be retrieved
* by calling spdk_pci_get_event() periodically.
*
* \return negative errno on failure, otherwise, return a file descriptor
* that may be later passed to spdk_pci_get_event().
*/
int spdk_pci_event_listen(void);
/**
* Get the next PCI bus event.
*
* \param fd A file descriptor returned by spdk_pci_event_listen()
* \param event An event on the PCI bus
*
* \return Negative errno on failure. 0 for no event. A positive number
* when an event has been returned
*/
int spdk_pci_get_event(int fd, struct spdk_pci_event *event);
/**
* Register a signal handler to handle bus errors on the PCI bus
*
* \param sighandler Signal bus handler of the PCI bus
* \param ctx The arg pass to the registered signal bus handler.
*
* \return negative errno on failure, otherwise it means successful
*/
int spdk_pci_register_error_handler(spdk_pci_error_handler sighandler, void *ctx);
/**
* Register a signal handler to handle bus errors on the PCI bus
*
* \param sighandler Signal bus handler of the PCI bus
*/
void spdk_pci_unregister_error_handler(spdk_pci_error_handler sighandler);
#ifdef __cplusplus
}
#endif

View File

@ -89,6 +89,7 @@ typedef void (*spdk_sighandler_t)(int signal);
*/
struct spdk_app_opts {
const char *name;
const char *config_file; /* deprecated */
const char *json_config_file;
bool json_config_ignore_errors;
const char *rpc_addr; /* Can be UNIX domain socket path or IP address + TCP port */
@ -101,7 +102,10 @@ struct spdk_app_opts {
bool enable_coredump;
int mem_channel;
int main_core;
union {
int main_core;
int master_core __attribute__((deprecated));
};
int mem_size;
bool no_pci;
bool hugepage_single_segments;
@ -109,10 +113,25 @@ struct spdk_app_opts {
const char *hugedir;
enum spdk_log_level print_level;
size_t num_pci_addr;
struct spdk_pci_addr *pci_blocked;
struct spdk_pci_addr *pci_allowed;
union {
struct spdk_pci_addr *pci_blocked;
struct spdk_pci_addr *pci_blacklist __attribute__((deprecated));
};
union {
struct spdk_pci_addr *pci_allowed;
struct spdk_pci_addr *pci_whitelist __attribute__((deprecated));
};
const char *iova_mode;
/* DEPRECATED. No longer has any effect.
*
* The maximum latency allowed when passing an event
* from one core to another. A value of 0
* means all cores continually poll. This is
* specified in microseconds.
*/
uint64_t max_delay_us;
/* Wait for the associated RPC before initializing subsystems
* when this flag is enabled.
*/

View File

@ -64,7 +64,7 @@ struct idxd_batch;
/**
* Signature for configuring a channel
*
* \param chan IDXD channel to be configured
* \param chan IDXD channel to be configured.
* \return 0 on success, negative errno on failure.
*/
int spdk_idxd_configure_chan(struct spdk_idxd_io_channel *chan);
@ -73,9 +73,10 @@ int spdk_idxd_configure_chan(struct spdk_idxd_io_channel *chan);
* Reconfigures this channel based on how many current channels there are.
*
* \param chan IDXD channel to be set.
* \param num_channels total number of channels in use.
* \return 0 on success, negative errno on failure.
*/
int spdk_idxd_reconfigure_chan(struct spdk_idxd_io_channel *chan);
int spdk_idxd_reconfigure_chan(struct spdk_idxd_io_channel *chan, uint32_t num_channels);
/**
* Signature for callback function invoked when a request is completed.
@ -391,9 +392,8 @@ int spdk_idxd_submit_crc32c(struct spdk_idxd_io_channel *chan, uint32_t *dst, vo
* Check for completed requests on an IDXD channel.
*
* \param chan IDXD channel to check for completions.
* \return number of operations completed.
*/
int spdk_idxd_process_events(struct spdk_idxd_io_channel *chan);
void spdk_idxd_process_events(struct spdk_idxd_io_channel *chan);
/**
* Returns an IDXD channel for a given IDXD device.
@ -408,17 +408,8 @@ struct spdk_idxd_io_channel *spdk_idxd_get_channel(struct spdk_idxd_device *idxd
* Free an IDXD channel.
*
* \param chan IDXD channel to free.
* \return true if the underlying device needs a rebalance
*/
bool spdk_idxd_put_channel(struct spdk_idxd_io_channel *chan);
/**
* Determine if the idxd device needs rebalancing.
*
* \param idxd IDXD device.
* \return true if rebalance is needed, false if not.
*/
bool spdk_idxd_device_needs_rebalance(struct spdk_idxd_device *idxd);
void spdk_idxd_put_channel(struct spdk_idxd_io_channel *chan);
#ifdef __cplusplus
}

View File

@ -82,7 +82,7 @@ struct spdk_jsonrpc_client_response {
*
* \param request JSON-RPC request to handle.
* \param method Function to handle the request.
* \param params Parameters passed to the function 'method'.
* \param param Parameters passed to the function 'method'.
*/
typedef void (*spdk_jsonrpc_handle_request_fn)(
struct spdk_jsonrpc_request *request,

View File

@ -2,7 +2,7 @@
* BSD LICENSE
*
* Copyright (c) Intel Corporation. All rights reserved.
* Copyright (c) 2019-2021 Mellanox Technologies LTD. All rights reserved.
* Copyright (c) 2019, 2020 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
@ -258,36 +258,6 @@ struct spdk_nvme_ctrlr_opts {
uint64_t fabrics_connect_timeout_us;
};
/**
* NVMe acceleration operation callback.
*
* \param cb_arg The user provided arg which is passed to the corresponding accelerated function call
* defined in struct spdk_nvme_accel_fn_table.
* \param status 0 if it completed successfully, or negative errno if it failed.
*/
typedef void (*spdk_nvme_accel_completion_cb)(void *cb_arg, int status);
/**
* Function table for the NVMe acccelerator device.
*
* This table provides a set of APIs to allow user to leverage
* accelerator functions.
*/
struct spdk_nvme_accel_fn_table {
/**
* The size of spdk_nvme_accel_fun_table according to the caller of
* this library is used for ABI compatibility. The library uses this
* field to know how many fields in this structure are valid.
* And the library will populate any remaining fields with default values.
* Newly added fields should be put at the end of the struct.
*/
size_t table_size;
/** The accelerated crc32c function. */
void (*submit_accel_crc32c)(void *ctx, uint32_t *dst, struct iovec *iov,
uint32_t iov_cnt, uint32_t seed, spdk_nvme_accel_completion_cb cb_fn, void *cb_arg);
};
/**
* Indicate whether a ctrlr handle is associated with a Discovery controller.
*
@ -450,44 +420,6 @@ struct spdk_nvme_host_id {
char hostsvcid[SPDK_NVMF_TRSVCID_MAX_LEN + 1];
};
struct spdk_nvme_rdma_device_stat {
const char *name;
uint64_t polls;
uint64_t idle_polls;
uint64_t completions;
uint64_t queued_requests;
uint64_t total_send_wrs;
uint64_t send_doorbell_updates;
uint64_t total_recv_wrs;
uint64_t recv_doorbell_updates;
};
struct spdk_nvme_pcie_stat {
uint64_t polls;
uint64_t idle_polls;
uint64_t completions;
uint64_t cq_doorbell_updates;
uint64_t submitted_requests;
uint64_t queued_requests;
uint64_t sq_doobell_updates;
};
struct spdk_nvme_transport_poll_group_stat {
spdk_nvme_transport_type_t trtype;
union {
struct {
uint32_t num_devices;
struct spdk_nvme_rdma_device_stat *device_stats;
} rdma;
struct spdk_nvme_pcie_stat pcie;
};
};
struct spdk_nvme_poll_group_stat {
uint32_t num_transports;
struct spdk_nvme_transport_poll_group_stat **transport_stat;
};
/*
* Controller support flags
*
@ -725,24 +657,6 @@ typedef void (*spdk_nvme_attach_cb)(void *cb_ctx, const struct spdk_nvme_transpo
*/
typedef void (*spdk_nvme_remove_cb)(void *cb_ctx, struct spdk_nvme_ctrlr *ctrlr);
typedef bool (*spdk_nvme_pcie_hotplug_filter_cb)(const struct spdk_pci_addr *addr);
/**
* Register the associated function to allow filtering of hot-inserted PCIe SSDs.
*
* If an application is using spdk_nvme_probe() to detect hot-inserted SSDs,
* this function may be used to register a function to filter those SSDs.
* If the filter function returns true, the nvme library will notify the SPDK
* env layer to allow probing of the device.
*
* Registering a filter function is optional. If none is registered, the nvme
* library will allow probing of all hot-inserted SSDs.
*
* \param filter_cb Filter function callback routine
*/
void
spdk_nvme_pcie_set_hotplug_filter(spdk_nvme_pcie_hotplug_filter_cb filter_cb);
/**
* Enumerate the bus indicated by the transport ID and attach the userspace NVMe
* driver to each device found if desired.
@ -1085,24 +999,6 @@ union spdk_nvme_vs_register spdk_nvme_ctrlr_get_regs_vs(struct spdk_nvme_ctrlr *
*/
union spdk_nvme_cmbsz_register spdk_nvme_ctrlr_get_regs_cmbsz(struct spdk_nvme_ctrlr *ctrlr);
/**
* Get the NVMe controller PMRCAP (Persistent Memory Region Capabilities) register.
*
* \param ctrlr Opaque handle to NVMe controller.
*
* \return the NVMe controller PMRCAP (Persistent Memory Region Capabilities) register.
*/
union spdk_nvme_pmrcap_register spdk_nvme_ctrlr_get_regs_pmrcap(struct spdk_nvme_ctrlr *ctrlr);
/**
* Get the NVMe controller PMR size.
*
* \param ctrlr Opaque handle to NVMe controller.
*
* \return the NVMe controller PMR size or 0 if PMR is not supported.
*/
uint64_t spdk_nvme_ctrlr_get_pmrsz(struct spdk_nvme_ctrlr *ctrlr);
/**
* Get the number of namespaces for the given NVMe controller.
*
@ -1215,21 +1111,21 @@ bool spdk_nvme_ctrlr_is_feature_supported(struct spdk_nvme_ctrlr *ctrlr, uint8_t
/**
* Signature for callback function invoked when a command is completed.
*
* \param ctx Callback context provided when the command was submitted.
* \param cpl Completion queue entry that contains the completion status.
* \param spdk_nvme_cpl Completion queue entry that coontains the completion status.
*/
typedef void (*spdk_nvme_cmd_cb)(void *ctx, const struct spdk_nvme_cpl *cpl);
typedef void (*spdk_nvme_cmd_cb)(void *, const struct spdk_nvme_cpl *);
/**
* Signature for callback function invoked when an asynchronous error request
* command is completed.
*
* \param ctrlr Opaque handle to NVMe controller.
* \param aer_cb_arg Context specified by spdk_nvme_register_aer_callback().
* \param cpl Completion queue entry that contains the completion status
* \param spdk_nvme_cpl Completion queue entry that contains the completion status
* of the asynchronous event request that was completed.
*/
typedef void (*spdk_nvme_aer_cb)(void *aer_cb_arg,
const struct spdk_nvme_cpl *cpl);
const struct spdk_nvme_cpl *);
/**
* Register callback function invoked when an AER command is completed for the
@ -1487,8 +1383,7 @@ spdk_nvme_qp_failure_reason spdk_nvme_ctrlr_get_admin_qp_failure_reason(
*
* \param qpair I/O queue pair to free.
*
* \return 0 on success, -1 on failure. On failure, the caller should reset
* the controller and try to free the io qpair again after the reset.
* \return 0 on success, -1 on failure.
*/
int spdk_nvme_ctrlr_free_io_qpair(struct spdk_nvme_qpair *qpair);
@ -2236,56 +2131,6 @@ void *spdk_nvme_ctrlr_map_cmb(struct spdk_nvme_ctrlr *ctrlr, size_t *size);
*/
void spdk_nvme_ctrlr_unmap_cmb(struct spdk_nvme_ctrlr *ctrlr);
/**
* Enable the Persistent Memory Region
*
* \param ctrlr Controller that contains the Persistent Memory Region
*
* \return 0 on success. Negated errno on the following error conditions:
* -ENOTSUP: PMR is not supported by the Controller.
* -EIO: Registers access failure.
* -EINVAL: PMR Time Units Invalid or PMR is already enabled.
* -ETIMEDOUT: Timed out to Enable PMR.
* -ENOSYS: Transport does not support Enable PMR function.
*/
int spdk_nvme_ctrlr_enable_pmr(struct spdk_nvme_ctrlr *ctrlr);
/**
* Disable the Persistent Memory Region
*
* \param ctrlr Controller that contains the Persistent Memory Region
*
* \return 0 on success. Negated errno on the following error conditions:
* -ENOTSUP: PMR is not supported by the Controller.
* -EIO: Registers access failure.
* -EINVAL: PMR Time Units Invalid or PMR is already disabled.
* -ETIMEDOUT: Timed out to Disable PMR.
* -ENOSYS: Transport does not support Disable PMR function.
*/
int spdk_nvme_ctrlr_disable_pmr(struct spdk_nvme_ctrlr *ctrlr);
/**
* Map the Persistent Memory Region so that it's data is
* visible from the CPU.
*
* \param ctrlr Controller that contains the Persistent Memory Region
* \param size Size of the region that was mapped.
*
* \return Pointer to Persistent Memory Region, or NULL on failure.
*/
void *spdk_nvme_ctrlr_map_pmr(struct spdk_nvme_ctrlr *ctrlr, size_t *size);
/**
* Free the Persistent Memory Region.
*
* \param ctrlr Controller from which to unmap the Persistent Memory Region.
*
* \return 0 on success, negative errno on failure.
* -ENXIO: Either PMR is not supported by the Controller or the PMR is already unmapped.
* -ENOSYS: Transport does not support Unmap PMR function.
*/
int spdk_nvme_ctrlr_unmap_pmr(struct spdk_nvme_ctrlr *ctrlr);
/**
* Get the transport ID for a given NVMe controller.
*
@ -2336,22 +2181,10 @@ typedef void (*spdk_nvme_disconnected_qpair_cb)(struct spdk_nvme_qpair *qpair,
* Create a new poll group.
*
* \param ctx A user supplied context that can be retrieved later with spdk_nvme_poll_group_get_ctx
* \param table The call back table defined by users which contains the accelerated functions
* which can be used to accelerate some operations such as crc32c.
*
* \return Pointer to the new poll group, or NULL on error.
*/
struct spdk_nvme_poll_group *spdk_nvme_poll_group_create(void *ctx,
struct spdk_nvme_accel_fn_table *table);
/**
* Get a optimal poll group.
*
* \param qpair The qpair to get the optimal poll group.
*
* \return Pointer to the optimal poll group, or NULL if not found.
*/
struct spdk_nvme_poll_group *spdk_nvme_qpair_get_optimal_poll_group(struct spdk_nvme_qpair *qpair);
struct spdk_nvme_poll_group *spdk_nvme_poll_group_create(void *ctx);
/**
* Add an spdk_nvme_qpair to a poll group. qpairs may only be added to
@ -2412,28 +2245,6 @@ int64_t spdk_nvme_poll_group_process_completions(struct spdk_nvme_poll_group *gr
*/
void *spdk_nvme_poll_group_get_ctx(struct spdk_nvme_poll_group *group);
/**
* Retrieves transport statistics for the given poll group.
*
* Note: the structure returned by this function should later be freed with
* @b spdk_nvme_poll_group_free_stats function
*
* \param group Pointer to NVME poll group
* \param stats Double pointer to statistics to be filled by this function
* \return 0 on success or negated errno on failure
*/
int spdk_nvme_poll_group_get_stats(struct spdk_nvme_poll_group *group,
struct spdk_nvme_poll_group_stat **stats);
/**
* Frees poll group statistics retrieved using @b spdk_nvme_poll_group_get_stats function
*
* @param group Pointer to a poll group
* @param stat Pointer to statistics to be released
*/
void spdk_nvme_poll_group_free_stats(struct spdk_nvme_poll_group *group,
struct spdk_nvme_poll_group_stat *stat);
/**
* Get the identify namespace data as defined by the NVMe specification.
*
@ -2644,16 +2455,16 @@ enum spdk_nvme_csi spdk_nvme_ns_get_csi(const struct spdk_nvme_ns *ns);
* \brief Namespace command support flags.
*/
enum spdk_nvme_ns_flags {
SPDK_NVME_NS_DEALLOCATE_SUPPORTED = 1 << 0, /**< The deallocate command is supported */
SPDK_NVME_NS_FLUSH_SUPPORTED = 1 << 1, /**< The flush command is supported */
SPDK_NVME_NS_RESERVATION_SUPPORTED = 1 << 2, /**< The reservation command is supported */
SPDK_NVME_NS_WRITE_ZEROES_SUPPORTED = 1 << 3, /**< The write zeroes command is supported */
SPDK_NVME_NS_DPS_PI_SUPPORTED = 1 << 4, /**< The end-to-end data protection is supported */
SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED = 1 << 5, /**< The extended lba format is supported,
SPDK_NVME_NS_DEALLOCATE_SUPPORTED = 0x1, /**< The deallocate command is supported */
SPDK_NVME_NS_FLUSH_SUPPORTED = 0x2, /**< The flush command is supported */
SPDK_NVME_NS_RESERVATION_SUPPORTED = 0x4, /**< The reservation command is supported */
SPDK_NVME_NS_WRITE_ZEROES_SUPPORTED = 0x8, /**< The write zeroes command is supported */
SPDK_NVME_NS_DPS_PI_SUPPORTED = 0x10, /**< The end-to-end data protection is supported */
SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED = 0x20, /**< The extended lba format is supported,
metadata is transferred as a contiguous
part of the logical block that it is associated with */
SPDK_NVME_NS_WRITE_UNCORRECTABLE_SUPPORTED = 1 << 6, /**< The write uncorrectable command is supported */
SPDK_NVME_NS_COMPARE_SUPPORTED = 1 << 7, /**< The compare command is supported */
SPDK_NVME_NS_WRITE_UNCORRECTABLE_SUPPORTED = 0x40, /**< The write uncorrectable command is supported */
SPDK_NVME_NS_COMPARE_SUPPORTED = 0x80, /**< The compare command is supported */
};
/**
@ -3397,14 +3208,6 @@ void spdk_nvme_qpair_print_command(struct spdk_nvme_qpair *qpair,
void spdk_nvme_qpair_print_completion(struct spdk_nvme_qpair *qpair,
struct spdk_nvme_cpl *cpl);
/**
* \brief Gets the NVMe qpair ID for the specified qpair.
*
* \param qpair Pointer to the NVMe queue pair.
* \returns ID for the specified qpair.
*/
uint16_t spdk_nvme_qpair_get_id(struct spdk_nvme_qpair *qpair);
/**
* \brief Prints (SPDK_NOTICELOG) the contents of an NVMe submission queue entry (command).
*
@ -3531,21 +3334,6 @@ int spdk_nvme_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs,
uint32_t len, size_t mps,
void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len));
/**
* Map NVMe command data buffers sent from Virtual Machine to virtual addresses
*
*\param prv Opaque handle to gpa_to_vva callback
*\param cmd NVMe command
*\param iovs IO vectors used to point the data buffers in NVMe command
*\param max_iovcnt Maximum IO vectors that can be used
*\param len Total buffer length for the NVMe command
*\param mps Memory page size
*\param gpa_to_vva Callback to map memory from Guest Physical address to Virtual address
*/
int spdk_nvme_map_cmd(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, uint32_t max_iovcnt,
uint32_t len, size_t mps,
void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len));
/**
* Opaque handle for a transport poll group. Used by the transport function table.
*/
@ -3596,14 +3384,6 @@ struct spdk_nvme_transport_ops {
int (*ctrlr_unmap_cmb)(struct spdk_nvme_ctrlr *ctrlr);
int (*ctrlr_enable_pmr)(struct spdk_nvme_ctrlr *ctrlr);
int (*ctrlr_disable_pmr)(struct spdk_nvme_ctrlr *ctrlr);
void *(*ctrlr_map_pmr)(struct spdk_nvme_ctrlr *ctrlr, size_t *size);
int (*ctrlr_unmap_pmr)(struct spdk_nvme_ctrlr *ctrlr);
struct spdk_nvme_qpair *(*ctrlr_create_io_qpair)(struct spdk_nvme_ctrlr *ctrlr, uint16_t qid,
const struct spdk_nvme_io_qpair_opts *opts);
@ -3628,8 +3408,6 @@ struct spdk_nvme_transport_ops {
void (*admin_qpair_abort_aers)(struct spdk_nvme_qpair *qpair);
struct spdk_nvme_transport_poll_group *(*poll_group_create)(void);
struct spdk_nvme_transport_poll_group *(*qpair_get_optimal_poll_group)(
struct spdk_nvme_qpair *qpair);
int (*poll_group_add)(struct spdk_nvme_transport_poll_group *tgroup, struct spdk_nvme_qpair *qpair);
@ -3644,12 +3422,6 @@ struct spdk_nvme_transport_ops {
uint32_t completions_per_qpair, spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb);
int (*poll_group_destroy)(struct spdk_nvme_transport_poll_group *tgroup);
int (*poll_group_get_stats)(struct spdk_nvme_transport_poll_group *tgroup,
struct spdk_nvme_transport_poll_group_stat **stats);
void (*poll_group_free_stats)(struct spdk_nvme_transport_poll_group *tgroup,
struct spdk_nvme_transport_poll_group_stat *stats);
};
/**

View File

@ -109,10 +109,7 @@ union spdk_nvme_cap_register {
/** memory page size maximum */
uint32_t mpsmax : 4;
/** persistent memory region supported */
uint32_t pmrs : 1;
uint32_t reserved3 : 7;
uint32_t reserved3 : 8;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cap_register) == 8, "Incorrect size");
@ -302,139 +299,6 @@ union spdk_nvme_cmbsts_register {
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cmbsts_register) == 4, "Incorrect size");
union spdk_nvme_pmrcap_register {
uint32_t raw;
struct {
uint32_t reserved1 : 3;
/** read data support */
uint32_t rds : 1;
/** write data support */
uint32_t wds : 1;
/** base indicator register */
uint32_t bir : 3;
/**
* persistent memory region time units
* 00b: 500 milliseconds
* 01b: minutes
*/
uint32_t pmrtu : 2;
/** persistent memory region write barrier mechanisms */
uint32_t pmrwbm : 4;
uint32_t reserved2 : 2;
/** persistent memory region timeout */
uint32_t pmrto : 8;
/** controller memory space supported */
uint32_t cmss : 1;
uint32_t reserved3 : 7;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrcap_register) == 4, "Incorrect size");
union spdk_nvme_pmrctl_register {
uint32_t raw;
struct {
/** enable */
uint32_t en : 1;
uint32_t reserved : 31;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrctl_register) == 4, "Incorrect size");
union spdk_nvme_pmrsts_register {
uint32_t raw;
struct {
/** err */
uint32_t err : 8;
/** not ready */
uint32_t nrdy : 1;
/**
* health status
* 000b: Normal Operation
* 001b: Restore Error
* 010b: Read Only
* 011b: Unreliable
*/
uint32_t hsts : 3;
/** controller base address invalid */
uint32_t cbai : 1;
uint32_t reserved : 19;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrsts_register) == 4, "Incorrect size");
union spdk_nvme_pmrebs_register {
uint32_t raw;
struct {
/**
* pmr elasicity buffer size units
* 0h: Bytes
* 1h: 1 KiB
* 2h: 1 MiB
* 3h: 1 GiB
*/
uint32_t pmrszu : 4;
/** read bypass behavior */
uint32_t rbb : 1;
uint32_t reserved : 3;
/** pmr elasticity buffer size base */
uint32_t pmrwbz : 24;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrebs_register) == 4, "Incorrect size");
union spdk_nvme_pmrswtp_register {
uint32_t raw;
struct {
/**
* pmr sustained write throughput units
* 0h: Bytes per second
* 1h: 1 KiB / s
* 2h: 1 MiB / s
* 3h: 1 GiB / s
*/
uint32_t pmrswtu : 4;
uint32_t reserved : 4;
/** pmr sustained write throughput */
uint32_t pmrswtv : 24;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrswtp_register) == 4, "Incorrect size");
union spdk_nvme_pmrmscl_register {
uint32_t raw;
struct {
uint32_t reserved1 : 1;
/** controller memory space enable */
uint32_t cmse : 1;
uint32_t reserved2 : 10;
/** controller base address */
uint32_t cba : 20;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_pmrmscl_register) == 4, "Incorrect size");
/** Boot partition information */
union spdk_nvme_bpinfo_register {
uint32_t raw;
@ -523,29 +387,7 @@ struct spdk_nvme_registers {
/** controller memory buffer status */
union spdk_nvme_cmbsts_register cmbsts;
uint32_t reserved2[0x369];
/** persistent memory region capabilities */
union spdk_nvme_pmrcap_register pmrcap;
/** persistent memory region control */
union spdk_nvme_pmrctl_register pmrctl;
/** persistent memory region status */
union spdk_nvme_pmrsts_register pmrsts;
/** persistent memory region elasticity buffer size */
union spdk_nvme_pmrebs_register pmrebs;
/** persistent memory region sustained write throughput */
union spdk_nvme_pmrswtp_register pmrswtp;
/** persistent memory region memory space control lower */
union spdk_nvme_pmrmscl_register pmrmscl;
uint32_t pmrmscu; /* persistent memory region memory space control upper */
uint32_t reserved3[0x79];
uint32_t reserved3[0x3e9];
struct {
uint32_t sq_tdbl; /* submission queue tail doorbell */
@ -581,20 +423,6 @@ SPDK_STATIC_ASSERT(0x50 == offsetof(struct spdk_nvme_registers, cmbmsc),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0x58 == offsetof(struct spdk_nvme_registers, cmbsts),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE00 == offsetof(struct spdk_nvme_registers, pmrcap),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE04 == offsetof(struct spdk_nvme_registers, pmrctl),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE08 == offsetof(struct spdk_nvme_registers, pmrsts),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE0C == offsetof(struct spdk_nvme_registers, pmrebs),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE10 == offsetof(struct spdk_nvme_registers, pmrswtp),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE14 == offsetof(struct spdk_nvme_registers, pmrmscl),
"Incorrect register offset");
SPDK_STATIC_ASSERT(0xE18 == offsetof(struct spdk_nvme_registers, pmrmscu),
"Incorrect register offset");
enum spdk_nvme_sgl_descriptor_type {
SPDK_NVME_SGL_TYPE_DATA_BLOCK = 0x0,
@ -884,14 +712,13 @@ union spdk_nvme_feat_async_event_configuration {
uint32_t raw;
struct {
union spdk_nvme_critical_warning_state crit_warn;
uint8_t ns_attr_notice : 1;
uint8_t fw_activation_notice : 1;
uint8_t telemetry_log_notice : 1;
uint8_t ana_change_notice : 1;
uint8_t reserved1 : 4;
uint16_t reserved2 : 15;
uint32_t ns_attr_notice : 1;
uint32_t fw_activation_notice : 1;
uint32_t telemetry_log_notice : 1;
uint32_t ana_change_notice : 1;
uint32_t reserved : 19;
/** Discovery log change (refer to the NVMe over Fabrics specification) */
uint16_t discovery_log_change_notice : 1;
uint32_t discovery_log_change_notice : 1;
} bits;
};
SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_feat_async_event_configuration) == 4, "Incorrect size");
@ -1283,7 +1110,7 @@ struct spdk_nvme_status {
uint16_t p : 1; /* phase tag */
uint16_t sc : 8; /* status code */
uint16_t sct : 3; /* status code type */
uint16_t crd : 2; /* command retry delay */
uint16_t rsvd2 : 2;
uint16_t m : 1; /* more */
uint16_t dnr : 1; /* do not retry */
};
@ -1587,12 +1414,6 @@ spdk_nvme_bytes_to_numd(uint32_t len)
return (len >> 2) - 1;
}
struct __attribute__((packed)) spdk_nvme_host_behavior {
uint8_t acre;
uint8_t reserved[511];
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_host_behavior) == 512, "Incorrect size");
enum spdk_nvme_feat {
/* 0x00 - reserved */
@ -1630,14 +1451,6 @@ enum spdk_nvme_feat {
/** cdw11 layout defined by \ref spdk_nvme_feat_non_operational_power_state_config */
SPDK_NVME_FEAT_NON_OPERATIONAL_POWER_STATE_CONFIG = 0x11,
SPDK_NVME_FEAT_READ_RECOVERY_LEVEL_CONFIG = 0x12,
SPDK_NVME_FEAT_PREDICTABLE_LATENCY_MODE_CONFIG = 0x13,
SPDK_NVME_FEAT_PREDICTABLE_LATENCY_MODE_WINDOW = 0x14,
SPDK_NVME_FEAT_LBA_STATUS_INFORMATION_ATTRIBUTES = 0x15,
/** data buffer layout defined by \ref spdk_nvme_host_behavior */
SPDK_NVME_FEAT_HOST_BEHAVIOR_SUPPORT = 0x16,
SPDK_NVME_FEAT_SANITIZE_CONFIG = 0x17,
SPDK_NVME_FEAT_ENDURANCE_GROUP_EVENT = 0x18,
/* 0x12-0x77 - reserved */
/* 0x78-0x7F - NVMe-MI features */
@ -1908,10 +1721,7 @@ struct __attribute__((packed)) __attribute__((aligned)) spdk_nvme_ctrlr_data {
/** FRU globally unique identifier */
uint8_t fguid[16];
/** Command Retry Delay Time 1, 2 and 3 */
uint16_t crdt[3];
uint8_t reserved_122[122];
uint8_t reserved_128[128];
/* bytes 256-511: admin command set attributes */
@ -2312,10 +2122,7 @@ struct spdk_nvme_ns_data {
/** Non-zero NGUID and EUI64 for namespace are never reused */
uint8_t guid_never_reused : 1;
/** Optimal Performance field */
uint8_t optperf : 1;
uint8_t reserved1 : 3;
uint8_t reserved1 : 4;
} nsfeat;
/** number of lba formats */
@ -2464,22 +2271,7 @@ struct spdk_nvme_ns_data {
/** NVM capacity */
uint64_t nvmcap[2];
/** Namespace Preferred Write Granularity */
uint16_t npwg;
/** Namespace Preferred Write Alignment */
uint16_t npwa;
/** Namespace Preferred Deallocate Granularity */
uint16_t npdg;
/** Namespace Preferred Deallocate Alignment */
uint16_t npda;
/** Namespace Optimal Write Size */
uint16_t nows;
uint8_t reserved64[18];
uint8_t reserved64[28];
/** ANA group identifier */
uint32_t anagrpid;

View File

@ -60,18 +60,6 @@ extern "C" {
*/
const struct spdk_nvme_zns_ns_data *spdk_nvme_zns_ns_get_data(struct spdk_nvme_ns *ns);
/**
* Get the zone size, in number of sectors, of the given namespace.
*
* This function is thread safe and can be called at any point while the controller
* is attached to the SPDK NVMe driver.
*
* \param ns Namespace to query.
*
* \return the zone size of the given namespace in number of sectors.
*/
uint64_t spdk_nvme_zns_ns_get_zone_size_sectors(struct spdk_nvme_ns *ns);
/**
* Get the zone size, in bytes, of the given namespace.
*
@ -96,40 +84,6 @@ uint64_t spdk_nvme_zns_ns_get_zone_size(struct spdk_nvme_ns *ns);
*/
uint64_t spdk_nvme_zns_ns_get_num_zones(struct spdk_nvme_ns *ns);
/**
* Get the maximum number of open zones for the given namespace.
*
* An open zone is a zone in any of the zone states:
* EXPLICIT OPEN or IMPLICIT OPEN.
*
* If this value is 0, there is no limit.
*
* This function is thread safe and can be called at any point while the controller
* is attached to the SPDK NVMe driver.
*
* \param ns Namespace to query.
*
* \return the maximum number of open zones.
*/
uint32_t spdk_nvme_zns_ns_get_max_open_zones(struct spdk_nvme_ns *ns);
/**
* Get the maximum number of active zones for the given namespace.
*
* An active zone is a zone in any of the zone states:
* EXPLICIT OPEN, IMPLICIT OPEN or CLOSED.
*
* If this value is 0, there is no limit.
*
* This function is thread safe and can be called at any point while the controller
* is attached to the SPDK NVMe driver.
*
* \param ns Namespace to query.
*
* \return the maximum number of active zones.
*/
uint32_t spdk_nvme_zns_ns_get_max_active_zones(struct spdk_nvme_ns *ns);
/**
* Get the Zoned Namespace Command Set Specific Identify Controller data
* as defined by the NVMe Zoned Namespace Command Set Specification.
@ -160,11 +114,11 @@ uint32_t spdk_nvme_zns_ctrlr_get_max_zone_append_size(const struct spdk_nvme_ctr
* The user must ensure that only one thread submits I/O on a given qpair at any
* given time.
*
* \param ns NVMe namespace to submit the zone append I/O.
* \param ns NVMe namespace to submit the write I/O.
* \param qpair I/O queue pair to submit the request.
* \param buffer Virtual address pointer to the data payload buffer.
* \param zslba Zone Start LBA of the zone that we are appending to.
* \param lba_count Length (in sectors) for the zone append operation.
* \param lba_count Length (in sectors) for the write operation.
* \param cb_fn Callback function to invoke when the I/O is completed.
* \param cb_arg Argument to pass to the callback function.
* \param io_flags Set flags, defined by the SPDK_NVME_IO_FLAGS_* entries in
@ -187,13 +141,13 @@ int spdk_nvme_zns_zone_append(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *q
* The user must ensure that only one thread submits I/O on a given qpair at any
* given time.
*
* \param ns NVMe namespace to submit the zone append I/O.
* \param ns NVMe namespace to submit the write I/O.
* \param qpair I/O queue pair to submit the request.
* \param buffer Virtual address pointer to the data payload buffer.
* \param metadata Virtual address pointer to the metadata payload, the length
* of metadata is specified by spdk_nvme_ns_get_md_size().
* \param zslba Zone Start LBA of the zone that we are appending to.
* \param lba_count Length (in sectors) for the zone append operation.
* \param lba_count Length (in sectors) for the write operation.
* \param cb_fn Callback function to invoke when the I/O is completed.
* \param cb_arg Argument to pass to the callback function.
* \param io_flags Set flags, defined by the SPDK_NVME_IO_FLAGS_* entries in
@ -211,69 +165,6 @@ int spdk_nvme_zns_zone_append_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_
uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag);
/**
* Submit a zone append I/O to the specified NVMe namespace.
*
* The command is submitted to a qpair allocated by spdk_nvme_ctrlr_alloc_io_qpair().
* The user must ensure that only one thread submits I/O on a given qpair at any
* given time.
*
* \param ns NVMe namespace to submit the zone append I/O.
* \param qpair I/O queue pair to submit the request.
* \param zslba Zone Start LBA of the zone that we are appending to.
* \param lba_count Length (in sectors) for the zone append operation.
* \param cb_fn Callback function to invoke when the I/O is completed.
* \param cb_arg Argument to pass to the callback function.
* \param io_flags Set flags, defined in nvme_spec.h, for this I/O.
* \param reset_sgl_fn Callback function to reset scattered payload.
* \param next_sge_fn Callback function to iterate each scattered payload memory
* segment.
*
* \return 0 if successfully submitted, negated errnos on the following error conditions:
* -EINVAL: The request is malformed.
* -ENOMEM: The request cannot be allocated.
* -ENXIO: The qpair is failed at the transport level.
*/
int spdk_nvme_zns_zone_appendv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
uint64_t zslba, uint32_t lba_count,
spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
spdk_nvme_req_next_sge_cb next_sge_fn);
/**
* Submit a zone append I/O to the specified NVMe namespace.
*
* The command is submitted to a qpair allocated by spdk_nvme_ctrlr_alloc_io_qpair().
* The user must ensure that only one thread submits I/O on a given qpair at any
* given time.
*
* \param ns NVMe namespace to submit the zone append I/O.
* \param qpair I/O queue pair to submit the request.
* \param zslba Zone Start LBA of the zone that we are appending to.
* \param lba_count Length (in sectors) for the zone append operation.
* \param cb_fn Callback function to invoke when the I/O is completed.
* \param cb_arg Argument to pass to the callback function.
* \param io_flags Set flags, defined in nvme_spec.h, for this I/O.
* \param reset_sgl_fn Callback function to reset scattered payload.
* \param next_sge_fn Callback function to iterate each scattered payload memory
* segment.
* \param metadata Virtual address pointer to the metadata payload, the length
* of metadata is specified by spdk_nvme_ns_get_md_size().
* \param apptag_mask Application tag mask.
* \param apptag Application tag to use end-to-end protection information.
*
* \return 0 if successfully submitted, negated errnos on the following error conditions:
* -EINVAL: The request is malformed.
* -ENOMEM: The request cannot be allocated.
* -ENXIO: The qpair is failed at the transport level.
*/
int spdk_nvme_zns_zone_appendv_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
uint64_t zslba, uint32_t lba_count,
spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
uint16_t apptag_mask, uint16_t apptag);
/**
* Submit a Close Zone operation to the specified NVMe namespace.
*

View File

@ -2,7 +2,7 @@
* BSD LICENSE
*
* Copyright (c) Intel Corporation. All rights reserved.
* Copyright (c) 2018-2021 Mellanox Technologies LTD. All rights reserved.
* Copyright (c) 2018-2019 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
@ -76,7 +76,6 @@ struct spdk_nvmf_transport_opts {
uint16_t max_queue_depth;
uint16_t max_qpairs_per_ctrlr;
uint32_t in_capsule_data_size;
/* used to calculate mdts */
uint32_t max_io_size;
uint32_t io_unit_size;
uint32_t max_aq_depth;
@ -125,30 +124,17 @@ struct spdk_nvmf_poll_group_stat {
uint64_t pending_bdev_io;
};
/* Deprecated.
* Please use the flow with spdk_nvmf_poll_group_dump_stat,
* which hides statistics structures within the transport.
*/
struct spdk_nvmf_rdma_device_stat {
const char *name;
uint64_t polls;
uint64_t idle_polls;
uint64_t completions;
uint64_t requests;
uint64_t request_latency;
uint64_t pending_free_request;
uint64_t pending_rdma_read;
uint64_t pending_rdma_write;
uint64_t total_send_wrs;
uint64_t send_doorbell_updates;
uint64_t total_recv_wrs;
uint64_t recv_doorbell_updates;
};
/* Deprecated.
* Please use the flow with spdk_nvmf_poll_group_dump_stat,
* which hides statistics structures within the transport.
*/
struct spdk_nvmf_transport_poll_group_stat {
spdk_nvme_transport_type_t trtype;
union {
@ -242,6 +228,21 @@ struct spdk_nvmf_tgt *spdk_nvmf_get_next_tgt(struct spdk_nvmf_tgt *prev);
*/
void spdk_nvmf_tgt_write_config_json(struct spdk_json_write_ctx *w, struct spdk_nvmf_tgt *tgt);
/**
* Begin accepting new connections at the address provided (deprecated, please use spdk_nvmf_tgt_listen_ext).
*
* The connections will be matched with a subsystem, which may or may not allow
* the connection based on a subsystem-specific list of allowed hosts. See
* spdk_nvmf_subsystem_add_host() and spdk_nvmf_subsystem_add_listener()
*
* \param tgt The target associated with this listen address.
* \param trid The address to listen at.
*
* \return 0 on success or a negated errno on failure.
*/
int spdk_nvmf_tgt_listen(struct spdk_nvmf_tgt *tgt,
struct spdk_nvme_transport_id *trid);
/**
* Begin accepting new connections at the address provided.
*
@ -261,7 +262,7 @@ int spdk_nvmf_tgt_listen_ext(struct spdk_nvmf_tgt *tgt, const struct spdk_nvme_t
/**
* Stop accepting new connections at the provided address.
*
* This is a counterpart to spdk_nvmf_tgt_listen_ext().
* This is a counterpart to spdk_nvmf_tgt_listen().
*
* \param tgt The target associated with the listen address.
* \param trid The address to stop listening at.
@ -314,7 +315,7 @@ int spdk_nvmf_poll_group_add(struct spdk_nvmf_poll_group *group,
struct spdk_nvmf_qpair *qpair);
/**
* Get current poll group statistics. (deprecated)
* Get current poll group statistics.
*
* \param tgt The NVMf target.
* \param stat Pointer to allocated statistics structure to fill with values.
@ -408,7 +409,7 @@ void spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem);
/**
* Function to be called once the subsystem has changed state.
*
* \param subsystem NVMe-oF subsystem that has changed state.
* \param subsytem NVMe-oF subsystem that has changed state.
* \param cb_arg Argument passed to callback function.
* \param status 0 if it completed successfully, or negative errno if it failed.
*/
@ -617,7 +618,7 @@ const char *spdk_nvmf_host_get_nqn(const struct spdk_nvmf_host *host);
/**
* Accept new connections on the address provided.
*
* This does not start the listener. Use spdk_nvmf_tgt_listen_ext() for that.
* This does not start the listener. Use spdk_nvmf_tgt_listen() for that.
*
* May only be performed on subsystems in the PAUSED or INACTIVE states.
* No namespaces are required to be paused.
@ -771,6 +772,23 @@ struct spdk_nvmf_ns_opts {
*/
void spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size);
/**
* Add a namespace to a subsytem (deprecated, please use spdk_nvmf_subsystem_add_ns_ext).
*
* May only be performed on subsystems in the PAUSED or INACTIVE states.
*
* \param subsystem Subsystem to add namespace to.
* \param bdev Block device to add as a namespace.
* \param opts Namespace options, or NULL to use defaults.
* \param opts_size sizeof(*opts)
* \param ptpl_file Persist through power loss file path.
*
* \return newly added NSID on success, or 0 on failure.
*/
uint32_t spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev,
const struct spdk_nvmf_ns_opts *opts, size_t opts_size,
const char *ptpl_file);
/**
* Add a namespace to a subsystems in the PAUSED or INACTIVE states.
*
@ -1088,7 +1106,7 @@ spdk_nvmf_transport_stop_listen(struct spdk_nvmf_transport *transport,
/**
* Stop accepting new connections at the provided address.
*
* This is a counterpart to spdk_nvmf_tgt_listen_ext(). It differs
* This is a counterpart to spdk_nvmf_tgt_listen(). It differs
* from spdk_nvmf_transport_stop_listen() in that it also destroys all
* qpairs that are connected to the specified listener. Because
* this function disconnects the qpairs, it has to be asynchronous.
@ -1105,11 +1123,8 @@ int spdk_nvmf_transport_stop_listen_async(struct spdk_nvmf_transport *transport,
spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn,
void *cb_arg);
/**
* \brief Get current transport poll group statistics. (deprecated)
*
* Please use the flow with spdk_nvmf_poll_group_dump_stat.
* \brief Get current transport poll group statistics.
*
* This function allocates memory for statistics and returns it
* in \p stat parameter. Caller must free this memory with
@ -1132,9 +1147,7 @@ spdk_nvmf_transport_poll_group_get_stat(struct spdk_nvmf_tgt *tgt,
struct spdk_nvmf_transport_poll_group_stat **stat);
/**
* Free statistics memory previously allocated with spdk_nvmf_transport_poll_group_get_stat(). (deprecated)
*
* Please use the flow with spdk_nvmf_poll_group_dump_stat.
* Free statistics memory previously allocated with spdk_nvmf_transport_poll_group_get_stat().
*
* \param transport The NVMf transport.
* \param stat Pointer to transport poll group statistics structure.
@ -1143,15 +1156,6 @@ void
spdk_nvmf_transport_poll_group_free_stat(struct spdk_nvmf_transport *transport,
struct spdk_nvmf_transport_poll_group_stat *stat);
/**
* Dump poll group statistics into JSON.
*
* \param group The group which statistics should be dumped.
* \param w The JSON write context to which statistics should be dumped.
*/
void spdk_nvmf_poll_group_dump_stat(struct spdk_nvmf_poll_group *group,
struct spdk_json_write_ctx *w);
/**
* \brief Set the global hooks for the RDMA transport, if necessary.
*

View File

@ -48,7 +48,7 @@
#define SPDK_NVMF_MAX_SGL_ENTRIES 16
/* The maximum number of buffers per request */
#define NVMF_REQ_MAX_BUFFERS (SPDK_NVMF_MAX_SGL_ENTRIES * 2 + 1)
#define NVMF_REQ_MAX_BUFFERS (SPDK_NVMF_MAX_SGL_ENTRIES * 2)
/* AIO backend requires block size aligned data buffers,
* extra 4KiB aligned data buffer should work for most devices.
@ -368,23 +368,15 @@ struct spdk_nvmf_transport_ops {
struct spdk_nvmf_request *req);
/*
* Get transport poll group statistics. (deprecated)
* Please use the flow with spdk_nvmf_poll_group_dump_stat.
* Get transport poll group statistics
*/
int (*poll_group_get_stat)(struct spdk_nvmf_tgt *tgt,
struct spdk_nvmf_transport_poll_group_stat **stat);
/*
* Free transport poll group statistics previously allocated with poll_group_get_stat(). (deprecated)
* Please use the flow with spdk_nvmf_poll_group_dump_stat.
* Free transport poll group statistics previously allocated with poll_group_get_stat()
*/
void (*poll_group_free_stat)(struct spdk_nvmf_transport_poll_group_stat *stat);
/*
* Dump transport poll group statistics into JSON.
*/
void (*poll_group_dump_stat)(struct spdk_nvmf_transport_poll_group *group,
struct spdk_json_write_ctx *w);
};
/**

View File

@ -102,6 +102,8 @@ void spdk_opal_dev_destruct(struct spdk_opal_dev *dev);
struct spdk_opal_d0_features_info *spdk_opal_get_d0_features_info(struct spdk_opal_dev *dev);
__attribute__((__deprecated__)) bool spdk_opal_supported(struct spdk_opal_dev *dev);
int spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd);
/**

View File

@ -52,6 +52,7 @@ extern "C" {
#define SPDK_PCI_VID_VIRTIO 0x1af4
#define SPDK_PCI_VID_CNEXLABS 0x1d1d
#define SPDK_PCI_VID_VMWARE 0x15ad
#define SPDK_PCI_VID_REDHAT 0x1b36
#define SPDK_PCI_CLASS_ANY_ID 0xffffff
/**

View File

@ -105,6 +105,8 @@
*
*/
#include "spdk/util.h"
/*
* Singly-linked Tail queue declarations.
*/

View File

@ -80,13 +80,6 @@ struct spdk_sock_request {
#define SPDK_SOCK_REQUEST_IOV(req, i) ((struct iovec *)(((uint8_t *)req + sizeof(struct spdk_sock_request)) + (sizeof(struct iovec) * i)))
enum spdk_placement_mode {
PLACEMENT_NONE,
PLACEMENT_NAPI,
PLACEMENT_CPU,
PLACEMENT_MARK,
};
/**
* SPDK socket implementation options.
*
@ -111,7 +104,6 @@ struct spdk_sock_impl_opts {
bool enable_recv_pipe;
/**
* **Deprecated, please use enable_zerocopy_send_server or enable_zerocopy_send_client instead**
* Enable or disable use of zero copy flow on send. Used by posix socket module.
*/
bool enable_zerocopy_send;
@ -123,19 +115,9 @@ struct spdk_sock_impl_opts {
/**
* Enable or disable placement_id. Used by posix and uring socket modules.
* Valid values in the enum spdk_placement_mode.
*/
uint32_t enable_placement_id;
bool enable_placement_id;
/**
* Enable or disable use of zero copy flow on send for server sockets. Used by posix socket module.
*/
bool enable_zerocopy_send_server;
/**
* Enable or disable use of zero copy flow on send for client sockets. Used by posix socket module.
*/
bool enable_zerocopy_send_client;
};
/**

View File

@ -131,7 +131,7 @@ typedef int (*spdk_poller_fn)(void *ctx);
* \param thread_ctx Context for the thread.
* \param fn Callback function for a poller.
* \param arg Argument passed to callback.
* \param period_microseconds Polling period in microseconds.
* \param period Polling period in microseconds.
*
* \return a pointer to the poller on success, or NULL on failure.
*/
@ -148,30 +148,6 @@ typedef struct spdk_poller *(*spdk_start_poller)(void *thread_ctx,
*/
typedef void (*spdk_stop_poller)(struct spdk_poller *poller, void *thread_ctx);
/**
* Callback function to set poller into interrupt mode or back to poll mode.
*
* \param poller Poller to set interrupt or poll mode.
* \param cb_arg Argument passed to the callback function.
* \param interrupt_mode Set interrupt mode for true, or poll mode for false
*/
typedef void (*spdk_poller_set_interrupt_mode_cb)(struct spdk_poller *poller, void *cb_arg,
bool interrupt_mode);
/**
* Mark that the poller is capable of entering interrupt mode.
*
* When registering the poller set interrupt callback, the callback will get
* executed immediately if its spdk_thread is in the interrupt mode.
*
* \param poller The poller to register callback function.
* \param cb_fn Callback function called when the poller must transition into or out of interrupt mode
* \param cb_arg Argument passed to the callback function.
*/
void spdk_poller_register_interrupt(struct spdk_poller *poller,
spdk_poller_set_interrupt_mode_cb cb_fn,
void *cb_arg);
/**
* I/O channel creation callback.
*
@ -537,16 +513,6 @@ int spdk_thread_send_critical_msg(struct spdk_thread *thread, spdk_msg_fn fn);
*/
void spdk_for_each_thread(spdk_msg_fn fn, void *ctx, spdk_msg_fn cpl);
/**
* Set current spdk_thread into interrupt mode or back to poll mode.
*
* Only valid when thread interrupt facility is enabled by
* spdk_interrupt_mode_enable().
*
* \param enable_interrupt Set interrupt mode for true, or poll mode for false
*/
void spdk_thread_set_interrupt_mode(bool enable_interrupt);
/**
* Register a poller on the current thread.
*
@ -755,15 +721,6 @@ struct spdk_io_channel *spdk_io_channel_iter_get_channel(struct spdk_io_channel_
*/
void *spdk_io_channel_iter_get_ctx(struct spdk_io_channel_iter *i);
/**
* Get the io_device for the specified I/O channel.
*
* \param ch I/O channel.
*
* \return a pointer to the io_device for the I/O channel
*/
void *spdk_io_channel_get_io_device(struct spdk_io_channel *ch);
/**
* Helper function to iterate all channels for spdk_for_each_channel().
*

View File

@ -46,7 +46,7 @@
/**
* Minor version number (month of original release).
*/
#define SPDK_VERSION_MINOR 4
#define SPDK_VERSION_MINOR 1
/**
* Patch level.
@ -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 1
#define SPDK_VERSION_PATCH 2
/**
* Version string suffix.

View File

@ -80,26 +80,14 @@ struct spdk_accel_task {
struct spdk_accel_batch *batch;
spdk_accel_completion_cb cb_fn;
void *cb_arg;
union {
struct {
struct iovec *iovs; /* iovs passed by the caller */
uint32_t iovcnt; /* iovcnt passed by the caller */
} v;
void *src;
};
void *src;
union {
void *dst;
void *src2;
};
union {
struct {
spdk_accel_completion_cb cb_fn;
void *cb_arg;
} chained;
void *dst2;
uint32_t seed;
uint64_t fill_pattern;
};
void *dst2;
uint32_t seed;
uint64_t fill_pattern;
enum accel_opcode op_code;
uint64_t nbytes;
TAILQ_ENTRY(spdk_accel_task) link;

View File

@ -214,7 +214,7 @@ void spdk_app_json_config_load(const char *json_config_file, const char *rpc_add
*/
void spdk_subsystem_config_json(struct spdk_json_write_ctx *w, struct spdk_subsystem *subsystem);
int spdk_rpc_initialize(const char *listen_addr);
void spdk_rpc_initialize(const char *listen_addr);
void spdk_rpc_finish(void);
struct spdk_governor_capabilities {
@ -236,7 +236,7 @@ struct spdk_governor {
/* freqs - the buffer array to save the frequencies; num - the number of frequencies to get; return - the number of available frequencies */
uint32_t (*get_core_freqs)(uint32_t lcore_id, uint32_t *freqs, uint32_t num);
/* return - current frequency on success, 0 on failure */
/* return - current frequency */
uint32_t (*get_core_curr_freq)(uint32_t lcore_id);
/**

View File

@ -102,7 +102,6 @@ struct nvme_tcp_pdu {
bool has_hdgst;
bool ddgst_enable;
uint32_t header_digest_crc32;
uint32_t data_digest_crc32;
uint8_t data_digest[SPDK_NVME_TCP_DIGEST_LEN];
uint8_t ch_valid_bytes;
@ -619,12 +618,12 @@ nvme_tcp_pdu_calc_psh_len(struct nvme_tcp_pdu *pdu, bool hdgst_enable)
if (g_nvme_tcp_hdgst[pdu->hdr.common.pdu_type] && hdgst_enable) {
pdu->has_hdgst = true;
psh_len += SPDK_NVME_TCP_DIGEST_LEN;
}
if (pdu->hdr.common.plen > psh_len) {
pdo = pdu->hdr.common.pdo;
padding_len = pdo - psh_len;
if (padding_len > 0) {
psh_len = pdo;
if (pdu->hdr.common.plen > psh_len) {
pdo = pdu->hdr.common.pdo;
padding_len = pdo - psh_len;
if (padding_len > 0) {
psh_len = pdo;
}
}
}

View File

@ -41,18 +41,6 @@
/* Contains hooks definition */
#include "spdk/nvme.h"
struct spdk_rdma_wr_stats {
/* Total number of submitted requests */
uint64_t num_submitted_wrs;
/* Total number of doorbell updates */
uint64_t doorbell_updates;
};
struct spdk_rdma_qp_stats {
struct spdk_rdma_wr_stats send;
struct spdk_rdma_wr_stats recv;
};
struct spdk_rdma_qp_init_attr {
void *qp_context;
struct ibv_cq *send_cq;
@ -60,7 +48,6 @@ struct spdk_rdma_qp_init_attr {
struct ibv_srq *srq;
struct ibv_qp_cap cap;
struct ibv_pd *pd;
struct spdk_rdma_qp_stats *stats;
};
struct spdk_rdma_send_wr_list {
@ -68,18 +55,10 @@ struct spdk_rdma_send_wr_list {
struct ibv_send_wr *last;
};
struct spdk_rdma_recv_wr_list {
struct ibv_recv_wr *first;
struct ibv_recv_wr *last;
};
struct spdk_rdma_qp {
struct ibv_qp *qp;
struct rdma_cm_id *cm_id;
struct spdk_rdma_send_wr_list send_wrs;
struct spdk_rdma_recv_wr_list recv_wrs;
struct spdk_rdma_qp_stats *stats;
bool shared_stats;
};
struct spdk_rdma_mem_map;
@ -98,58 +77,10 @@ struct spdk_rdma_memory_translation {
union spdk_rdma_mr mr_or_key;
uint8_t translation_type;
};
struct spdk_rdma_srq_init_attr {
struct ibv_pd *pd;
struct spdk_rdma_wr_stats *stats;
struct ibv_srq_init_attr srq_init_attr;
};
struct spdk_rdma_srq {
struct ibv_srq *srq;
struct spdk_rdma_recv_wr_list recv_wrs;
struct spdk_rdma_wr_stats *stats;
bool shared_stats;
};
/**
* Create RDMA SRQ
*
* \param init_attr Pointer to SRQ init attr
* \return pointer to srq on success or NULL on failure. errno is updated in failure case.
*/
struct spdk_rdma_srq *spdk_rdma_srq_create(struct spdk_rdma_srq_init_attr *init_attr);
/**
* Destroy RDMA SRQ
*
* \param rdma_srq Pointer to SRQ
* \return 0 on succes, errno on failure
*/
int spdk_rdma_srq_destroy(struct spdk_rdma_srq *rdma_srq);
/**
* Append the given recv wr structure to the SRQ's outstanding recv list.
* This function accepts either a single Work Request or the first WR in a linked list.
*
* \param rdma_srq Pointer to SRQ
* \param first pointer to the first Work Request
* \return true if there were no outstanding WRs before, false otherwise
*/
bool spdk_rdma_srq_queue_recv_wrs(struct spdk_rdma_srq *rdma_srq, struct ibv_recv_wr *first);
/**
* Submit all queued receive Work Request
*
* \param rdma_srq Pointer to SRQ
* \param bad_wr Stores a pointer to the first failed WR if this function return nonzero value
* \return 0 on succes, errno on failure
*/
int spdk_rdma_srq_flush_recv_wrs(struct spdk_rdma_srq *rdma_srq, struct ibv_recv_wr **bad_wr);
/**
* Create RDMA provider specific qpair
*
* \param cm_id Pointer to RDMA_CM cm_id
* \param cm_id Pointer to RDMACM cm_id
* \param qp_attr Pointer to qpair init attributes
* \return Pointer to a newly created qpair on success or NULL on failure
*/
@ -158,8 +89,7 @@ struct spdk_rdma_qp *spdk_rdma_qp_create(struct rdma_cm_id *cm_id,
/**
* Accept a connection request. Called by the passive side (NVMEoF target)
*
* \param spdk_rdma_qp Pointer to SPDK RDMA qpair
* \param spdk_rdma_qp Pointer to a qpair
* \param conn_param Optional information needed to establish the connection
* \return 0 on success, errno on failure
*/
@ -168,24 +98,21 @@ int spdk_rdma_qp_accept(struct spdk_rdma_qp *spdk_rdma_qp, struct rdma_conn_para
/**
* Complete the connection process, must be called by the active
* side (NVMEoF initiator) upon receipt RDMA_CM_EVENT_CONNECT_RESPONSE
*
* \param spdk_rdma_qp Pointer to SPDK RDMA qpair
* \param spdk_rdma_qp Pointer to a qpair
* \return 0 on success, errno on failure
*/
int spdk_rdma_qp_complete_connect(struct spdk_rdma_qp *spdk_rdma_qp);
/**
* Destroy RDMA provider specific qpair
*
* \param spdk_rdma_qp Pointer to SPDK RDMA qpair to be destroyed
* \param spdk_rdma_qp Pointer to qpair to be destroyed
*/
void spdk_rdma_qp_destroy(struct spdk_rdma_qp *spdk_rdma_qp);
/**
* Disconnect a connection and transition associated qpair to error state.
* Disconnect a connection and transition assoiciated qpair to error state.
* Generates RDMA_CM_EVENT_DISCONNECTED on both connection sides
*
* \param spdk_rdma_qp Pointer to qpair to be disconnected
* \param spdk_rdma_qp Pointer to qpair to be destroyed
*/
int spdk_rdma_qp_disconnect(struct spdk_rdma_qp *spdk_rdma_qp);
@ -200,32 +127,13 @@ int spdk_rdma_qp_disconnect(struct spdk_rdma_qp *spdk_rdma_qp);
bool spdk_rdma_qp_queue_send_wrs(struct spdk_rdma_qp *spdk_rdma_qp, struct ibv_send_wr *first);
/**
* Submit all queued send Work Request
*
* Submit all queued Work Request
* \param spdk_rdma_qp Pointer to SPDK RDMA qpair
* \param bad_wr Stores a pointer to the first failed WR if this function return nonzero value
* \return 0 on succes, errno on failure
*/
int spdk_rdma_qp_flush_send_wrs(struct spdk_rdma_qp *spdk_rdma_qp, struct ibv_send_wr **bad_wr);
/**
* Append the given recv wr structure to the qpair's outstanding recv list.
* This function accepts either a single Work Request or the first WR in a linked list.
*
* \param spdk_rdma_qp Pointer to SPDK RDMA qpair
* \param first Pointer to the first Work Request
* \return true if there were no outstanding WRs before, false otherwise
*/
bool spdk_rdma_qp_queue_recv_wrs(struct spdk_rdma_qp *spdk_rdma_qp, struct ibv_recv_wr *first);
/**
* Submit all queued recv Work Request
* \param spdk_rdma_qp Pointer to SPDK RDMA qpair
* \param bad_wr Stores a pointer to the first failed WR if this function return nonzero value
* \return 0 on succes, errno on failure
*/
int spdk_rdma_qp_flush_recv_wrs(struct spdk_rdma_qp *spdk_rdma_qp, struct ibv_recv_wr **bad_wr);
/**
* Create a memory map which is used to register Memory Regions and perform address -> memory
* key translations

View File

@ -66,6 +66,7 @@ struct spdk_sock {
int cb_cnt;
spdk_sock_cb cb_fn;
void *cb_arg;
int placement_id;
struct {
uint8_t closed : 1;
uint8_t reserved : 7;
@ -79,14 +80,14 @@ struct spdk_sock_group {
struct spdk_sock_group_impl {
struct spdk_net_impl *net_impl;
struct spdk_sock_group *group;
TAILQ_HEAD(, spdk_sock) socks;
STAILQ_ENTRY(spdk_sock_group_impl) link;
};
struct spdk_sock_map {
STAILQ_HEAD(, spdk_sock_placement_id_entry) entries;
pthread_mutex_t mtx;
/* List of removed sockets. refreshed each time we poll the sock group. */
int num_removed_socks;
/* Unfortunately, we can't just keep a tailq of the sockets in case they are freed
* or added to another poll group later.
*/
uintptr_t removed_socks[MAX_EVENTS_PER_POLL];
};
struct spdk_net_impl {
@ -114,7 +115,7 @@ struct spdk_net_impl {
bool (*is_ipv4)(struct spdk_sock *sock);
bool (*is_connected)(struct spdk_sock *sock);
struct spdk_sock_group_impl *(*group_impl_get_optimal)(struct spdk_sock *sock);
int (*get_placement_id)(struct spdk_sock *sock, int *placement_id);
struct spdk_sock_group_impl *(*group_impl_create)(void);
int (*group_impl_add_sock)(struct spdk_sock_group_impl *group, struct spdk_sock *sock);
int (*group_impl_remove_sock)(struct spdk_sock_group_impl *group, struct spdk_sock *sock);
@ -276,65 +277,6 @@ end:
return iovcnt;
}
static inline void
spdk_sock_get_placement_id(int fd, enum spdk_placement_mode mode, int *placement_id)
{
*placement_id = -1;
switch (mode) {
case PLACEMENT_NONE:
break;
case PLACEMENT_MARK:
case PLACEMENT_NAPI: {
#if defined(SO_INCOMING_NAPI_ID)
socklen_t len = sizeof(int);
getsockopt(fd, SOL_SOCKET, SO_INCOMING_NAPI_ID, placement_id, &len);
#endif
break;
}
case PLACEMENT_CPU: {
#if defined(SO_INCOMING_CPU)
socklen_t len = sizeof(int);
getsockopt(fd, SOL_SOCKET, SO_INCOMING_CPU, placement_id, &len);
#endif
break;
}
default:
break;
}
}
/**
* Insert a group into the placement map.
* If the group is already in the map, take a reference.
*/
int spdk_sock_map_insert(struct spdk_sock_map *map, int placement_id,
struct spdk_sock_group_impl *group_impl);
/**
* Release a reference for the given placement_id. If the reference count goes to 0, the
* entry will no longer be associated with a group.
*/
void spdk_sock_map_release(struct spdk_sock_map *map, int placement_id);
/**
* Look up the group for the given placement_id.
*/
int spdk_sock_map_lookup(struct spdk_sock_map *map, int placement_id,
struct spdk_sock_group_impl **group_impl);
/**
* Find a placement id with no associated group
*/
int spdk_sock_map_find_free(struct spdk_sock_map *map);
/**
* Clean up all memory associated with the given map
*/
void spdk_sock_map_cleanup(struct spdk_sock_map *map);
#ifdef __cplusplus
}
#endif

View File

@ -74,9 +74,7 @@ struct spdk_poller {
spdk_poller_fn fn;
void *arg;
struct spdk_thread *thread;
int interruptfd;
spdk_poller_set_interrupt_mode_cb set_intr_cb_fn;
void *set_intr_cb_arg;
int timerfd;
char name[SPDK_MAX_POLLER_NAME_LEN + 1];
};
@ -130,8 +128,7 @@ struct spdk_thread {
struct spdk_cpuset cpumask;
uint64_t exit_timeout_tsc;
/* Indicates whether this spdk_thread currently runs in interrupt. */
bool in_interrupt;
bool interrupt_mode;
struct spdk_fd_group *fgrp;
/* User context allocated at the end */

View File

@ -483,16 +483,4 @@ int virtio_user_dev_init(struct virtio_dev *vdev, const char *name, const char *
int virtio_pci_dev_init(struct virtio_dev *vdev, const char *name,
struct virtio_pci_ctx *pci_ctx);
/**
* Process the uevent which is accepted from the kernel and the
* uevent descript the physical device hot add or remove action.
*
* \param fd the file descriptor of the kobject netlink socket
* \param device_id virtio device ID used to represent virtio-blk or other device.
* \return the name of the virtio device on success, NULL means it
* is not a suitable uevent.
*/
const char *
virtio_pci_dev_event_process(int fd, uint16_t device_id);
#endif /* SPDK_VIRTIO_H */

View File

@ -34,7 +34,7 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 5
SO_VER := 4
SO_MINOR := 0
SO_SUFFIX := $(SO_VER).$(SO_MINOR)

View File

@ -36,7 +36,6 @@
#include "spdk_internal/accel_engine.h"
#include "spdk/env.h"
#include "spdk/likely.h"
#include "spdk/log.h"
#include "spdk/thread.h"
#include "spdk/json.h"
@ -73,7 +72,6 @@ static void _sw_accel_copy(void *dst, void *src, uint64_t nbytes);
static int _sw_accel_compare(void *src1, void *src2, uint64_t nbytes);
static void _sw_accel_fill(void *dst, uint8_t fill, uint64_t nbytes);
static void _sw_accel_crc32c(uint32_t *dst, void *src, uint32_t seed, uint64_t nbytes);
static void _sw_accel_crc32cv(uint32_t *dst, struct iovec *iov, uint32_t iovcnt, uint32_t seed);
/* Registration of hw modules (currently supports only 1 at a time) */
void
@ -113,19 +111,13 @@ void
spdk_accel_task_complete(struct spdk_accel_task *accel_task, int status)
{
struct accel_io_channel *accel_ch = accel_task->accel_ch;
struct spdk_accel_batch *batch = accel_task->batch;
spdk_accel_completion_cb cb_fn = accel_task->cb_fn;
void *cb_arg = accel_task->cb_arg;
struct spdk_accel_batch *batch;
/* We should put the accel_task into the list firstly in order to avoid
* the accel task list is exhausted when there is recursive call to
* allocate accel_task in user's call back function (cb_fn)
*/
TAILQ_INSERT_TAIL(&accel_ch->task_pool, accel_task, link);
accel_task->cb_fn(accel_task->cb_arg, status);
cb_fn(cb_arg, status);
/* If this task is part of a batch, check for completion of the batch. */
if (batch) {
if (accel_task->batch) {
batch = accel_task->batch;
assert(batch->count > 0);
batch->count--;
if (batch->count == 0) {
@ -137,6 +129,8 @@ spdk_accel_task_complete(struct spdk_accel_task *accel_task, int status)
TAILQ_INSERT_TAIL(&accel_ch->batch_pool, batch, link);
}
}
TAILQ_INSERT_TAIL(&accel_ch->task_pool, accel_task, link);
}
/* Accel framework public API for discovering current engine capabilities. */
@ -314,7 +308,6 @@ spdk_accel_submit_crc32c(struct spdk_io_channel *ch, uint32_t *dst, void *src, u
accel_task->dst = (void *)dst;
accel_task->src = src;
accel_task->v.iovcnt = 0;
accel_task->seed = seed;
accel_task->nbytes = nbytes;
accel_task->op_code = ACCEL_OPCODE_CRC32C;
@ -328,78 +321,6 @@ spdk_accel_submit_crc32c(struct spdk_io_channel *ch, uint32_t *dst, void *src, u
}
}
static void
crc32cv_done(void *cb_arg, int status)
{
struct spdk_accel_task *accel_task = cb_arg;
struct spdk_io_channel *ch = spdk_io_channel_from_ctx(accel_task->accel_ch);
assert(accel_task->chained.cb_fn != NULL);
assert(accel_task->chained.cb_arg != NULL);
if (spdk_likely(!status)) {
status = spdk_accel_submit_crc32cv(ch, accel_task->dst, ++accel_task->v.iovs,
accel_task->v.iovcnt - 1, ~(*((uint32_t *)accel_task->dst)),
accel_task->chained.cb_fn, accel_task->chained.cb_arg);
if (spdk_likely(!status)) {
return;
}
}
accel_task->chained.cb_fn(accel_task->chained.cb_arg, status);
}
/* Accel framework public API for chained CRC-32C function */
int
spdk_accel_submit_crc32cv(struct spdk_io_channel *ch, uint32_t *dst, struct iovec *iov,
uint32_t iov_cnt, uint32_t seed, spdk_accel_completion_cb cb_fn, void *cb_arg)
{
struct accel_io_channel *accel_ch;
struct spdk_accel_task *accel_task;
if (iov == NULL) {
SPDK_ERRLOG("iov should not be NULL");
return -EINVAL;
}
if (!iov_cnt) {
SPDK_ERRLOG("iovcnt should not be zero value\n");
return -EINVAL;
}
if (iov_cnt == 1) {
return spdk_accel_submit_crc32c(ch, dst, iov[0].iov_base, seed, iov[0].iov_len, cb_fn, cb_arg);
}
accel_ch = spdk_io_channel_get_ctx(ch);
accel_task = _get_task(accel_ch, NULL, cb_fn, cb_arg);
if (accel_task == NULL) {
SPDK_ERRLOG("no memory\n");
assert(0);
return -ENOMEM;
}
accel_task->v.iovs = iov;
accel_task->v.iovcnt = iov_cnt;
accel_task->dst = (void *)dst;
accel_task->op_code = ACCEL_OPCODE_CRC32C;
if (_is_supported(accel_ch->engine, ACCEL_CRC32C)) {
accel_task->cb_fn = crc32cv_done;
accel_task->cb_arg = accel_task;
accel_task->chained.cb_fn = cb_fn;
accel_task->chained.cb_arg = cb_arg;
accel_task->nbytes = iov[0].iov_len;
return accel_ch->engine->submit_tasks(accel_ch->engine_ch, accel_task);
} else {
_sw_accel_crc32cv(dst, iov, iov_cnt, seed);
spdk_accel_task_complete(accel_task, 0);
return 0;
}
}
/* Accel framework public API for getting max operations for a batch. */
uint32_t
spdk_accel_batch_get_max(struct spdk_io_channel *ch)
@ -538,7 +459,6 @@ spdk_accel_batch_prep_crc32c(struct spdk_io_channel *ch, struct spdk_accel_batch
accel_task->dst = dst;
accel_task->src = src;
accel_task->v.iovcnt = 0;
accel_task->seed = seed;
accel_task->nbytes = nbytes;
accel_task->op_code = ACCEL_OPCODE_CRC32C;
@ -552,82 +472,6 @@ spdk_accel_batch_prep_crc32c(struct spdk_io_channel *ch, struct spdk_accel_batch
return 0;
}
static void
batched_crc32cv_done(void *cb_arg, int status)
{
struct spdk_accel_task *accel_task = cb_arg;
struct spdk_io_channel *ch = spdk_io_channel_from_ctx(accel_task->accel_ch);
struct spdk_accel_batch *batch;
batch = accel_task->batch;
assert(batch != NULL);
assert(accel_task->chained.cb_fn != NULL);
assert(accel_task->chained.cb_arg != NULL);
if (spdk_likely(!status)) {
status = spdk_accel_batch_prep_crc32cv(ch, batch, accel_task->dst,
++accel_task->v.iovs, accel_task->v.iovcnt - 1, ~(*((uint32_t *)accel_task->dst)),
accel_task->chained.cb_fn, accel_task->chained.cb_arg);
if (spdk_likely(!status)) {
return;
}
}
accel_task->chained.cb_fn(accel_task->chained.cb_arg, status);
}
int
spdk_accel_batch_prep_crc32cv(struct spdk_io_channel *ch, struct spdk_accel_batch *batch,
uint32_t *dst, struct iovec *iovs, uint32_t iov_cnt, uint32_t seed,
spdk_accel_completion_cb cb_fn, void *cb_arg)
{
struct accel_io_channel *accel_ch;
struct spdk_accel_task *accel_task;
if (iovs == NULL) {
SPDK_ERRLOG("iovs should not be NULL\n");
return -EINVAL;
}
if (iov_cnt == 0) {
SPDK_ERRLOG("iovcnt should not be zero value\n");
return -EINVAL;
}
if (iov_cnt == 1) {
return spdk_accel_batch_prep_crc32c(ch, batch, dst, iovs[0].iov_base, seed, iovs[0].iov_len, cb_fn,
cb_arg);
}
accel_ch = spdk_io_channel_get_ctx(ch);
accel_task = _get_task(accel_ch, batch, cb_fn, cb_arg);
if (accel_task == NULL) {
return -ENOMEM;
}
accel_task->v.iovs = iovs;
accel_task->v.iovcnt = iov_cnt;
accel_task->dst = dst;
accel_task->seed = seed;
accel_task->op_code = ACCEL_OPCODE_CRC32C;
if (_is_supported(accel_ch->engine, ACCEL_CRC32C)) {
accel_task->cb_arg = accel_task;
accel_task->cb_fn = batched_crc32cv_done;
accel_task->cb_arg = accel_task;
accel_task->chained.cb_fn = cb_fn;
accel_task->chained.cb_arg = cb_arg;
accel_task->nbytes = iovs[0].iov_len;
TAILQ_INSERT_TAIL(&batch->hw_tasks, accel_task, link);
} else {
TAILQ_INSERT_TAIL(&batch->sw_tasks, accel_task, link);
}
return 0;
}
/* Accel framework public API for batch_create function. */
struct spdk_accel_batch *
spdk_accel_batch_create(struct spdk_io_channel *ch)
@ -707,12 +551,8 @@ spdk_accel_batch_submit(struct spdk_io_channel *ch, struct spdk_accel_batch *bat
batch->status |= rc;
break;
case ACCEL_OPCODE_CRC32C:
if (accel_task->v.iovcnt == 0) {
_sw_accel_crc32c(accel_task->dst, accel_task->src, accel_task->seed,
accel_task->nbytes);
} else {
_sw_accel_crc32cv(accel_task->dst, accel_task->v.iovs, accel_task->v.iovcnt, accel_task->seed);
}
_sw_accel_crc32c(accel_task->dst, accel_task->src, accel_task->seed,
accel_task->nbytes);
spdk_accel_task_complete(accel_task, 0);
break;
case ACCEL_OPCODE_DUALCAST:
@ -964,20 +804,6 @@ _sw_accel_crc32c(uint32_t *dst, void *src, uint32_t seed, uint64_t nbytes)
*dst = spdk_crc32c_update(src, nbytes, ~seed);
}
static void
_sw_accel_crc32cv(uint32_t *dst, struct iovec *iov, uint32_t iovcnt, uint32_t seed)
{
uint32_t i, crc32c = ~seed;
for (i = 0; i < iovcnt; i++) {
assert(iov[i].iov_base != NULL);
assert(iov[i].iov_len != 0);
crc32c = spdk_crc32c_update(iov[i].iov_base, iov[i].iov_len, crc32c);
}
*dst = crc32c;
}
static struct spdk_io_channel *sw_accel_get_io_channel(void);
static uint32_t

View File

@ -14,7 +14,6 @@
spdk_accel_batch_prep_compare;
spdk_accel_batch_prep_fill;
spdk_accel_batch_prep_crc32c;
spdk_accel_batch_prep_crc32cv;
spdk_accel_batch_submit;
spdk_accel_batch_cancel;
spdk_accel_submit_copy;
@ -22,7 +21,6 @@
spdk_accel_submit_compare;
spdk_accel_submit_fill;
spdk_accel_submit_crc32c;
spdk_accel_submit_crc32cv;
spdk_accel_write_config_json;
# functions needed by modules

View File

@ -34,7 +34,7 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 6
SO_VER := 5
SO_MINOR := 0
ifeq ($(CONFIG_VTUNE),y)

View File

@ -304,7 +304,11 @@ struct spdk_bdev_desc {
struct spdk_bdev *bdev;
struct spdk_thread *thread;
struct {
spdk_bdev_event_cb_t event_fn;
bool open_with_ext;
union {
spdk_bdev_remove_cb_t remove_fn;
spdk_bdev_event_cb_t event_fn;
};
void *ctx;
} callback;
bool closed;
@ -1471,6 +1475,7 @@ bdev_mgr_unregister_cb(void *io_device)
g_fini_cb_arg = NULL;
g_bdev_mgr.init_complete = false;
g_bdev_mgr.module_init_complete = false;
pthread_mutex_destroy(&g_bdev_mgr.mutex);
}
static void
@ -3459,7 +3464,7 @@ spdk_bdev_notify_blockcnt_change(struct spdk_bdev *bdev, uint64_t size)
bdev->blockcnt = size;
TAILQ_FOREACH(desc, &bdev->internal.open_descs, link) {
pthread_mutex_lock(&desc->mutex);
if (!desc->closed) {
if (desc->callback.open_with_ext && !desc->closed) {
desc->refs++;
spdk_thread_send_msg(desc->thread, _resize_notify, desc);
}
@ -5306,8 +5311,6 @@ spdk_bdev_io_complete_nvme_status(struct spdk_bdev_io *bdev_io, uint32_t cdw0, i
{
if (sct == SPDK_NVME_SCT_GENERIC && sc == SPDK_NVME_SC_SUCCESS) {
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
} else if (sct == SPDK_NVME_SCT_GENERIC && sc == SPDK_NVME_SC_ABORTED_BY_REQUEST) {
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_ABORTED;
} else {
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_NVME_ERROR;
}
@ -5495,9 +5498,6 @@ bdev_destroy_cb(void *io_device)
cb_fn = bdev->internal.unregister_cb;
cb_arg = bdev->internal.unregister_ctx;
pthread_mutex_destroy(&bdev->internal.mutex);
free(bdev->internal.qos);
rc = bdev->fn_table->destruct(bdev->ctxt);
if (rc < 0) {
SPDK_ERRLOG("destruct failed\n");
@ -5507,6 +5507,17 @@ bdev_destroy_cb(void *io_device)
}
}
static void
bdev_fini(struct spdk_bdev *bdev)
{
pthread_mutex_destroy(&bdev->internal.mutex);
free(bdev->internal.qos);
spdk_io_device_unregister(__bdev_to_io_dev(bdev), bdev_destroy_cb);
}
static void
bdev_start_finished(void *arg)
{
@ -5539,6 +5550,13 @@ spdk_bdev_register(struct spdk_bdev *bdev)
return rc;
}
int
spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, int base_bdev_count)
{
SPDK_ERRLOG("This function is deprecated. Use spdk_bdev_register() instead.\n");
return spdk_bdev_register(vbdev);
}
void
spdk_bdev_destruct_done(struct spdk_bdev *bdev, int bdeverrno)
{
@ -5557,7 +5575,11 @@ _remove_notify(void *arg)
if (!desc->closed) {
pthread_mutex_unlock(&desc->mutex);
desc->callback.event_fn(SPDK_BDEV_EVENT_REMOVE, desc->bdev, desc->callback.ctx);
if (desc->callback.open_with_ext) {
desc->callback.event_fn(SPDK_BDEV_EVENT_REMOVE, desc->bdev, desc->callback.ctx);
} else {
desc->callback.remove_fn(desc->callback.ctx);
}
return;
} else if (0 == desc->refs) {
/* This descriptor was closed after this remove_notify message was sent.
@ -5623,7 +5645,9 @@ spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void
}
pthread_mutex_lock(&g_bdev_mgr.mutex);
pthread_mutex_lock(&bdev->internal.mutex);
if (bdev->internal.status == SPDK_BDEV_STATUS_REMOVING) {
pthread_mutex_unlock(&bdev->internal.mutex);
pthread_mutex_unlock(&g_bdev_mgr.mutex);
if (cb_fn) {
cb_fn(cb_arg, -EBUSY);
@ -5631,7 +5655,6 @@ spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void
return;
}
pthread_mutex_lock(&bdev->internal.mutex);
bdev->internal.status = SPDK_BDEV_STATUS_REMOVING;
bdev->internal.unregister_cb = cb_fn;
bdev->internal.unregister_ctx = cb_arg;
@ -5642,10 +5665,16 @@ spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void
pthread_mutex_unlock(&g_bdev_mgr.mutex);
if (rc == 0) {
spdk_io_device_unregister(__bdev_to_io_dev(bdev), bdev_destroy_cb);
bdev_fini(bdev);
}
}
static void
bdev_dummy_event_cb(void *remove_ctx)
{
SPDK_DEBUGLOG(bdev, "Bdev remove event received with no remove callback specified");
}
static int
bdev_start_qos(struct spdk_bdev *bdev)
{
@ -5713,6 +5742,46 @@ bdev_open(struct spdk_bdev *bdev, bool write, struct spdk_bdev_desc *desc)
return 0;
}
int
spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb,
void *remove_ctx, struct spdk_bdev_desc **_desc)
{
struct spdk_bdev_desc *desc;
int rc;
desc = calloc(1, sizeof(*desc));
if (desc == NULL) {
SPDK_ERRLOG("Failed to allocate memory for bdev descriptor\n");
return -ENOMEM;
}
if (remove_cb == NULL) {
remove_cb = bdev_dummy_event_cb;
}
TAILQ_INIT(&desc->pending_media_events);
TAILQ_INIT(&desc->free_media_events);
desc->callback.open_with_ext = false;
desc->callback.remove_fn = remove_cb;
desc->callback.ctx = remove_ctx;
pthread_mutex_init(&desc->mutex, NULL);
pthread_mutex_lock(&g_bdev_mgr.mutex);
rc = bdev_open(bdev, write, desc);
if (rc != 0) {
bdev_desc_free(desc);
desc = NULL;
}
*_desc = desc;
pthread_mutex_unlock(&g_bdev_mgr.mutex);
return rc;
}
int
spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
void *event_ctx, struct spdk_bdev_desc **_desc)
@ -5747,6 +5816,7 @@ spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event
TAILQ_INIT(&desc->pending_media_events);
TAILQ_INIT(&desc->free_media_events);
desc->callback.open_with_ext = true;
desc->callback.event_fn = event_cb;
desc->callback.ctx = event_ctx;
pthread_mutex_init(&desc->mutex, NULL);
@ -5827,7 +5897,7 @@ spdk_bdev_close(struct spdk_bdev_desc *desc)
pthread_mutex_unlock(&bdev->internal.mutex);
if (rc == 0) {
spdk_io_device_unregister(__bdev_to_io_dev(bdev), bdev_destroy_cb);
bdev_fini(bdev);
}
} else {
pthread_mutex_unlock(&bdev->internal.mutex);

View File

@ -44,30 +44,12 @@ spdk_bdev_get_zone_size(const struct spdk_bdev *bdev)
return bdev->zone_size;
}
uint64_t
spdk_bdev_get_num_zones(const struct spdk_bdev *bdev)
{
return bdev->zone_size ? bdev->blockcnt / bdev->zone_size : 0;
}
uint32_t
spdk_bdev_get_max_zone_append_size(const struct spdk_bdev *bdev)
{
return bdev->max_zone_append_size;
}
uint32_t
spdk_bdev_get_max_open_zones(const struct spdk_bdev *bdev)
{
return bdev->max_open_zones;
}
uint32_t
spdk_bdev_get_max_active_zones(const struct spdk_bdev *bdev)
{
return bdev->max_active_zones;
}
uint32_t
spdk_bdev_get_optimal_open_zones(const struct spdk_bdev *bdev)
{

View File

@ -491,6 +491,27 @@ spdk_bdev_part_base_construct_ext(const char *bdev_name,
return 0;
}
struct spdk_bdev_part_base *
spdk_bdev_part_base_construct(struct spdk_bdev *bdev,
spdk_bdev_remove_cb_t remove_cb, struct spdk_bdev_module *module,
struct spdk_bdev_fn_table *fn_table, struct bdev_part_tailq *tailq,
spdk_bdev_part_base_free_fn free_fn, void *ctx,
uint32_t channel_size, spdk_io_channel_create_cb ch_create_cb,
spdk_io_channel_destroy_cb ch_destroy_cb)
{
struct spdk_bdev_part_base *base = NULL;
int rc;
rc = spdk_bdev_part_base_construct_ext(spdk_bdev_get_name(bdev), remove_cb, module,
fn_table, tailq, free_fn, ctx,
channel_size, ch_create_cb, ch_destroy_cb, &base);
if (rc == 0) {
return base;
} else {
return NULL;
}
}
int
spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
char *name, uint64_t offset_blocks, uint64_t num_blocks,

View File

@ -99,6 +99,7 @@
spdk_bdev_register;
spdk_bdev_unregister;
spdk_bdev_destruct_done;
spdk_vbdev_register;
spdk_bdev_module_examine_done;
spdk_bdev_module_init_done;
spdk_bdev_module_finish_done;
@ -131,6 +132,7 @@
spdk_bdev_part_base_free;
spdk_bdev_part_free;
spdk_bdev_part_base_hotremove;
spdk_bdev_part_base_construct;
spdk_bdev_part_base_construct_ext;
spdk_bdev_part_construct;
spdk_bdev_part_submit_request;
@ -143,10 +145,7 @@
# Public functions in bdev_zone.h
spdk_bdev_get_zone_size;
spdk_bdev_get_num_zones;
spdk_bdev_get_max_zone_append_size;
spdk_bdev_get_max_open_zones;
spdk_bdev_get_max_active_zones;
spdk_bdev_get_optimal_open_zones;
spdk_bdev_get_zone_info;
spdk_bdev_zone_management;

View File

@ -34,7 +34,7 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 5
SO_VER := 4
SO_MINOR := 0
C_SRCS = blobstore.c request.c zeroes.c blob_bs_dev.c

View File

@ -63,8 +63,8 @@ static int blob_get_xattr_value(struct spdk_blob *blob, const char *name,
const void **value, size_t *value_len, bool internal);
static int blob_remove_xattr(struct spdk_blob *blob, const char *name, bool internal);
static void blob_write_extent_page(struct spdk_blob *blob, uint32_t extent, uint64_t cluster_num,
spdk_blob_op_complete cb_fn, void *cb_arg);
static void blob_insert_extent(struct spdk_blob *blob, uint32_t extent, uint64_t cluster_num,
spdk_blob_op_complete cb_fn, void *cb_arg);
static void
blob_verify_md_op(struct spdk_blob *blob)
@ -1642,7 +1642,6 @@ blob_persist_complete(spdk_bs_sequence_t *seq, struct spdk_blob_persist_ctx *ctx
free(ctx);
if (next_persist != NULL) {
blob->state = SPDK_BLOB_STATE_DIRTY;
blob_persist_check_dirty(next_persist);
}
}
@ -1766,7 +1765,7 @@ blob_persist_clear_clusters(spdk_bs_sequence_t *seq, struct spdk_blob_persist_ct
spdk_bs_batch_t *batch;
size_t i;
uint64_t lba;
uint32_t lba_count;
uint64_t lba_count;
/* Clusters don't move around in blobs. The list shrinks or grows
* at the end, but no changes ever occur in the middle of the list.
@ -1779,9 +1778,10 @@ blob_persist_clear_clusters(spdk_bs_sequence_t *seq, struct spdk_blob_persist_ct
lba_count = 0;
for (i = blob->active.num_clusters; i < blob->active.cluster_array_size; i++) {
uint64_t next_lba = blob->active.clusters[i];
uint32_t next_lba_count = bs_cluster_to_lba(bs, 1);
uint64_t next_lba_count = bs_cluster_to_lba(bs, 1);
if (next_lba > 0 && (lba + lba_count) == next_lba) {
if (next_lba > 0 && (lba + lba_count) == next_lba &&
(lba_count + next_lba_count <= UINT32_MAX)) {
/* This cluster is contiguous with the previous one. */
lba_count += next_lba_count;
continue;
@ -2132,31 +2132,36 @@ blob_persist_write_extent_pages(spdk_bs_sequence_t *seq, void *cb_arg, int bserr
return;
}
/* Only write out Extent Pages when blob was resized. */
for (i = ctx->next_extent_page; i < blob->active.extent_pages_array_size; i++) {
/* Only write out changed extent pages */
for (i = ctx->next_extent_page; i < blob->active.num_extent_pages; i++) {
extent_page_id = blob->active.extent_pages[i];
if (extent_page_id == 0) {
/* No Extent Page to persist */
assert(spdk_blob_is_thin_provisioned(blob));
continue;
}
assert(spdk_bit_array_get(blob->bs->used_md_pages, extent_page_id));
ctx->next_extent_page = i + 1;
rc = blob_serialize_add_page(ctx->blob, &ctx->extent_page, &page_count, &ctx->extent_page);
if (rc < 0) {
blob_persist_complete(seq, ctx, rc);
/* Writing out new extent page for the first time. Either active extent pages is larger
* than clean extent pages or there was no extent page assigned due to thin provisioning. */
if (i >= blob->clean.extent_pages_array_size || blob->clean.extent_pages[i] == 0) {
blob->state = SPDK_BLOB_STATE_DIRTY;
assert(spdk_bit_array_get(blob->bs->used_md_pages, extent_page_id));
ctx->next_extent_page = i + 1;
rc = blob_serialize_add_page(ctx->blob, &ctx->extent_page, &page_count, &ctx->extent_page);
if (rc < 0) {
blob_persist_complete(seq, ctx, rc);
return;
}
blob_serialize_extent_page(blob, i * SPDK_EXTENTS_PER_EP, ctx->extent_page);
ctx->extent_page->crc = blob_md_page_calc_crc(ctx->extent_page);
bs_sequence_write_dev(seq, ctx->extent_page, bs_md_page_to_lba(blob->bs, extent_page_id),
bs_byte_to_lba(blob->bs, SPDK_BS_PAGE_SIZE),
blob_persist_write_extent_pages, ctx);
return;
}
blob->state = SPDK_BLOB_STATE_DIRTY;
blob_serialize_extent_page(blob, i * SPDK_EXTENTS_PER_EP, ctx->extent_page);
ctx->extent_page->crc = blob_md_page_calc_crc(ctx->extent_page);
bs_sequence_write_dev(seq, ctx->extent_page, bs_md_page_to_lba(blob->bs, extent_page_id),
bs_byte_to_lba(blob->bs, SPDK_BS_PAGE_SIZE),
blob_persist_write_extent_pages, ctx);
return;
assert(blob->clean.extent_pages[i] != 0);
}
blob_persist_generate_new_md(ctx);
@ -2178,20 +2183,6 @@ blob_persist_start(struct spdk_blob_persist_ctx *ctx)
}
if (blob->clean.num_clusters < blob->active.num_clusters) {
/* Blob was resized up */
assert(blob->clean.num_extent_pages <= blob->active.num_extent_pages);
ctx->next_extent_page = spdk_max(1, blob->clean.num_extent_pages) - 1;
} else if (blob->active.num_clusters < blob->active.cluster_array_size) {
/* Blob was resized down */
assert(blob->clean.num_extent_pages >= blob->active.num_extent_pages);
ctx->next_extent_page = spdk_max(1, blob->active.num_extent_pages) - 1;
} else {
/* No change in size occured */
blob_persist_generate_new_md(ctx);
return;
}
blob_persist_write_extent_pages(seq, ctx, 0);
}
@ -2278,6 +2269,7 @@ blob_persist(spdk_bs_sequence_t *seq, struct spdk_blob *blob,
ctx->seq = seq;
ctx->cb_fn = cb_fn;
ctx->cb_arg = cb_arg;
ctx->next_extent_page = 0;
/* Multiple blob persists can affect one another, via blob->state or
* blob mutable data changes. To prevent it, queue up the persists. */
@ -4349,6 +4341,12 @@ bs_load_super_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)
}
ctx->bs->md_start = ctx->super->md_start;
ctx->bs->md_len = ctx->super->md_len;
rc = spdk_bit_array_resize(&ctx->bs->open_blobids, ctx->bs->md_len);
if (rc < 0) {
bs_load_ctx_fail(ctx, -ENOMEM);
return;
}
ctx->bs->total_data_clusters = ctx->bs->total_clusters - spdk_divide_round_up(
ctx->bs->md_start + ctx->bs->md_len, ctx->bs->pages_per_cluster);
ctx->bs->super_blob = ctx->super->super_blob;
@ -4920,7 +4918,7 @@ spdk_bs_init(struct spdk_bs_dev *dev, struct spdk_bs_opts *o,
lba = num_md_lba;
while (lba < ctx->bs->dev->blockcnt) {
lba_count = spdk_min(UINT32_MAX, ctx->bs->dev->blockcnt - lba);
lba_count = spdk_min(UINT32_MAX - 127, ctx->bs->dev->blockcnt - lba);
switch (opts.clear_method) {
case BS_CLEAR_WITH_UNMAP:
/* Trim data clusters */
@ -6355,7 +6353,6 @@ struct delete_snapshot_ctx {
spdk_blob_op_with_handle_complete cb_fn;
void *cb_arg;
int bserrno;
uint32_t next_extent_page;
};
static void
@ -6525,62 +6522,6 @@ delete_snapshot_sync_clone_cpl(void *cb_arg, int bserrno)
spdk_blob_sync_md(ctx->snapshot, delete_snapshot_sync_snapshot_cpl, ctx);
}
static void
delete_snapshot_update_extent_pages_cpl(struct delete_snapshot_ctx *ctx)
{
/* Delete old backing bs_dev from clone (related to snapshot that will be removed) */
ctx->clone->back_bs_dev->destroy(ctx->clone->back_bs_dev);
/* Set/remove snapshot xattr and switch parent ID and backing bs_dev on clone... */
if (ctx->parent_snapshot_entry != NULL) {
/* ...to parent snapshot */
ctx->clone->parent_id = ctx->parent_snapshot_entry->id;
ctx->clone->back_bs_dev = ctx->snapshot->back_bs_dev;
blob_set_xattr(ctx->clone, BLOB_SNAPSHOT, &ctx->parent_snapshot_entry->id,
sizeof(spdk_blob_id),
true);
} else {
/* ...to blobid invalid and zeroes dev */
ctx->clone->parent_id = SPDK_BLOBID_INVALID;
ctx->clone->back_bs_dev = bs_create_zeroes_dev();
blob_remove_xattr(ctx->clone, BLOB_SNAPSHOT, true);
}
spdk_blob_sync_md(ctx->clone, delete_snapshot_sync_clone_cpl, ctx);
}
static void
delete_snapshot_update_extent_pages(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
uint32_t *extent_page;
uint64_t i;
for (i = ctx->next_extent_page; i < ctx->snapshot->active.num_extent_pages &&
i < ctx->clone->active.num_extent_pages; i++) {
if (ctx->snapshot->active.extent_pages[i] == 0) {
/* No extent page to use from snapshot */
continue;
}
extent_page = &ctx->clone->active.extent_pages[i];
if (*extent_page == 0) {
/* Copy extent page from snapshot when clone did not have a matching one */
*extent_page = ctx->snapshot->active.extent_pages[i];
continue;
}
/* Clone and snapshot both contain partialy filled matching extent pages.
* Update the clone extent page in place with cluster map containing the mix of both. */
ctx->next_extent_page = i + 1;
blob_write_extent_page(ctx->clone, *extent_page, i * SPDK_EXTENTS_PER_EP,
delete_snapshot_update_extent_pages, ctx);
return;
}
delete_snapshot_update_extent_pages_cpl(ctx);
}
static void
delete_snapshot_sync_snapshot_xattr_cpl(void *cb_arg, int bserrno)
{
@ -6604,8 +6545,32 @@ delete_snapshot_sync_snapshot_xattr_cpl(void *cb_arg, int bserrno)
ctx->clone->active.clusters[i] = ctx->snapshot->active.clusters[i];
}
}
ctx->next_extent_page = 0;
delete_snapshot_update_extent_pages(ctx, 0);
for (i = 0; i < ctx->snapshot->active.num_extent_pages &&
i < ctx->clone->active.num_extent_pages; i++) {
if (ctx->clone->active.extent_pages[i] == 0) {
ctx->clone->active.extent_pages[i] = ctx->snapshot->active.extent_pages[i];
}
}
/* Delete old backing bs_dev from clone (related to snapshot that will be removed) */
ctx->clone->back_bs_dev->destroy(ctx->clone->back_bs_dev);
/* Set/remove snapshot xattr and switch parent ID and backing bs_dev on clone... */
if (ctx->parent_snapshot_entry != NULL) {
/* ...to parent snapshot */
ctx->clone->parent_id = ctx->parent_snapshot_entry->id;
ctx->clone->back_bs_dev = ctx->snapshot->back_bs_dev;
blob_set_xattr(ctx->clone, BLOB_SNAPSHOT, &ctx->parent_snapshot_entry->id,
sizeof(spdk_blob_id),
true);
} else {
/* ...to blobid invalid and zeroes dev */
ctx->clone->parent_id = SPDK_BLOBID_INVALID;
ctx->clone->back_bs_dev = bs_create_zeroes_dev();
blob_remove_xattr(ctx->clone, BLOB_SNAPSHOT, true);
}
spdk_blob_sync_md(ctx->clone, delete_snapshot_sync_clone_cpl, ctx);
}
static void
@ -7075,18 +7040,6 @@ blob_insert_cluster_msg_cb(void *arg, int bserrno)
spdk_thread_send_msg(ctx->thread, blob_insert_cluster_msg_cpl, ctx);
}
static void
blob_insert_new_ep_cb(void *arg, int bserrno)
{
struct spdk_blob_insert_cluster_ctx *ctx = arg;
uint32_t *extent_page;
extent_page = bs_cluster_to_extent_page(ctx->blob, ctx->cluster_num);
*extent_page = ctx->extent_page;
ctx->blob->state = SPDK_BLOB_STATE_DIRTY;
blob_sync_md(ctx->blob, blob_insert_cluster_msg_cb, ctx);
}
static void
blob_persist_extent_page_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)
{
@ -7097,8 +7050,8 @@ blob_persist_extent_page_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)
}
static void
blob_write_extent_page(struct spdk_blob *blob, uint32_t extent, uint64_t cluster_num,
spdk_blob_op_complete cb_fn, void *cb_arg)
blob_insert_extent(struct spdk_blob *blob, uint32_t extent, uint64_t cluster_num,
spdk_blob_op_complete cb_fn, void *cb_arg)
{
spdk_bs_sequence_t *seq;
struct spdk_bs_cpl cpl;
@ -7154,11 +7107,13 @@ blob_insert_cluster_msg(void *arg)
extent_page = bs_cluster_to_extent_page(ctx->blob, ctx->cluster_num);
if (*extent_page == 0) {
/* Extent page requires allocation.
* It was already claimed in the used_md_pages map and placed in ctx. */
* It was already claimed in the used_md_pages map and placed in ctx.
* Blob persist will take care of writing out new extent page on disk. */
assert(ctx->extent_page != 0);
assert(spdk_bit_array_get(ctx->blob->bs->used_md_pages, ctx->extent_page) == true);
blob_write_extent_page(ctx->blob, ctx->extent_page, ctx->cluster_num,
blob_insert_new_ep_cb, ctx);
*extent_page = ctx->extent_page;
ctx->blob->state = SPDK_BLOB_STATE_DIRTY;
blob_sync_md(ctx->blob, blob_insert_cluster_msg_cb, ctx);
} else {
/* It is possible for original thread to allocate extent page for
* different cluster in the same extent page. In such case proceed with
@ -7170,8 +7125,8 @@ blob_insert_cluster_msg(void *arg)
}
/* Extent page already allocated.
* Every cluster allocation, requires just an update of single extent page. */
blob_write_extent_page(ctx->blob, *extent_page, ctx->cluster_num,
blob_insert_cluster_msg_cb, ctx);
blob_insert_extent(ctx->blob, *extent_page, ctx->cluster_num,
blob_insert_cluster_msg_cb, ctx);
}
}

View File

@ -34,7 +34,7 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 4
SO_VER := 3
SO_MINOR := 0
C_SRCS = blobfs.c tree.c

View File

@ -34,8 +34,8 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 3
SO_MINOR := 0
SO_VER := 2
SO_MINOR := 1
C_SRCS = conf.c
LIBNAME = conf

View File

@ -34,13 +34,12 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 6
SO_MINOR := 0
SO_VER := 5
SO_MINOR := 1
CFLAGS += $(ENV_CFLAGS)
C_SRCS = env.c memory.c pci.c init.c threads.c
C_SRCS += pci_ioat.c pci_virtio.c pci_vmd.c pci_idxd.c
C_SRCS += pci_event.c sigbus_handler.c
LIBNAME = env_dpdk
SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_env_dpdk.map)
@ -49,18 +48,9 @@ include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
LIBDPDK_PKGCONFIG = $(call pkgconfig_filename,spdk_dpdklibs)
$(LIBDPDK_PKGCONFIG): $(PKGCONFIG) $(PKGCONFIG_INST)
$(LIBDPDK_PKGCONFIG): $(PKGCONFIG)
$(Q)$(SPDK_ROOT_DIR)/scripts/pc_libs.sh \
"-L$(DPDK_ABS_DIR)/lib $(DPDK_LIB_LIST:%=-l%)" "" DPDK spdk_dpdklibs > $@
$(Q)sed -i.bak '5s,.*,Requires: $(DEPDIRS-$(LIBNAME):%=spdk_%) spdk_dpdklibs,' $(PKGCONFIG) ; rm $(PKGCONFIG).bak
$(Q)sed -i.bak '5s,.*,Requires: $(DEPDIRS-$(LIBNAME):%=spdk_%) spdk_dpdklibs,' $(PKGCONFIG_INST) ; rm $(PKGCONFIG_INST).bak
$(Q)echo Requires: spdk_dpdklibs >> $(PKGCONFIG)
_install_dpdklibs: $(LIBDPDK_PKGCONFIG)
@$(call pkgconfig_install,$(LIBDPDK_PKGCONFIG))
_uninstall_dpdklibs: $(LIBDPDK_PKGCONFIG)
@$(call pkgconfig_uninstall,$(LIBDPDK_PKGCONFIG))
all: $(LIBDPDK_PKGCONFIG)
install: _install_dpdklibs
uninstall: _uninstall_dpdklibs
all : $(LIBDPDK_PKGCONFIG)

View File

@ -48,7 +48,7 @@ DPDK_INC_DIR := $(DPDK_ABS_DIR)/include/dpdk
endif
DPDK_INC := -I$(DPDK_INC_DIR)
DPDK_LIB_LIST = rte_eal rte_mempool rte_ring rte_mbuf rte_bus_pci rte_pci rte_mempool_ring
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 rte_ethdev rte_net

View File

@ -832,8 +832,10 @@ vtophys_iommu_map_dma(uint64_t vaddr, uint64_t iova, uint64_t size)
ret = ioctl(g_vfio.fd, VFIO_IOMMU_MAP_DMA, &dma_map->map);
if (ret) {
/* There are cases the vfio container doesn't have IOMMU group, it's safe for this case */
SPDK_NOTICELOG("Cannot set up DMA mapping, error %d, ignored\n", errno);
DEBUG_PRINT("Cannot set up DMA mapping, error %d\n", errno);
pthread_mutex_unlock(&g_vfio.mutex);
free(dma_map);
return ret;
}
out_insert:
@ -890,7 +892,9 @@ vtophys_iommu_unmap_dma(uint64_t iova, uint64_t size)
unmap.size = dma_map->map.size;
ret = ioctl(g_vfio.fd, VFIO_IOMMU_UNMAP_DMA, &unmap);
if (ret) {
SPDK_NOTICELOG("Cannot clear DMA mapping, error %d, ignored\n", errno);
DEBUG_PRINT("Cannot clear DMA mapping, error %d\n", errno);
pthread_mutex_unlock(&g_vfio.mutex);
return ret;
}
out_remove:
@ -1464,7 +1468,6 @@ vtophys_init(void)
g_vtophys_map = spdk_mem_map_alloc(SPDK_VTOPHYS_ERROR, &vtophys_map_ops, NULL);
if (g_vtophys_map == NULL) {
DEBUG_PRINT("vtophys map allocation failed\n");
spdk_mem_map_free(&g_phys_ref_map);
return -ENOMEM;
}
return 0;

View File

@ -269,17 +269,8 @@ pci_device_rte_dev_event(const char *device_name,
if (dev != NULL && can_detach) {
/* if device is not attached we can remove it right away.
* Otherwise it will be removed at detach.
*
* Because the user's callback is invoked in eal interrupt
* callback, the interrupt callback need to be finished before
* it can be unregistered when detaching device. So finish
* callback soon and use a deferred removal to detach device
* is need. It is a workaround, once the device detaching be
* moved into the eal in the future, the deferred removal could
* be deleted.
*/
rte_eal_alarm_set(1, detach_rte_cb, dev->dev_handle);
* Otherwise it will be removed at detach. */
remove_rte_dev(dev->dev_handle);
}
break;
}
@ -1044,7 +1035,9 @@ spdk_pci_device_unclaim(struct spdk_pci_device *dev)
dev->internal.claim_fd = -1;
unlink(dev_name);
}
#else /* !__linux__ */
#endif /* __linux__ */
#ifdef __FreeBSD__
int
spdk_pci_device_claim(struct spdk_pci_device *dev)
{
@ -1057,7 +1050,7 @@ spdk_pci_device_unclaim(struct spdk_pci_device *dev)
{
/* TODO */
}
#endif /* __linux__ */
#endif /* __FreeBSD__ */
int
spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf)
@ -1135,37 +1128,3 @@ spdk_pci_device_get_type(const struct spdk_pci_device *dev)
{
return dev->type;
}
int
spdk_pci_device_allow(struct spdk_pci_addr *pci_addr)
{
struct rte_devargs *da;
char devargs_str[128];
da = calloc(1, sizeof(*da));
if (da == NULL) {
SPDK_ERRLOG("could not allocate rte_devargs\n");
return -ENOMEM;
}
snprintf(devargs_str, sizeof(devargs_str), "pci:%04x:%02x:%02x.%x",
pci_addr->domain, pci_addr->bus, pci_addr->dev, pci_addr->func);
if (rte_devargs_parse(da, devargs_str) != 0) {
SPDK_ERRLOG("rte_devargs_parse() failed on '%s'\n", devargs_str);
free(da);
return -EINVAL;
}
da->policy = RTE_DEV_ALLOWED;
/* Note: if a devargs already exists for this device address, it just gets
* overridden. So we do not need to check if the devargs already exists.
* DPDK will take care of memory management for the devargs structure after
* it has been inserted, so there's nothing SPDK needs to track.
*/
if (rte_devargs_insert(&da) != 0) {
SPDK_ERRLOG("rte_devargs_insert() failed on '%s'\n", devargs_str);
free(da);
return -EINVAL;
}
return 0;
}

View File

@ -1,137 +0,0 @@
/*-
* BSD LICENSE
*
* Copyright (c) Intel Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "spdk/stdinc.h"
#include "spdk/env.h"
#include "spdk/log.h"
struct sigbus_handler {
spdk_pci_error_handler func;
void *ctx;
TAILQ_ENTRY(sigbus_handler) tailq;
};
static pthread_mutex_t g_sighandler_mutex = PTHREAD_MUTEX_INITIALIZER;
static TAILQ_HEAD(, sigbus_handler) g_sigbus_handler =
TAILQ_HEAD_INITIALIZER(g_sigbus_handler);
static void
sigbus_fault_sighandler(int signum, siginfo_t *info, void *ctx)
{
struct sigbus_handler *sigbus_handler;
pthread_mutex_lock(&g_sighandler_mutex);
TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) {
sigbus_handler->func(info, sigbus_handler->ctx);
}
pthread_mutex_unlock(&g_sighandler_mutex);
}
__attribute__((constructor)) static void
device_set_signal(void)
{
struct sigaction sa;
sa.sa_sigaction = sigbus_fault_sighandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sigaction(SIGBUS, &sa, NULL);
}
__attribute__((destructor)) static void
device_destroy_signal(void)
{
struct sigbus_handler *sigbus_handler, *tmp;
TAILQ_FOREACH_SAFE(sigbus_handler, &g_sigbus_handler, tailq, tmp) {
free(sigbus_handler);
}
}
int
spdk_pci_register_error_handler(spdk_pci_error_handler sighandler, void *ctx)
{
struct sigbus_handler *sigbus_handler;
if (!sighandler) {
SPDK_ERRLOG("Error handler is NULL\n");
return -EINVAL;
}
pthread_mutex_lock(&g_sighandler_mutex);
TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) {
if (sigbus_handler->func == sighandler) {
pthread_mutex_unlock(&g_sighandler_mutex);
SPDK_ERRLOG("Error handler has been registered\n");
return -EINVAL;
}
}
pthread_mutex_unlock(&g_sighandler_mutex);
sigbus_handler = calloc(1, sizeof(*sigbus_handler));
if (!sigbus_handler) {
SPDK_ERRLOG("Failed to allocate sigbus handler\n");
return -ENOMEM;
}
sigbus_handler->func = sighandler;
sigbus_handler->ctx = ctx;
pthread_mutex_lock(&g_sighandler_mutex);
TAILQ_INSERT_TAIL(&g_sigbus_handler, sigbus_handler, tailq);
pthread_mutex_unlock(&g_sighandler_mutex);
return 0;
}
void
spdk_pci_unregister_error_handler(spdk_pci_error_handler sighandler)
{
struct sigbus_handler *sigbus_handler;
if (!sighandler) {
return;
}
pthread_mutex_lock(&g_sighandler_mutex);
TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) {
if (sigbus_handler->func == sighandler) {
TAILQ_REMOVE(&g_sigbus_handler, sigbus_handler, tailq);
free(sigbus_handler);
pthread_mutex_unlock(&g_sighandler_mutex);
return;
}
}
pthread_mutex_unlock(&g_sighandler_mutex);
}

View File

@ -79,7 +79,6 @@
spdk_pci_device_unclaim;
spdk_pci_device_detach;
spdk_pci_device_attach;
spdk_pci_device_allow;
spdk_pci_device_cfg_read;
spdk_pci_device_cfg_write;
spdk_pci_device_cfg_read8;
@ -105,10 +104,6 @@
spdk_mem_register;
spdk_mem_unregister;
spdk_mem_get_fd_and_offset;
spdk_pci_event_listen;
spdk_pci_get_event;
spdk_pci_register_error_handler;
spdk_pci_unregister_error_handler;
# Public functions in env_dpdk.h
spdk_env_dpdk_post_init;

View File

@ -34,7 +34,7 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 8
SO_VER := 7
SO_MINOR := 0
CFLAGS += $(ENV_CFLAGS)

View File

@ -278,12 +278,7 @@ app_start_rpc(int rc, void *arg1)
return;
}
rc = spdk_rpc_initialize(g_spdk_app.rpc_addr);
if (rc) {
spdk_app_stop(rc);
return;
}
spdk_rpc_initialize(g_spdk_app.rpc_addr);
if (!g_delay_subsystem_init) {
spdk_rpc_set_state(SPDK_RPC_RUNTIME);
app_start_application();
@ -398,8 +393,6 @@ app_setup_trace(struct spdk_app_opts *opts)
static void
bootstrap_fn(void *arg1)
{
int rc;
if (g_spdk_app.json_config_file) {
g_delay_subsystem_init = false;
spdk_app_json_config_load(g_spdk_app.json_config_file, g_spdk_app.rpc_addr, app_start_rpc,
@ -408,11 +401,7 @@ bootstrap_fn(void *arg1)
if (!g_delay_subsystem_init) {
spdk_subsystem_init(app_start_rpc, NULL);
} else {
rc = spdk_rpc_initialize(g_spdk_app.rpc_addr);
if (rc) {
spdk_app_stop(rc);
return;
}
spdk_rpc_initialize(g_spdk_app.rpc_addr);
}
}
}
@ -429,6 +418,7 @@ app_copy_opts(struct spdk_app_opts *opts, struct spdk_app_opts *opts_user, size_
} \
SET_FIELD(name);
SET_FIELD(config_file);
SET_FIELD(json_config_file);
SET_FIELD(json_config_ignore_errors);
SET_FIELD(rpc_addr);
@ -449,6 +439,7 @@ app_copy_opts(struct spdk_app_opts *opts, struct spdk_app_opts *opts_user, size_
SET_FIELD(pci_blocked);
SET_FIELD(pci_allowed);
SET_FIELD(iova_mode);
SET_FIELD(max_delay_us);
SET_FIELD(delay_subsystem_init);
SET_FIELD(num_entries);
SET_FIELD(env_context);
@ -457,7 +448,7 @@ app_copy_opts(struct spdk_app_opts *opts, struct spdk_app_opts *opts_user, size_
/* You should not remove this statement, but need to update the assert statement
* if you add a new field, and also add a corresponding SET_FIELD statement */
SPDK_STATIC_ASSERT(sizeof(struct spdk_app_opts) == 184, "Incorrect size");
SPDK_STATIC_ASSERT(sizeof(struct spdk_app_opts) == 200, "Incorrect size");
#undef SET_FIELD
}
@ -485,6 +476,18 @@ spdk_app_start(struct spdk_app_opts *opts_user, spdk_msg_fn start_fn,
app_copy_opts(opts, opts_user, opts_user->opts_size);
if (opts->config_file) {
SPDK_ERRLOG("opts->config_file is deprecated. Use opts->json_config_file instead.\n");
/* For now we will just treat config_file as json_config_file. But if both were
* specified we will return an error here.
*/
if (opts->json_config_file) {
SPDK_ERRLOG("Setting both opts->config_file and opts->json_config_file not allowed.\n");
return 1;
}
opts->json_config_file = opts->config_file;
}
if (!start_fn) {
SPDK_ERRLOG("start_fn should not be NULL\n");
return 1;
@ -704,6 +707,11 @@ spdk_app_parse_args(int argc, char **argv, struct spdk_app_opts *opts,
memcpy(&g_default_opts, opts, sizeof(g_default_opts));
if (opts->config_file && access(opts->config_file, R_OK) != 0) {
SPDK_WARNLOG("Can't read JSON configuration file '%s'\n", opts->config_file);
opts->config_file = NULL;
}
if (opts->json_config_file && access(opts->json_config_file, R_OK) != 0) {
SPDK_WARNLOG("Can't read JSON configuration file '%s'\n", opts->json_config_file);
opts->json_config_file = NULL;

View File

@ -365,12 +365,9 @@ _rpc_framework_get_reactors(void *arg1, void *arg2)
{
struct rpc_get_stats_ctx *ctx = arg1;
uint32_t current_core;
uint32_t curr_core_freq;
struct spdk_reactor *reactor;
struct spdk_lw_thread *lw_thread;
struct spdk_thread *thread;
struct spdk_governor *governor;
struct spdk_governor_capabilities capabilities;
current_core = spdk_env_get_current_core();
reactor = spdk_reactor_get(current_core);
@ -381,16 +378,6 @@ _rpc_framework_get_reactors(void *arg1, void *arg2)
spdk_json_write_named_uint32(ctx->w, "lcore", current_core);
spdk_json_write_named_uint64(ctx->w, "busy", reactor->busy_tsc);
spdk_json_write_named_uint64(ctx->w, "idle", reactor->idle_tsc);
governor = _spdk_governor_get();
/* We need to check whether governor can return current core frequency. */
if (governor->get_core_capabilities && governor->get_core_freqs) {
governor->get_core_capabilities(current_core, &capabilities);
if (capabilities.freq_getset) {
/* Governor returns core freqs in kHz, we want MHz. */
curr_core_freq = governor->get_core_curr_freq(current_core) / 1000;
spdk_json_write_named_uint32(ctx->w, "core_freq", curr_core_freq);
}
}
spdk_json_write_named_array_begin(ctx->w, "lw_threads");
TAILQ_FOREACH(lw_thread, &reactor->threads, link) {
@ -510,9 +497,9 @@ rpc_framework_get_scheduler(struct spdk_jsonrpc_request *request,
w = spdk_jsonrpc_begin_result(request);
spdk_json_write_object_begin(w);
spdk_json_write_named_string(w, "scheduler_name", scheduler->name);
spdk_json_write_named_uint64(w, "scheduler_period", scheduler_period);
spdk_json_write_named_string(w, "governor_name", governor->name);
spdk_json_write_named_string(w, "scheduler name", scheduler->name);
spdk_json_write_named_uint64(w, "scheduler period", scheduler_period);
spdk_json_write_named_string(w, "governor name", governor->name);
spdk_json_write_object_end(w);
spdk_jsonrpc_end_result(request, w);
}

View File

@ -49,25 +49,7 @@ _get_core_freqs(uint32_t lcore_id, uint32_t *freqs, uint32_t num)
static uint32_t
_get_core_curr_freq(uint32_t lcore_id)
{
const uint32_t MAX_CORE_FREQ_NUM = 64;
uint32_t freqs[MAX_CORE_FREQ_NUM];
uint32_t freq_index;
int rc;
rc = rte_power_freqs(lcore_id, freqs, MAX_CORE_FREQ_NUM);
if (!rc) {
SPDK_ERRLOG("Unable to get current core frequency array for core %d\n.", lcore_id);
return 0;
}
freq_index = rte_power_get_freq(lcore_id);
if (freq_index >= MAX_CORE_FREQ_NUM) {
SPDK_ERRLOG("Unable to get current core frequency for core %d\n.", lcore_id);
return 0;
}
return freqs[freq_index];
return rte_power_get_freq(lcore_id);
}
static int

Some files were not shown because too many files have changed in this diff Show More