Compare commits

...

98 Commits

Author SHA1 Message Date
Darek Stojaczyk
31b5b6e1e6 env_dpdk/memory: include rte_memory.h
Latest DPDK moved some definitions around and we don't
compile with it right now. Adding the missing include
fixes it.

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/460905 (master)

(cherry picked from commit cf35beccf4)
Change-Id: I256c6fae926d7829d06cf5f6b6601d062386b1e7
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/462437
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-07-22 14:23:15 +00:00
Darek Stojaczyk
f6dfa72703 autotest: disable ASAN when SPDK_TEST_BLOCKDEV
At the time of SPDK 19.04 release the blockdev tests
were run on machines without libasan installed. A few
months after the release we've merged a fairly big
patch series enabling blockdev to be run with ASAN
and we've installed libasan on all CI machines.

19.04.x doesn't have this patch series and currently
fails to start fio on CI.

We don't want to cherry-pick the entire series, so just
explicitly disable ASAN in our test scripts whenever
blockdev tests are run.

Change-Id: Ib5e26932b5dfd736611ffabd4b055459ec25e59f
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/462820
2019-07-22 13:40:49 +00:00
Tomasz Zawadzki
50a116dbe5 fio_plugin: Use CLOCK_MONOTONIC for FreeBSD
In order for fio_plugin to compile a replacement is needed
for CLOCK_MONOTONIC_RAW, since FreeBSD does not support it.
In that case CLOCK_MONOTONIC is used.

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

(cherry picked from commit 9b96749f66)
Change-Id: Ie2f7c5b2f19e473a37983856a37370a879b0e3f3
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/462512
2019-07-22 13:40:49 +00:00
Tomasz Zawadzki
82f691be43 version: 19.04.2-pre
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I569dc9f4a1dce24ac595a06a71b0bdc9a3404ab6
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458577
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-26 08:06:23 +00:00
Tomasz Zawadzki
efabcb5b61 SPDK 19.04.1
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I2f53f98334fdcd501b74d0f0b0b7e1f9d93a8935
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458576
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-19 10:44:27 +00:00
Tomasz Zawadzki
52fa503769 CHANGELOG: updated for v19.04.1
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: Iaaaa46598b83e8356b34e3e138886e70d1d68b26
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458575
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-19 10:44:27 +00:00
paul luse
d1a833ffb1 log: passing user-defined log
Signed-off-by: zkhatami88 <z.khatami88@gmail.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/456407 (master)

(cherry picked from commit 46523f33e0)
Change-Id: I993e15a6e75029b0717960d5da31325e7f3522c1
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458450
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-19 10:28:53 +00:00
Maciej Szwed
f944a090e3 blobstore: Fix error path for snapshot creation
In _spdk_bs_snapshot_origblob_sync_cpl function on error
path we should not close snapshot as it will be closed during
volume closing when bs_dev is being destroyed.
This issue was found in unit test (see next patch in series).

Signed-off-by: Maciej Szwed <maciej.szwed@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455215 (master)

(cherry picked from commit f27cbce428)
Change-Id: I51c38d1f1f97b134679251b43109b1265e565a17
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458589
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-19 10:25:23 +00:00
Maciej Szwed
84b5ac7dac blobstore: Enable/disable snapshot deletion with CFLAGS
Snapshot delete functionality is targeted for .1 release
and therefore should not be enabled by default. Use
export CFLAGS=-DSPDK_ENABLE_SNAPSHOT_DELETION
to enable this functionality.

Signed-off-by: Maciej Szwed <maciej.szwed@intel.com>
Change-Id: I2d966b62cd5d7eaf8134962d1a833542edfe2d9f
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458466
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-19 10:24:59 +00:00
Maciej Szwed
3c22b8e41b blobstore: Make possible to remove snapshot if there is only one clone
Starting with this patch it is possible to remove a
snapshot if there is only a one clone created from it.

In such case snapshot can be removed without any data
copying. This is achieved with following steps (case
with only one clone):
1. Open snapshot (Snapshot1) that shall be removed
2. Check if the Snapshot1 has no more than 1 clone (Clone1)
3. Remove Clone1 entry from Snapshot1
4. If the Snapshot1 has a parent snapshot (Snapshot2):
 4a. Add Clone1 entry to the Snapshot2 clones list
 4b. Remove Snapshot1 entry from Snapshot2 clones list
5. Open Clone1 blob
6. Freeze I/O operations on Clone1
7. Temporarily override md_ro flag for Snapshot1 and Clone1
   for MD modification
8. Merge Snapshot1 and Clone1 clusters maps into Clone1
   clusters map
9a. If Snapshot2 is present switch parent ID and backing
    bs_dev on Clone1
9b. If Snapshot2 is not present set parent ID to
    SPDK_BLOBID_INVALID and backing bs_dev to zeroes_dev
10. Sync MD on Clone1
11. Sync MD on Snapshot1
12. Restore MD flags for Clone1 and Snapshot1
13. Unfreeze I/O on Clone1
14. Close Clone1 blob
15. Remove Snapshot1

Signed-off-by: Maciej Szwed <maciej.szwed@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/445576 (master)

(cherry picked from commit 622127d7e1)
Change-Id: I800724b981af894e01e1912d0077c5b34a2ae634
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458464
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-19 10:24:59 +00:00
Darek Stojaczyk
a15831658d test/lvol: wait for bdevs to be examined
The lvol "tasting" done as a part of bdev examine is
done asynchronously in background, so we need to sleep
for a while before checking the list of created lvol
bdevs.

Fixes #801

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458228 (master)

(cherry picked from commit 036ca4acb6)
Change-Id: Iab94ac5c66d329cd93955b53262fc03c6b3c9f3a
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458449
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-19 09:29:54 +00:00
Ziye Yang
880cbc5da3 blobfs: fix the semphore usage issue in spdk_file_read
We need to move sub_reads++ statement earlier. Otherwise if
the read fails, the sem_wait(&channel->sem) call number
is not correct.

Signed-off-by: Ziye Yang <ziye.yang@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453788 (master)

(cherry picked from commit bc1495b0f0)
Change-Id: I05281a74bef78e4f80ce8d202b47849d1e6c2009
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457285
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-19 09:26:37 +00:00
Darek Stojaczyk
91096c9e4f rpc: fix segfault on get_spdk_version request with extra params
We tried to send two responses for a single RPC request.

Fixes #798

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455220 (master)

(cherry picked from commit 75a6265de9)
Change-Id: I37eebd6a1212f6ab2c026b7587415e42c3c7417e
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457242
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-18 19:02:49 +00:00
Vitaliy Mysak
9811e15503 test/ocf: disable norandommap flag
disable FIO norandommap flag because it is incompatible with
  verify which in context of async IO could cause verification errors.
More on norandommap:
  https://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-norandommap

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457001 (master)

(cherry picked from commit 5875bb0e3b)
Change-Id: I94392495a1f9f06360e3791fca31b88908d19dcb
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457589
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-18 19:01:37 +00:00
Vitaliy Mysak
a82ed6455a ocf: Improve handling of partial IOs
Improve handling of partial IOs for case when iovcnt == 1.
This case is pretty frqeuent because all data allocated by OCF
  have iovcnt == 1 (see ctx->data->alloc() or vbdev_ocf_ctx_data_alloc())

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/456202 (master)

(cherry picked from commit 7b7590f838)
Change-Id: I8d38ca9e9d2bd3e6ce298bf788ce6ed782b56594
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457588
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-18 19:01:37 +00:00
Vitaliy Mysak
b6765e8efa ocf: fix offset check
This patch fixes submission of partial IOs in bottom adapter

Existing check (if offset > 0) was not sufficient to detect partial IOs
  because there could be an IO with offset = 0 but length < total size of iovs.
This patch changes the check, but also free operation on completion
  because now the old free does not cover all situations when we allocate iovs.

`Partial IOs` are the IOs handled by bottom adapter
  which specify only part of the internal iovs vector.
So their length is less that the length of internal iovs vector.
They exist because sometimes parts of single IO from top adapter
  need to be sent to different locations.
Also, in general, IOs initiated by OCF (such as cleaner IOs) are represented
  as single big iov that is submitted by parts in form of 'Partial IOs'.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455821 (master)

(cherry picked from commit 2bfa860dfe)
Change-Id: I8ae47659fb34904c593a696d74d683a418ac9962
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457587
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-18 19:01:37 +00:00
Darek Stojaczyk
4b58c6a3db test/vhost: remove virtio-pmd tests
Those tests are absolutely awful. For the last few days
they've been randomly failing way more often than usual
and we have no way of figuring out what the root cause is.
We know it's 'discover_bdevs' that hangs, but since it
doesn't produce any output (all redirected to null), we
can't get any relevant information out of it. The only
way to move forward is to rewrite this entire test from
scratch.

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457766 (master)

(cherry picked from commit 59c8eeddf6)
Change-Id: Ie874110008f82f3ca0dd62f733b0dac73160fbb8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458069
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-18 19:00:37 +00:00
Darek Stojaczyk
a994009f30 rte_vhost: fix compilation against dpdk master
struct ether_addr was renamed to struct rte_ether_addr
in latest DPDK master, but our internal fork of rte_vhost
still used the old name, which can be now a non-defined type.

Together with the struct, the RTE_ETHER_ADDR_LEN define
was renamed as well, so we'll now check if it's defined and
we'll manually define struct ether_addr to keep the old
rte_vhost working.

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457609 (master)

(cherry picked from commit 1a8ee925b0)
Change-Id: I78b8104ed3bfe03397881a94f0f8bee14f9efae8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458068
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-18 19:00:37 +00:00
lorneli
902bef378c nvme: zero request->submit_tick in allocation
Request may be submitted several times via nvme_qpair_submit_request
function, such as request in queued_req queue being re-submitted.

With enabling timeout feature, nvme_qpair_submit_request compares
request->submit_tick to zero to check if this is the first submission
for this request. If true, record submit_tick for this reuqest.

So request->submit_tick needs to be set zero in allocation.

Signed-off-by: lorneli <lorneli@163.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/456328 (master)

(cherry picked from commit a5dfbc4daf)
Change-Id: Ie3f420aa337802c5ad3962c3fdcd680dec1ccdcb
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457290
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-18 19:00:37 +00:00
Changpeng Liu
ad96f83787 bdev: don't call spdk_bdev_free_io() for the error case
Existing code in spdk_bdev_write_zeroes_blocks() will call spdk_bdev_free_io()
for the error case, which will cause assertion because the bdev_io isn't
submitted to the backend yet, so we will check the condtion first to
avoid the error case.

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

(cherry picked from commit 9da1c7384d)
Change-Id: If27d78217f709a3315e74c00869d345abd6b9a69
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457288
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
2019-06-18 19:00:37 +00:00
Jim Harris
9a92b9e3ed nvmf: fix assert in spdk_nvmf_tcp_req_fill_iovs
It's OK for iovcnt to equal SPDK_NVMF_MAX_SGL_ENTRIES.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/456111 (master)

(cherry picked from commit f758598c44)
Change-Id: Ic95d04f5667858e7fbb025f469c027e2d47b8ba1
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457287
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
2019-06-18 19:00:37 +00:00
John Kariuki
366297805e scripts/nvmf performance: fix config param and connection error
Fixed the following:
1) Missing python paramiko module in package dependecies.
2) Paramiko connection error: TypeError: missing_host_key() missing 1 required positional argument: 'key'
The set_missing_host_key_policy call should take a class instance AutoAddPolicy(), instead of the class name.
3) JSON config file defines "rdma_ips" instead of "nic_ips"
4) Added result file location in the documentation
5) Added env variable for PYTHONPATH to documentation
6) config.json changed default rw to randrw instead of read

Signed-off-by: John Kariuki <John.K.Kariuki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455285 (master)

(cherry picked from commit d601374387)
Change-Id: I96624e2912131f62254c684a6c03a53a7f806cde
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457286
Reviewed-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: John Kariuki <John.K.Kariuki@intel.com>
Reviewed-by: Liang Yan <liang.z.yan@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-18 19:00:37 +00:00
Darek Stojaczyk
59401ab51b build: make dpdk depend on ipsec
DPDK 19.05+ can build a single test app with -lIPSec_MB,
so we need to make sure ipsec is built beforehand.

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455915 (master)

(cherry picked from commit 4de4b78b28)
Change-Id: I6f28936f79558af24e20dc702a6f4e75c507043d
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457284
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-18 19:00:37 +00:00
Darek Stojaczyk
a6c675733b dpdkbuild: specify ldflags
In DPDK 19.05 there's a new test app which we obviously
don't need to build, but we have no way not to, as it's
built together with a library that we do need.

That app may try to link with crypto and compress PMDs,
which require IPSec and ISA-L respectively. If those were
not installed on the system, the linking would fail. We
fix it by providing DPDK with extra -L/path/to/[...]

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455825 (master)

(cherry picked from commit 9399b20431)
Change-Id: I652efb669d10d2d03d0f643ce539404c1f0e38c4
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457283
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-18 19:00:37 +00:00
Tomasz Kulasek
be83292657 test/json_config: wait for clean config
Fixes issue #789

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455668 (master)

(cherry picked from commit b7080d47c5)
Change-Id: I795247e3b19c24dbf1564e2c0f6c5c44e850ab8b
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458346
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-18 11:43:24 +00:00
Jim Harris
b85a64c878 blobfs: don't flush a partial buffer with no sync pending
We flush a cache buffer once it's filled.  When the write
for that cache buffer has completed, we look to see if
there's more data to flush.  Currently if there's *any*
more data to flush, we will flush it, even if it's not
a full buffer.

That can hurt performance though.  Ideally we only want
to flush a partial buffer if there's been an explicit
sync operation that requires that partial buffer to be
flushed.  Otherwise we will end up writing the partial
buffer to disk, and then come back and write that data
again later when the buffer is full.

Add a new unit test to test for this condition.  This
patch breaks one of the existing unit tests which was
designed specifically around a RocksDB failure condition.
Change that file_length unit test to now write exactly
one CACHE_BUFFER, which still tests the general logic
making sure that we don't confuse the amount of data
flushed with the value written to the file's length
xattr.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455698 (master)

(cherry picked from commit cdd089a8c5)
Change-Id: I83795fb45afe854b38648d0e0c1a7928219307a2
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457276
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
2019-06-18 10:59:28 +00:00
Jim Harris
31f18569bd blobfs: ensure length xattr is written even if all data is flushed
Data can get implicitly flushed as cache buffers are filled.  But
the length xattr is only written in response to a sync or close
operation.  So we cannot just look at the amount of data flushed,
and ignore the sync operation if all of the data written has been
flushed - we still need to write the length xattr.

This also adds a unit test which reproduces the original problem.

Fixes issue #297.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455692 (master)

(cherry picked from commit e967dcd245)
Change-Id: Icca6ef4d1544f72e9bc31c4ee77d26b4b7f0cce4
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457275
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 10:59:28 +00:00
Richael Zhuang
1fa9d7e14e lib/ftl: fix PAGE_SIZE for AArch64
Not only 4KB page size is supported on AArch64. The most common is 4KB
and 64KB. 16KB is supported too. We can get it by "getconf PAGESIZE".

Signed-off-by: Richael Zhuang <richael.zhuang@arm.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454447 (master)

(cherry picked from commit 5327875c74)
Change-Id: I6f09741372d35e868228528d976fe3b5a65ff96c
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457229
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-18 07:57:03 +00:00
Vitaliy Mysak
d8a948ca1d ocf: RPC add WriteBack to allowed cache modes
Make construct_ocf_bdev call accept 'wb'
  as allowed cache mode.
Previusly user could only create OCF bdevs
  in WriteThrough or PassThrough modes.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455628 (master)

(cherry picked from commit 1e0e0ea1fc)
Change-Id: Ic2e1c8d2905cb51fc13c080aa7b7a4dfd7d9387f
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457585
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
3768d9a8c6 ocf: implement metadata probe
Implement metadata probe functionality to load cache state
  from disk.
During metadata probe, we inspect UUIDs of core devices
  and create vbdev configurations based on them.
  Then, to start vbdev, we use load path (loadq = true).

After this change persistent metadata is officially supported,
  we can save and restore cache state from persistant storage.

WriteBack mode is now safe to use in respect to unexpected shutdowns,
  because all information about dirty data is also restored during cache load.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455417 (master)

(cherry picked from commit 9686948334)
Change-Id: I6cf86aabd68177b88638a68ea6a5b78a1068a4d0
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457584
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
a7411e316a test/ocf: enable serialize_overlap flag for FIO
Set serialize_overlap=1 to prevent data races.
This solves the issue of fio --verify fails in OCF tests
  when persistent metadata is enabled.
  Example:
     https://dqtibwqq6s6ux.cloudfront.net/public_build/autotest-per-patch_33325.html

The serialize_overlap flag prevents from
  creating undefined regions by doing simultaneus writes
  (occurs on certain storages).
  More on that:
     https://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-serialize-overlap

We should probably use this flag for all FIO --verify tests.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/456991 (master)

(cherry picked from commit 73224f880e)
Change-Id: Ia4f73f9900835faf4f94018f1d148fb64f06dc8a
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457583
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
e1e269463d ocf: Update ocf submodule to version OCF v19.3.2
This patch updates submodule and appropriate functions.
Cleaner poller is now registered only when needed.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455408 (master)

(cherry picked from commit 5983f92cfc)
Change-Id: Ic4ca7ce6f77b71ac12c19462f62ae7cd96c59006
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457582
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
7a606da6df ocf: accept optional base in bottom adapter
Interpret volume->open() options as our vbdev_ocf_base struct.
This is used during metadata probe procedure, when there is no
  vbdev configurations created, so we need to pass base structure
  as option.

This patch is a prepartion for persistant metadata support,
  and it does not change current behavior.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455415 (master)

(cherry picked from commit fec9d4146b)
Change-Id: I0b7435df1692d8b3028931c6c9fc50d2d84b2557
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457274
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
3e5cfa4124 ocf: serialize base bdev names in OCF UUID
Use OCF per-volume UUID field to serialize bdev names.
This is going to be used during cache load to find out
  which bdevs we want to attach.

Note that there is in fact "user_metadata" buffor that is
  also stored in cache metadata, but we cannot use it
  because its size is limited to 64 bytes.
  UUID in OCF terms is not standarized
  and is meant to be used to store custom immutable data.

This change preparation for persistent metadata support.
Functionality is not changed. (everything works the same way)

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455414 (master)

(cherry picked from commit 4003ebf73c)
Change-Id: Ia9204fae29106f5b816d93a6771425a223d6c028
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457268
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
624769671d ocf: stop cache immediately at shutdown
Change shutdown behavior such that now first bdev destruct() call
  stops OCF cache instance.
Previusly, cache was stopped when single vbdev was referencing it.

This patch is related to persistent metadata support.
Without this change, every time a SPDK application is stopped,
  only the last core is remembered in metadata,
  because vbdevs detach by 1 by 1, each time updating the metadata.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455413 (master)

(cherry picked from commit 1292ef24e7)
Change-Id: I57db3f77db525177c024ee85e660a85aff2f8c31
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457267
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
ce3ffa45ed ocf: fix vbdev_ocf_ctx_data_seek() function
Fix instance function for OCF ctx interface.
This function is used for persistent metadata only.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455412 (master)

(cherry picked from commit efe48d7ca9)
Change-Id: I9583ea8eb21f07a3e9072a9552bed1c077cb7114
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457266
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
2c4928649a ocf: allow loading cache without setting cache mode
Make init_vbdev() accept NULL as cache_mode if loadq flag
  is set.
This is needed for load path because we don't know cache mode
  before the actual load (happens later).

This change is related to persistant metadata support.
This patch does not change current behavior because loadq flag
  is always false.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455411 (master)

(cherry picked from commit cca2eab10a)
Change-Id: I42727eb841d87903c81bd5e6d51b6d4869ed9be3
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457265
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
398e1b15ac ocf: implement cache load path
Implement load path for OCF cache.
During load OCF will read metadata from cache disk and restore its state.

management_channel initialization is moved before cache load/attach part
  because ocf_mngt_cache_load() needs it to read metadata.

This patch is a preparation for persistant metadata support.
Load path is never used yet because loadq flag is always false.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455410 (master)

(cherry picked from commit 2b1c1e7031)
Change-Id: Iff6c1c52eae7b9f52812a8bd3d5ae6d6facedd60
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457264
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
Vitaliy Mysak
8e0360cffa ocf: add loadq flag to construct path
Add new loadq flag that indicates if vbdev
  should load cache instance from disk or start a new one.

This change is a preparation for persistent metadata support.
Functionality is not changed in this patch as the loadq flag is always false.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455409 (master)

(cherry picked from commit 242564a82c)
Change-Id: I1baac7f988e6eeadb4f365ba7bfab8019d55a753
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457263
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-18 07:11:21 +00:00
Piotr Pelplinski
c6b5afcec9 ocf: add metadata callbacks
This patch adds callback for serializing spdk metadata
stored in ocf cache devices.

Signed-off-by: Piotr Pelplinski <piotr.pelplinski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/449300 (master)

(cherry picked from commit fca402b0f2)
Change-Id: I856bac3d63c7172dd6c67361794159fa38812a78
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457262
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-18 07:11:21 +00:00
paul luse
c126086c00 bdev/compress: fix issues with delete
I didn't test delete after making a bunch of channel changes so there
were some bugs in that path.  Also as a drive-by I NULL out the
base_desc in vbdev_reduce_load_cb() to be consistent with other places
where I'm closing the base desc.

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

(cherry picked from commit 168738298b)
Change-Id: Iddd5dc704cde8eb7a6a5a3a8481e064a5c6c6d4e
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457228
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-18 03:17:06 +00:00
Shuhei Matsumoto
38a1ebb516 bdev/passthru: call spdk_bdev_module_release_bdev in the error path of registration
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453955 (master)

(cherry picked from commit cd02f1cda5)
Change-Id: Ibdea7a34fff5cea7a9861a3172835429aef7e992
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457226
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-18 03:17:06 +00:00
Vitaliy Mysak
1c78126235 ocf: test: use all cache modes
Modify FIO test to use all cache modes that we support,
  including WriteBack

New test config uses Nvme bdevs instead of mallocs because
  memory is an issue when testing OCF

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/451022 (master)

(cherry picked from commit d6f0613d19)
Change-Id: I3abec9605b61791f8ebaaaf08b88a011a50d3f26
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457261
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
11b1e6bf4c ocf: send flush during shutdown
Do management flush during OCF shutdown to write all dirty requests to cores.
Dirty requests are relevant to WriteBack mode only.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/450683 (master)

(cherry picked from commit 40cac0ecad)
Change-Id: I778a73ed8ab5659921f192f638027d513c239814
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457260
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Piotr Pelplinski
a2711aa354 OCF: Update ocf submodule to version OCF v19.3.1
This patch updates submodule and appropiate functions.

Signed-off-by: Piotr Pelplinski <piotr.pelplinski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/451463 (master)

(cherry picked from commit a34f905a74)
Change-Id: I8cd7707058745cdc3e91f7d821bf215ff9287c86
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457259
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
38031e742c ocf: implement OCF cleaner
Implement cleaner that is used in WriteBack mode.

Cleaner is a background agent that does synchronization
 of data between cache and its cores.
 Cleaner usually runs every ~20 seconds to perform cleaning.
 The synchronization is a simmilar operation to OCF management flushes.
We need cleaner for WriteBack because only WriteBack mode
 produces dirty data that cleaner needs to deal with.
Cleaner requires adopting trylock() because in current version
 cleaner uses management lock when performs cleaning,
 which may lead to deadlocks if cleaner runs on
 the same thread as management operations.

WriteBack mode is fully functional after this change,
  but persistent metadata support is required to use it for production.

Cleaner will run on management thread for now.
  We plan to implement functionality of
  chosing a CPU core where cleaner should run.
Cleaning policy is not configurable yet.
  The default is ALRU with 20 sec interval.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/448537 (master)

(cherry picked from commit 80a2ff01f3)
Change-Id: I35aa7e00c44e0d7a77e64e60df1f66f20be03f55
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457258
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
6450c84d9a ocf: create management channel
Create new management channel and handle sharing between vbdevs.
This channel is going to be used for management operations
 that produce IOs (such as flush) and also for cleaner.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455272 (master)

(cherry picked from commit eb58ad5379)
Change-Id: Ieeed8454a7ab7459c86ac06ec6c0ece038bc928e
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457257
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
f3ff9870d8 ocf: implement mngt_queue for asynchronous management
Implement management queue for asynchronous management that is provided
  in new OCF API. This is a neccessery step to be able to implement
  metadata support.

OCF submodule was updated to get management queue functionality
It has to be done in this patch because OCF module will not work
otherwise.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/448619 (master)

(cherry picked from commit 54eeeac6e0)
Change-Id: Id19c2e5bd6a5d26fee41752b62720e408dc082e8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457256
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
5f930d1738 ocf: lock queue list during create/delete
OCF queue list needs to be managed synchronously.
This patch uses our own mutex to achieve that because we cannot rely on
  ocf_mngt_cache_lock() as it may produce deadlocks when using
  cleaner.

Alternative way would be to use trylock, but
  we need to register a poller for it and do locking concurently
  which doesn't seem to be possible in callbacks of io channel.

We agreed with OCF team that we are going to change this part
  when OCF will deliver safe ocf_mngt_cache_lock() function.

This patch fixes a very rare failure on our CI that looked like this:
```
04:33:02 vbdev_ocf.c: 134:stop_vbdev: *NOTICE*: Not stopping cache instance 'Malloc0' because it is referenced by other OCF bdev
04:33:03 MalCache1: Core core2 successfully removed
04:33:03 MalCache1: Stopping cache
04:33:03 MalCache1: Done saving cache state!
04:33:03 src/ocf/mngt/ocf_mngt_cache.c:1576:2: runtime error: pointer index expression with base 0x000000000000 overflowed to 0xffffffffffffffa8
04:33:03     #0 0x7f3c52d54c26 in _ocf_mngt_cache_stop src/ocf/mngt/ocf_mngt_cache.c:1576
04:33:03     #1 0x7f3c52d5579f in ocf_mngt_cache_stop src/ocf/mngt/ocf_mngt_cache.c:1657
04:33:03     #2 0x7f3c52cbe9f4 in stop_vbdev /var/jenkins/workspace/NVMe_tests/nvme_phy_autotest/spdk/lib/bdev/ocf/vbdev_ocf.c:147
04:33:03     #3 0x7f3c52cbf4a0 in vbdev_ocf_destruct /var/jenkins/workspace/NVMe_tests/nvme_phy_autotest/spdk/lib/bdev/ocf/vbdev_ocf.c:216
```

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/450682 (master)

(cherry picked from commit 244d6e3daa)
Change-Id: Id6fafb444958f3becdc480e44762074c6c081e1f
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457255
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
58b41ea2b5 ocf: add shared cache instance context
Introduce cache context structure that is going to be used
  for sharing per cache info. For example: management queue,
  cleaner_channel, cleaner_thread.

Lifetime of this structure ends with last vbdev that gets unregistered
  and NOT when cache stops because cache does not have to be freed
  there.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/451403 (master)

(cherry picked from commit 4e7fb25066)
Change-Id: I66252084d7efda92edd10fb737c8e9c8169b4f6d
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457254
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
301d6e7c78 ocf: adapt new asynchronous OCF API
Adapt to new async API which was changed recently
This is a neccessery step to be able to implement persistent metadata support

OCF submodule was updated to get new API

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/448397 (master)

(cherry picked from commit f51d3b6dd7)
Change-Id: I6bf9941ab0557981235c5be27686594a1b8ac3a0
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457253
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
3f6c9a4e0f ocf: move register_finish() function up
Move last step of register chain to the top because it is arguably more readable.
This should not be done in previus patch because it spoils the gerrithub diff.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454574 (master)

(cherry picked from commit cac0e9d01c)
Change-Id: If51642a32c5cf2a757ca20485d2347410653ca2a
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457252
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
0b4df54fb2 ocf: use trylock in vbdev_ocf.c
Use new trylock API to prevent lockups when using OCF cleaner.
Starting and stoping OCF bdev becomes asynchronous with this patch.

Using trylock means that we have to poll function that does locking each
  time we want to initiate some operation on cache instance.
  This is the reason why management functions become asynchronous.
Each management operation now has a _poll() operation associated with it.
  _poll() uses trylock and continues when cache is locked.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/447888 (master)

(cherry picked from commit 9000deb734)
Change-Id: I83b9fbe87c27433e178583411b87a68b8efaf58e
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457251
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Vitaliy Mysak
5242a14b30 ocf: use vbdev_ocf_mngt_ interface in register path
This patch is a preparation for adopting ocf_cache_trylock() function.
Register OCF bdev path uses vbdev_ocf_mngt_ interface now
Register stays synchronous blocking operation in this patch,
 but with adoption of ocf_cache_trylock() function,
 register will be asynchronous, in which case we
 want to use mngt_ interface.

This series of OCF patches will enable WriteBack support for OCF bdev.
There is a lot of preparation before we will be able
 to actually implement WriteBack.
Dependencies look like this:
- WriteBack
  - Cleaner
    - trylock
  - Persistent metadata
    - asynchronous management API

Cleaner is a background agent that does synchronization
 of data between cache and its cores.
 Cleaner usually runs every ~30 seconds to perform cleaning.
 The synchronization is a simmilar operation to OCF management flushes.
We need cleaner for WriteBack because only WriteBack mode
 produces dirty data that cleaner needs to deal with.
Cleaner requires adopting trylock() because in current version
 cleaner uses management lock when performs cleaning,
 which may lead to deadlocks if cleaner runs on
 the same thread as management operations.

Peristent metadata is functionality of OCF
 that allows to restore cache state after shutdown
We need persistent metadata in context of shutdown
 with some data being dirty which may only happen
 when using WriteBack mode
Support for persistent metadata requieres
 asynchronous OCF API because in current version
 we will have a deadlock during metadata initialization
 because it is required to be done on different thread
 than cache initialization.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455225 (master)

(cherry picked from commit c3d044cbd7)
Change-Id: I45d84a5fa0c96581d522050dad186b06d489226e
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457244
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-17 15:25:31 +00:00
Maciej Szwed
10698ea595 blobstore: Remove blob on blobstore load when required
In some cases user may want to flag blob for removal
then do some operations (before removing it) and while
it happens there might be power failure. In such cases
we should remove this blob on next blobstore load.
Example of such usage is delete snapshot functionality
that will be introduced in upcoming patch.

Signed-off-by: Maciej Szwed <maciej.szwed@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453835 (master)

(cherry picked from commit 92cafd1586)
Change-Id: I85f396b73762d2665ba8aec62528bb224acace74
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457273
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-17 14:07:45 +00:00
Maciej Szwed
9c52d301db blobstore: Move _spdk_blob_set_thin_provision function
This patch moves _spdk_blob_set_thin_provision function
higher in the file as it will be later used during
blobstore load.

Signed-off-by: Maciej Szwed <maciej.szwed@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455488 (master)

(cherry picked from commit 543d8b7b67)
Change-Id: Ife37ef8c69b88903646b2002b3561101c1eb5135
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457272
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-17 14:07:45 +00:00
Tianyu yang
1256453f92 rte_vhost: fix deadlock on rte_vhost_driver_unregister()
when qemu connect to vhost, but don't send msg to vhost. We use
kill -15 to destroy vhost process. it will lead to deadlock.
(A)
* rte_vhost_driver_unregister()
 * pthread_mutex_lock hold vhost_user.mutex (1)
 * wait TAILQ_FIRST(&vsocket->conn_list) is NULL
(B)
* fdset_event_dispatch()
 * vhost_user_read_cb() start
   * vhost_user_msg_handler() start
   * dev->notify_ops is NULL because qemu just connect, no message recv.
   * vhost_driver_callback_get()
     * pthread_mutex_lock hold vhost_user.mutex (2)

(A) & (B) deadlock

To avoid this scenes, when qemu connect in vhost_new_device()
initialize dev->notify_ops

Signed-off-by: Tianyu yang <yangtianyu2@huawei.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454832 (master)

(cherry picked from commit 151a357ca3)
Change-Id: Iaf699da41dfa3088cfc0f09688b50fada6b2c8d6
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457269
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-17 14:07:45 +00:00
Jim Harris
d77f8f48e6 nvmf: increase default max num qps to 128
This matches the Linux kernel target.  Users can
still decrease this default when creating the
transport (i.e. -p option for nvmf_create_transport
in rpc.py).

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454820 (master)

(cherry picked from commit bf647c168a)
Change-Id: Icad59350a2cd35cfc4ad76d06399345191680c05
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457243
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
2019-06-17 14:07:45 +00:00
Seth Howell
90f2eb1863 rdma: add check for allocating too many SRQ.
We could run into issues with this if we were using an arbitrarily large
amount of cores to run SPDK.

Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452250 (master)

(cherry picked from commit 61948a1ca7)
Change-Id: Ia7add027d7e6ef1ccb4a69ac328dbdf4f2751fd8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457236
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
2019-06-17 14:07:45 +00:00
Vitaliy Mysak
d5e3f80d0f ocf: add timeout functionality for vbdev_ocf_mngt_ interface
Allow user to set timeout for poller in management operations.
Now also all management pollers have 5 sec default timeout.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453655 (master)

(cherry picked from commit c967d539d8)
Change-Id: Ic75f2b150ef21ccd673b80aa84f16c9a24f90e32
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457238
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-17 10:02:50 +00:00
Vitaliy Mysak
f282384991 ocf: add vbdev_ocf_mngt_stop() function
Add stop function to management interface.
It is needed for error handling when execution has to be aborted early.

Example flow:
```
rc = op();
if (rc) {
   handle();
   vbdev_ocf_mngt_stop();
} else {
   vbdev_ocf_mngt_continue();
}
```

This can be improved in the future, because currently, error
  handling cannot be a management operation on its own (but should be).

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453654 (master)

(cherry picked from commit bbbe9e1ce6)
Change-Id: I9ba528db8a9957ee561e5c1b5528b16bd143d5d8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457237
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-17 10:02:50 +00:00
Jim Harris
e0145cc2a7 test/ocf: print just basename of test script for timing
Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454359 (master)

(cherry picked from commit b883f3a036)
Change-Id: I3392956a841d7c4c2e8748940b7e1d7838bdb5d2
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457234
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
2019-06-17 10:02:50 +00:00
Vitaliy Mysak
f176690ec7 ocf: split remove_base() function
Replace remove_base() function by smaller ones:
  detach_cache(), remove_cache_bdev(),
  detach_core(), remove_core_bdev()

This change is necessary for implementing asynchronous unregister using
  trylock API.

Also introduce stop status variable because unregister path has changed.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452416 (master)

(cherry picked from commit 27ddbb7393)
Change-Id: I62599cafacdba685848bd7d32d3d5245907ee4a1
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457233
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-17 10:02:50 +00:00
Vitaliy Mysak
2577a292ef ocf: reorder management functions
Reorder function for register and unregister path to make code more
  readable.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452415 (master)

(cherry picked from commit b29ec8a261)
Change-Id: I3479b231de1f6a4f84f9538f345e62eb73e6847c
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457232
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-17 10:02:50 +00:00
Vitaliy Mysak
6381e4749d ocf: make stop_vbdev() function a step of unregister_path[]
stop_vbdev() is management a function so it should be one of the steps
  of unregister_path[]. It will have to be when stoping is asynchronous,
  but right now it is not a hard requirement.

remove_base() no longer calls stop_vbdev() because that was actually a
  dead code.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453653 (master)

(cherry picked from commit 1ddc8cb53a)
Change-Id: Ie2d87da0fbe7807efea084181ea386b323e6b9d8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457231
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-17 10:02:50 +00:00
Jim Harris
611e2f7823 iscsi: fix hang on high QD large reads
We throttle the number of data_in operations per
connection.  Currently after a read is completed,
we try to send more data_in operations since one
has just been completed.

But we are trying to send more too early.  The data_in_cnt
doesn't actually get decremented until after the PDU is
written on the socket.  So this results in a case
where data_in_cnt == 64, and all 64 read operations
complete before any of those 64 are actually transmitted
onto the TCP socket.  There are no more read operations
waiting, so we won't try to handle the data_in list
again, and if none of these 64 resulted in a SCSI
command completing, then the initiator may not send us
any more read I/O which would have also kicked the data_in
list.

So the solution is to kick the data_in list after the
PDU has been written - not after a read I/O is completed
back from the SCSI layer.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455454 (master)

(cherry picked from commit 59a1fbe937)
Change-Id: Ia01cf96e8eb6e08ddcaaeff449386e78de7c5bc5
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457271
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: GangCao <gang.cao@intel.com>
2019-06-16 14:44:50 +00:00
Jim Harris
5f697b3148 iscsi: free pdus in hot remove path with no lun
The datain handling code path will set the LUN to
NULL if it finds a task's LUN has been hotremoved.
This could happen before the iscsi hotplug routine
actually gets a chance to run.  If this happens,
one of these tasks doesn't actually get freed, and
then will be freed after the lun is closed -
causing a segfault in the bdev layer since it may
have a bdev_io associated with it.

Found by running the iscsi_tgt/fio test after
applying the next patch in this series.

There's more work needed in this hot remove clean up
path - currently we are just freeing a lot of PDUs
rather than completing them with error status when
a LUN is hot removed.  But let's tackle that
separately.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455460 (master)

(cherry picked from commit 462c12d9e9)
Change-Id: I8d27f0c7a79ae91cb6504e5ff6ffc8e346c9e54c
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457270
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
2019-06-16 14:44:50 +00:00
Liu Xiaodong
01088b6906 test/notify: fix parameters' mismatching
Previous test cases got passed, is because all parameters
are filtered to be same accidentally, for example:
Previous, they are
	event=bdev_register:66ab4189
	ev_type=bdev_register:66ab4189
	ev_ctx=bdev_register:66ab4189
	ex_ev_type='bdev_register:[[:alnum:]-]+'
	ex_ev_ctx='bdev_register:[[:alnum:]-]+'
But actually they should be:
	event=bdev_register:66ab4189
	ev_type=bdev_register
	ev_ctx=66ab4189
	ex_ev_type='bdev_register'
	ex_ev_ctx='[[:alnum:]-]+'

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

(cherry picked from commit 31736dc25c)
Change-Id: I7a2dc801931f792a39fc2775d883679cf8185fd0
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457240
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
2019-06-16 14:44:50 +00:00
yidong0635
abb0ccd40a lib/ftl:fix scanbuild error in ftl_anm.c
Here we should consider about that ctrlr may be NULL,
so add assert here.

Signed-off-by: yidong0635 <dongx.yi@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454546 (master)

(cherry picked from commit 1c8efbdd51)
Change-Id: If4c8b2c6382ae6fdad541168d2e2b856fb5b8182
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457239
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-16 14:44:50 +00:00
Pawel Kaminski
4bf1f64f56 makefile: Add cc.flags.mk to .gitignore list
If user defines some flags then cc.flags.mk
file is generated. This causes tests to exit with 1.

This change help testing delete snapshot feature
where we need to define flag by command:
  export CFLAGS=-DSPDK_ENABLE_SNAPSHOT_DELETION

Signed-off-by: Pawel Kaminski <pawelx.kaminski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454457 (master)

(cherry picked from commit 9abbab3647)
Change-Id: I6ddd52d6260393785269e7f34a4b65bf95e5c4e2
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457235
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
2019-06-16 14:44:50 +00:00
Jim Harris
94b8126d8a test/nvme: make reset test exit 0 on QEMU SSDs
There are some QEMU bugs with resets for NVMe emulation.
It simply hasn't been tested for this test's very
stressful reset scenarios.

Since this test is failing the nightly builds fairly
regularly on VMs, just have this test print an
error message and exit 0 when it finds a QEMU SSD.

This will also allow us to enable this test per-patch
in a future patch.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454517 (master)

(cherry picked from commit 223a87b023)
Change-Id: I1013f1d84ab4d0e13f713fe99352b011d77dd1f8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457230
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 14:44:50 +00:00
GangCao
93be2ada98 iscsi: fix double free when failed to start target
When iSCSI target failed to start due to insuccificent resource like PDU pool,
one memory is double freed.

Signed-off-by: GangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453981 (master)

(cherry picked from commit e358eaeeea)
Change-Id: I1b68d4f0f130b024be9f8406c8d1611e92a27787
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457225
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: GangCao <gang.cao@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 14:44:50 +00:00
Ziye Yang
754c217d09 blobfs: fix the wrong parameter in spdk_file_close
According to my code understanding, should be assigned
itself instead of req.

Signed-off-by: Ziye Yang <ziye.yang@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452120 (master)

(cherry picked from commit dfbbcc74dd)
Change-Id: I0af4d56f8029269e0632bb6be6c9d912c7106cf8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457213
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 14:44:50 +00:00
Richael Zhuang
c7658dea37 sock: fix a uninitialized-variable error
Valgrind reports error "epoll_ctl(event) points to uninitiazlized
byte(s)" when running unit test. Fix it by initializing variable event
to a known state.

Signed-off-by: Richael Zhuang <richael.zhuang@arm.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453525 (master)

(cherry picked from commit 09a782dcff)
Change-Id: I756687c1077eeb632c045c316a76714aa453b918
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457210
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Tomasz Zawadzki
a39873a5e5 test/raid: switch from config file to RPC
bdev_raid.sh was using configuration file (bdev.conf.in)
made for blockdev.sh. Changes in that config file affected
the raid tests.

Since the test actually only used two malloc devices as
raid bases, switching to RPC makes it simpler clearer
to understand what is used in tests. Additionally
making raid tests standalone from blockdev.sh.

Fixes issue #777

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

(cherry picked from commit 9011f2401b)
Change-Id: Ia4c5858852241a9fd8212690aefbf015c98d1b57
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457209
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Tomasz Zawadzki
a715b454e9 test/raid: always call rpc_py with correct socket
Previously the socket was only used in single rpc call,
upcoming patch will use of the $rpc_py.
Moving socket to $rpc_py simplifies calling it in multiple
parts of the script.

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

(cherry picked from commit a394f62868)
Change-Id: Id1ba86740237c32a6f0259562c0b5c11d917bbcf
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457208
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Karol Latecki
12466d1ae3 scripts/rpc.py: fix pipe for whitespace separated list arguments
Ordinary python str.split() will by default split on each whitespace.
This includes arguments for rpc.py which expect a whitespace separated list,
eg. construct_raid_bdev -b "Bdev_1 Bdev_2".
shlex.split() prevents splitting on quoted arguments.

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

(cherry picked from commit 22c3befd3d)
Change-Id: If37eb87cf82a161263f2b247baff5c8a77c43efc
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457222
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Vitaliy Mysak
d5aeeaf2f7 ocf: adopt examine to asynchronous construct
Make examine work with asynchronous bdev startup.

We need to count references of bdevs that are being examined,
  for the case when single cache bdev is referenced by multiple OCF
  vbdevs.

The construct function is not in fact asynchronous yet,
  but will be after adopting "trylock" API. Adopting trylock
  requires a lot of changes, so this patch is really to split
  implementation.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/450033 (master)

(cherry picked from commit ac2b06c809)
Change-Id: I6ac091f2dd48462e74aa89cf54acb0306c30673b
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457207
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Darek Stojaczyk
18a977f289 test/ocf: add missing test completion report
This way we can track which machine runs OCF tests.

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453542 (master)

(cherry picked from commit 937e10b1f6)
Change-Id: I51ad8f467965ae7051caac06b834a9db9f0b1a8d
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457206
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
f8c1f991f0 rpc.py: detect stdin pipe
If user calls rpc.py with no parameters, it currently
hangs, waiting for input.  It should print help in this
case instead.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453431 (master)

(cherry picked from commit ac0824b2d8)
Change-Id: I5939999c57b8db0916267935d79ccc1a3201748b
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457221
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
9cbb4af809 test/bdevio: allow reset test to fail on NVMe
NVMe-oF target doesn't support reset yet - but we want
to use bdevio to test other NVMe-oF target functionality
in the next patch.

An issue will be filed against the reset support so
that it gets added.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452935 (master)

(cherry picked from commit 4460761f22)
Change-Id: I84b2be9268a344ee9e613a39487345dc1b8187bf
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457205
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Shuhei Matsumoto
c2d4486dba bdev/raid: Make destroy_raid_bdev RPC wait for completion by callback
This is the end of the patch series.

Make destroy_raid_bdev RPC Wait for completion of spdk_bdev_unregister
to the raid bdev by using callback function.

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

(cherry picked from commit bc49bbe232)
Change-Id: I3ed157ee71e3b8e6dc14b5b66732baba516eacce
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457561
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Shuhei Matsumoto
30c4390ea0 bdev/raid: Process only the first call of destroy_raid_bdev RPC
We have to process only the first call of destroy_raid_bdev RPC
for the same RAID bdev.

The existing flag destruct_called cannot be used for that purpose
because of the following reason.

destruct_called is set to true in both of
- destroy_raid_bdev RPC
- hot removal of any base bdev.
If destruct_called is set in destroy_raid_bdev RPC, destroy_raid_bdev
RPC must return immediately, but if destruct_called is set in hot
removal of any base bdev, destroy_raid_bdev RPC must go forward
with the current logic.

Hence add another flag destroy_started to struct raid_bdev and
use it.

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

(cherry picked from commit 0d9a2b504a)
Change-Id: Ifeefcaa1d289499342d8bb9bc162ded65e0368dd
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457560
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Seth Howell
de271dbe13 nvmf: add srq opts to get_nvmf_transports method.
Print these out for the RDMA transport.

Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452272 (master)

(cherry picked from commit cbf74b20b3)
Change-Id: I44ab01088fcab180540a93e024855322036241db
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457204
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Seth Howell
f6823c5907 rdma: add a flag for disabling srq.
There are cases where srq can be a detriment. Add a flag to allow users
to disable srq even if they have a piece of hardware that supports it.

Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452271 (master)

(cherry picked from commit 350e429a57)
Change-Id: Ia3be8e8c8e8463964e6ff1c02b07afbf4c3cc8f7
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457195
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Seth Howell
e30e5d7c79 rdma: clean up the create_transport rpc docs
Just a couple minor clarifications.

Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452270 (master)

(cherry picked from commit 9d0e11d4a2)
Change-Id: I6c368d263296f742d5bfb0df431d3bf40c800c6c
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457194
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Seth Howell
d353ce1982 nvme_rdma: don't send split sgl requests inline.
In order to truly support multi-sgl inline requests in the RDMA
transport, we would need to increase the size of the
spdk_nvme_rdma_req object dramatically. This is because we would need
enough ibv_sge objects in it to support up to the maximum number of SGEs
supported by the target (for SPDK that is up to 16). Instead of doing
that or creating a new pool of shared ibv_sge objects to support that
case, just send split multi-sgl requests through the regular sgl path.

Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452266 (master)

(cherry picked from commit eb6006c242)
Change-Id: I78313bd88f3ed1cea3b772d9476a00087f49a4dd
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457581
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
850a5b642a build: add full version to SONAME for shared libraries
Fixes issue #781.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452895 (master)

(cherry picked from commit cb0c0509f4)
Change-Id: Ic0793721cb996ec01286ff21ed10fe2076b706ec
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457193
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
ca3a5cf8de test/nvmf: fix host/fio.sh test
get_lvs_free_mb only takes a UUID argument, not
a friendly name.  So revert that part of the changes
to this script made previously.

Also fix ordering of nested lvolstore and lvol names.

This fixes last night's nightly test failures for
nvmf.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453007 (master)

(cherry picked from commit 7685a48fd8)
Change-Id: I408ed787b6ff43314dd432c9fa7d9f5882c3d071
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457192
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
820d0320dd autopackage: move tarball build to nightly testing
There's not a lot of value in building from the
tarballs on every patch.  The git status --porcelain
check is still good on every patch though.  So
return early if it's not the nightly test - this may
cut up 90 seconds on some tests.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452810 (master)

(cherry picked from commit 4de00fed67)
Change-Id: I351a43b802061fe7d7bc4556b3b003a9ec73833f
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457191
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
adb85a252d test/rocksdb: suppress leak reports on thread local ctx
Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452732 (master)

(cherry picked from commit 90586a7dca)
Change-Id: I77b9f640d75c12ec083bec791506bed921e26292
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457190
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
6df4d14eec test/nvmf: simplify host/fio.sh
We don't need to use the UUIDs for lvolstores and
lvols in the nightly test - just use the names that
we've specified.

Also remove the bdev loops - there's only one namespace
per subsystem.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452772 (master)

(cherry picked from commit 59955106a6)
Change-Id: I684b72ca4472009dd8bc49f5221a7937769f1ab8
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457189
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
ade2511df2 scripts/rpc.py: allow users to pipe multiple requests
Users can now pipe a large number of requests to
rpc.py, separated by newlines - each line will be
executed as if it was passed to rpc.py individually.

There is significant savings using this feature when
executing multiple requests through rpc.py.  On my
system, a loop of 30 RPCs related to setting up
10 NVMf subsystems takes 5 seconds when executed
one at a time.  With this new feature, it takes
less than 1 second.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452770 (master)

(cherry picked from commit 363fe506bc)
Change-Id: Iec957ca67461af8e8c41aee47e1d113714b22d3d
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457220
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Jim Harris
02b29614e7 scripts/rpc.py: add call_rpc_func()
This makes no functional change to the script, but
it prepares for an upcoming change allowing callers
to pipe a newline delimited list of rpc calls.

Signed-off-by: Jim Harris <james.r.harris@intel.com>

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452769 (master)

(cherry picked from commit 6895f0f27e)
Change-Id: I695ca61510f9edd336713e88d134e42c1d78a1b4
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457219
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-06-16 08:46:05 +00:00
Darek Stojaczyk
a9085b08c3 thread: fix deadlock in spdk_for_each_thread error handling
We could return from spdk_for_each_thread() without
unlocking the global threading mutex, rendering the
entire SPDK application useless.

Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452087 (master)

(cherry picked from commit 7b3f411063)
Change-Id: I641c7b36db996f9a36310332279648014579de83
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457188
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2019-06-16 08:46:05 +00:00
Tomasz Zawadzki
cf0daf7f3b ocf: add callback argument to vbdev_ocf_construct()
Add callback for construct function.
It is not asynchronous yet, but will be after
  adopting asynchronous OCF API

Also adopt RPC construct call for this change.
This is done in this patch because (1) change is small (2) leaving
  implementation as TODO still requires implementing a mock because we
  decided that callback should be required rather than optional.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Change-Id: Ib6a78e2caf34ac057d4da53ad5dda47163e8a089
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452146 (master)
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457187
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-12 13:09:46 +00:00
Tomasz Zawadzki
5ba7fb92c6 ocf: pass vbdev in callback of mngt_ interface
Add vbdev as another argument in callback of vbdev management operations.
This is nice for async version of vbdev_ocf_construct() which uses mngt_
  interface and creates vbdev structure.

Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Change-Id: I8c88e0a881855b9f22fcf1f8174c888f3cfd6828
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/452145 (master)
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457186
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2019-06-12 13:09:46 +00:00
Darek Stojaczyk
3706702904 version: 19.04.1-pre
Change-Id: I87b4e4a9573b1361fcaef12d363a426ba606637d
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453252
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: SPDK CI Jenkins <sys_sgci@intel.com>
2019-05-10 22:32:26 +00:00
80 changed files with 2818 additions and 700 deletions

1
.gitignore vendored
View File

@ -27,4 +27,5 @@ CONFIG.local
.settings
mk/cc.mk
mk/config.mk
mk/cc.flags.mk
PYTHON_COMMAND

View File

@ -1,5 +1,22 @@
# Changelog
## v19.04.2: (Upcoming Release)
## v19.04.1:
### NVMe-oF Target
Increased default maximum number of queue pairs to 128 in order to match
Linux kernel target. Users can still decrease this default when
creating the transport (i.e. -p option for nvmf_create_transport in rpc.py).
Shared receive queue can now be disabled even for NICs that support it using the
`nvmf_create_transport` RPC method parameter `no_srq`. The actual use of a shared
receive queue is predicated on hardware support when this flag is not used.
### DPDK
Added DPDK 19.05 support
## v19.04:
### nvme

View File

@ -63,10 +63,12 @@ endif
ifeq ($(CONFIG_IPSEC_MB),y)
LIB += ipsecbuild
DPDK_DEPS += ipsecbuild
endif
ifeq ($(CONFIG_ISAL),y)
LIB += isalbuild
DPDK_DEPS += isalbuild
endif
all: $(DIRS-y)
@ -78,9 +80,7 @@ install: all
$(Q)echo "Installed to $(DESTDIR)$(CONFIG_PREFIX)"
ifneq ($(SKIP_DPDK_BUILD),1)
ifeq ($(CONFIG_ISAL),y)
dpdkbuild: isalbuild
endif
dpdkbuild: $(DPDK_DEPS)
endif
shared_lib: lib

View File

@ -10,8 +10,7 @@ out=$PWD
MAKEFLAGS=${MAKEFLAGS:--j16}
cd $rootdir
timing_enter autopackage
timing_enter porcelain_check
$MAKE clean
if [ `git status --porcelain --ignore-submodules | wc -l` -ne 0 ]; then
@ -19,6 +18,14 @@ if [ `git status --porcelain --ignore-submodules | wc -l` -ne 0 ]; then
git status --porcelain --ignore-submodules
exit 1
fi
timing_exit porcelain_check
if [ $RUN_NIGHTLY -eq 0 ]; then
timing_finish
exit 0
fi
timing_enter autopackage
spdk_pv=spdk-$(date +%Y_%m_%d)
spdk_tarball=${spdk_pv}.tar

View File

@ -779,14 +779,14 @@ Example response:
Construct new OCF bdev.
Command accepts cache mode that is going to be used.
Currently, we support Write-Through and Pass-Through OCF cache modes.
Currently, we support Write-Through, Pass-Through and Write-Back OCF cache modes.
### Parameters
Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
name | Required | string | Bdev name to use
mode | Required | string | OCF cache mode ('wt' or 'pt')
mode | Required | string | OCF cache mode ('wb' or 'wt' or 'pt')
cache_bdev_name | Required | string | Name of underlying cache bdev
core_bdev_name | Required | string | Name of underlying core bdev
@ -3487,6 +3487,8 @@ io_unit_size | Optional | number | I/O unit size (bytes)
max_aq_depth | Optional | number | Max number of admin cmds per AQ
num_shared_buffers | Optional | number | The number of pooled data buffers available to the transport
buf_cache_size | Optional | number | The number of shared buffers to reserve for each poll group
max_srq_depth | Optional | number | The number of elements in a per-thread shared receive queue (RDMA only)
no_srq | Optional | boolean | Disable shared receive queue even for devices that support it. (RDMA only)
### Example:

View File

@ -46,6 +46,7 @@ ifeq ($(CONFIG_CRYPTO),y)
CRYPTO_ENABLED = y
DPDK_OPTS += CONFIG_RTE_LIBRTE_PMD_AESNI_MB=y
DPDK_CFLAGS += -I$(IPSEC_MB_DIR)
DPDK_LDFLAGS += -L$(IPSEC_MB_DIR)
DPDK_OPTS += CONFIG_RTE_LIBRTE_REORDER=y
DPDK_OPTS += CONFIG_RTE_LIBRTE_PMD_QAT=y
DPDK_OPTS += CONFIG_RTE_LIBRTE_PMD_QAT_SYM=y
@ -67,6 +68,7 @@ endif
ifeq ($(CONFIG_REDUCE),y)
DPDK_OPTS += CONFIG_RTE_LIBRTE_PMD_ISAL=y
DPDK_CFLAGS += -I$(ISAL_DIR)
DPDK_LDFLAGS += -L$(ISAL_DIR)/.libs
else
DPDK_OPTS += CONFIG_RTE_LIBRTE_PMD_ISAL=n
endif
@ -117,7 +119,7 @@ $(SPDK_ROOT_DIR)/dpdk/build:
$(Q)$(MAKE) -C $(SPDK_ROOT_DIR)/dpdk config T=$(DPDK_CONFIG) $(DPDK_OPTS)
all: $(SPDK_ROOT_DIR)/dpdk/build
$(Q)$(MAKE) -C $(SPDK_ROOT_DIR)/dpdk/build EXTRA_CFLAGS="$(DPDK_CFLAGS)" MAKEFLAGS="T=$(DPDK_CONFIG) -j$(NPROC)" $(DPDK_OPTS)
$(Q)$(MAKE) -C $(SPDK_ROOT_DIR)/dpdk/build EXTRA_CFLAGS="$(DPDK_CFLAGS)" EXTRA_LDFLAGS="$(DPDK_LDFLAGS)" MAKEFLAGS="T=$(DPDK_CONFIG) -j$(NPROC)" $(DPDK_OPTS)
clean:
$(Q)rm -rf $(SPDK_ROOT_DIR)/dpdk/build

View File

@ -49,6 +49,12 @@
#include "fio.h"
#include "optgroup.h"
/* FreeBSD is missing CLOCK_MONOTONIC_RAW,
* so alternative is provided. */
#ifndef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif
struct spdk_fio_options {
void *pad;
char *conf;

View File

@ -45,6 +45,12 @@
#include "fio.h"
#include "optgroup.h"
/* FreeBSD is missing CLOCK_MONOTONIC_RAW,
* so alternative is provided. */
#ifndef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif
#define NVME_IO_ALIGN 4096
static bool g_spdk_env_initialized;

View File

@ -132,6 +132,19 @@ struct spdk_app_opts {
/** Opaque context for use of the env implementation. */
void *env_context;
/**
* for passing user-provided log call
*
* \param level Log level threshold.
* \param file Name of the current source file.
* \param line Current source file line.
* \param func Current source function name.
* \param format Format string to the message.
*/
void (* log)(int level, const char *file, const int line,
const char *func, const char *format);
};
/**

View File

@ -45,11 +45,14 @@
extern "C" {
#endif
typedef void logfunc(int level, const char *file, const int line,
const char *func, const char *format);
/**
* Initialize the logging module. Messages prior
* to this call will be dropped.
*/
void spdk_log_open(void);
void spdk_log_open(logfunc *logf);
/**
* Close the currently active log. Messages after this call

View File

@ -64,15 +64,16 @@ struct spdk_json_write_ctx;
struct spdk_nvmf_transport;
struct spdk_nvmf_transport_opts {
uint16_t max_queue_depth;
uint16_t max_qpairs_per_ctrlr;
uint32_t in_capsule_data_size;
uint32_t max_io_size;
uint32_t io_unit_size;
uint32_t max_aq_depth;
uint32_t num_shared_buffers;
uint32_t buf_cache_size;
uint32_t max_srq_depth;
uint16_t max_queue_depth;
uint16_t max_qpairs_per_ctrlr;
uint32_t in_capsule_data_size;
uint32_t max_io_size;
uint32_t io_unit_size;
uint32_t max_aq_depth;
uint32_t num_shared_buffers;
uint32_t buf_cache_size;
uint32_t max_srq_depth;
bool no_srq;
};
/**

View File

@ -54,12 +54,12 @@
* Patch level is incremented on maintenance branch releases and reset to 0 for each
* new major.minor release.
*/
#define SPDK_VERSION_PATCH 0
#define SPDK_VERSION_PATCH 2
/**
* Version string suffix.
*/
#define SPDK_VERSION_SUFFIX ""
#define SPDK_VERSION_SUFFIX "-pre"
/**
* Single numeric value representing a version number for compile-time comparisons.

View File

@ -2903,6 +2903,11 @@ spdk_bdev_write_zeroes_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channe
return -EINVAL;
}
if (!_spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE_ZEROES) &&
!_spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE)) {
return -ENOTSUP;
}
bdev_io = spdk_bdev_get_io(channel);
if (!bdev_io) {
@ -2919,16 +2924,15 @@ spdk_bdev_write_zeroes_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channe
if (_spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE_ZEROES)) {
spdk_bdev_io_submit(bdev_io);
return 0;
} else if (_spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE)) {
assert(spdk_bdev_get_block_size(bdev) <= ZERO_BUFFER_SIZE);
bdev_io->u.bdev.split_remaining_num_blocks = num_blocks;
bdev_io->u.bdev.split_current_offset_blocks = offset_blocks;
_spdk_bdev_write_zero_buffer_next(bdev_io);
return 0;
} else {
spdk_bdev_free_io(bdev_io);
return -ENOTSUP;
}
assert(_spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE));
assert(spdk_bdev_get_block_size(bdev) <= ZERO_BUFFER_SIZE);
bdev_io->u.bdev.split_remaining_num_blocks = num_blocks;
bdev_io->u.bdev.split_current_offset_blocks = offset_blocks;
_spdk_bdev_write_zero_buffer_next(bdev_io);
return 0;
}
int

View File

@ -693,6 +693,7 @@ _reduce_destroy_cb(void *ctx, int reduce_errno)
}
comp_bdev->vol = NULL;
spdk_put_io_channel(comp_bdev->base_ch);
spdk_bdev_unregister(&comp_bdev->comp_bdev, comp_bdev->delete_cb_fn,
comp_bdev->delete_cb_arg);
}
@ -703,11 +704,12 @@ delete_vol_unload_cb(void *cb_arg, int reduce_errno)
{
struct vbdev_compress *comp_bdev = (struct vbdev_compress *)cb_arg;
/* Close the underlying bdev. */
spdk_bdev_close(comp_bdev->base_desc);
if (reduce_errno) {
SPDK_ERRLOG("number %d\n", reduce_errno);
} else {
/* reducelib needs a channel to comm with the backing device */
comp_bdev->base_ch = spdk_bdev_get_io_channel(comp_bdev->base_desc);
/* Clean the device before we free our resources. */
spdk_reduce_vol_destroy(&comp_bdev->backing_dev, _reduce_destroy_cb, comp_bdev);
}
@ -1300,6 +1302,7 @@ vbdev_reduce_load_cb(void *cb_arg, struct spdk_reduce_vol *vol, int reduce_errno
/* Done with metadata operations */
spdk_put_io_channel(meta_ctx->base_ch);
spdk_bdev_close(meta_ctx->base_desc);
meta_ctx->base_desc = NULL;
if (reduce_errno != 0) {
/* This error means it is not a compress disk. */

View File

@ -579,12 +579,14 @@ void
vbdev_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
{
struct vbdev_lvol_destroy_ctx *ctx;
size_t count;
assert(lvol != NULL);
assert(cb_fn != NULL);
/* Check if it is possible to delete lvol */
if (spdk_lvol_deletable(lvol) == false) {
spdk_blob_get_clones(lvol->lvol_store->blobstore, lvol->blob_id, NULL, &count);
if (count > 1) {
/* throw an error */
SPDK_ERRLOG("Cannot delete lvol\n");
cb_fn(cb_arg, -EPERM);

View File

@ -225,11 +225,11 @@ vbdev_ocf_ctx_data_seek(ctx_data_t *dst, ctx_data_seek_t seek, uint32_t offset)
switch (seek) {
case ctx_data_seek_begin:
off = MIN(off, d->size);
off = MIN(offset, d->size);
d->seek = off;
break;
case ctx_data_seek_current:
off = MIN(off, d->size - d->seek);
off = MIN(offset, d->size - d->seek);
d->seek += off;
break;
}
@ -288,31 +288,185 @@ vbdev_ocf_ctx_data_secure_erase(ctx_data_t *ctx_data)
}
}
int vbdev_ocf_queue_create(ocf_cache_t cache, ocf_queue_t *queue, const struct ocf_queue_ops *ops)
{
int rc;
struct vbdev_ocf_cache_ctx *ctx = ocf_cache_get_priv(cache);
pthread_mutex_lock(&ctx->lock);
rc = ocf_queue_create(cache, queue, ops);
pthread_mutex_unlock(&ctx->lock);
return rc;
}
void vbdev_ocf_queue_put(ocf_queue_t queue)
{
ocf_cache_t cache = ocf_queue_get_cache(queue);
struct vbdev_ocf_cache_ctx *ctx = ocf_cache_get_priv(cache);
pthread_mutex_lock(&ctx->lock);
ocf_queue_put(queue);
pthread_mutex_unlock(&ctx->lock);
}
void vbdev_ocf_cache_ctx_put(struct vbdev_ocf_cache_ctx *ctx)
{
if (env_atomic_dec_return(&ctx->refcnt) == 0) {
pthread_mutex_destroy(&ctx->lock);
free(ctx);
}
}
void vbdev_ocf_cache_ctx_get(struct vbdev_ocf_cache_ctx *ctx)
{
env_atomic_inc(&ctx->refcnt);
}
struct cleaner_priv {
struct spdk_poller *poller;
ocf_queue_t queue;
uint64_t next_run;
};
static int
cleaner_poll(void *arg)
{
ocf_cleaner_t cleaner = arg;
struct cleaner_priv *priv = ocf_cleaner_get_priv(cleaner);
uint32_t iono = ocf_queue_pending_io(priv->queue);
int i, max = spdk_min(32, iono);
for (i = 0; i < max; i++) {
ocf_queue_run_single(priv->queue);
}
if (spdk_get_ticks() >= priv->next_run) {
ocf_cleaner_run(cleaner, priv->queue);
return 1;
}
if (iono > 0) {
return 1;
} else {
return 0;
}
}
static void
cleaner_cmpl(ocf_cleaner_t c, uint32_t interval)
{
struct cleaner_priv *priv = ocf_cleaner_get_priv(c);
priv->next_run = spdk_get_ticks() + ((interval * spdk_get_ticks_hz()) / 1000);
}
static void
cleaner_queue_kick(ocf_queue_t q)
{
}
static void
cleaner_queue_stop(ocf_queue_t q)
{
struct cleaner_priv *cpriv = ocf_queue_get_priv(q);
if (cpriv) {
spdk_poller_unregister(&cpriv->poller);
free(cpriv);
}
}
const struct ocf_queue_ops cleaner_queue_ops = {
.kick_sync = cleaner_queue_kick,
.kick = cleaner_queue_kick,
.stop = cleaner_queue_stop,
};
static int
vbdev_ocf_ctx_cleaner_init(ocf_cleaner_t c)
{
/* TODO [writeback]: implement with writeback mode support */
int rc;
struct cleaner_priv *priv = calloc(1, sizeof(*priv));
ocf_cache_t cache = ocf_cleaner_get_cache(c);
struct vbdev_ocf_cache_ctx *cctx = ocf_cache_get_priv(cache);
if (priv == NULL) {
return -ENOMEM;
}
rc = vbdev_ocf_queue_create(cache, &priv->queue, &cleaner_queue_ops);
if (rc) {
free(priv);
return rc;
}
ocf_queue_set_priv(priv->queue, priv);
cctx->cleaner_queue = priv->queue;
ocf_cleaner_set_cmpl(c, cleaner_cmpl);
ocf_cleaner_set_priv(c, priv);
return 0;
}
static void
vbdev_ocf_ctx_cleaner_stop(ocf_cleaner_t c)
{
/* TODO [writeback]: implement with writeback mode support */
struct cleaner_priv *priv = ocf_cleaner_get_priv(c);
vbdev_ocf_queue_put(priv->queue);
}
static int vbdev_ocf_volume_updater_init(ocf_metadata_updater_t mu)
static void
vbdev_ocf_ctx_cleaner_kick(ocf_cleaner_t cleaner)
{
/* TODO [metadata]: implement with persistent metadata support */
struct cleaner_priv *priv = ocf_cleaner_get_priv(cleaner);
if (priv->poller) {
return;
}
/* We start cleaner poller at the same thread where cache was created
* TODO: allow user to specify core at which cleaner should run */
priv->poller = spdk_poller_register(cleaner_poll, cleaner, 0);
}
static void
vbdev_ocf_md_kick(void *ctx)
{
ocf_metadata_updater_t mu = ctx;
ocf_cache_t cache = ocf_metadata_updater_get_cache(mu);
if (ocf_cache_is_running(cache)) {
ocf_metadata_updater_run(mu);
}
}
static int
vbdev_ocf_volume_updater_init(ocf_metadata_updater_t mu)
{
struct spdk_thread *md_thread = spdk_get_thread();
ocf_metadata_updater_set_priv(mu, md_thread);
return 0;
}
static void vbdev_ocf_volume_updater_stop(ocf_metadata_updater_t mu)
static void
vbdev_ocf_volume_updater_stop(ocf_metadata_updater_t mu)
{
/* TODO [metadata]: implement with persistent metadata support */
}
static void vbdev_ocf_volume_updater_kick(ocf_metadata_updater_t mu)
static void
vbdev_ocf_volume_updater_kick(ocf_metadata_updater_t mu)
{
/* TODO [metadata]: implement with persistent metadata support */
struct spdk_thread *md_thread = ocf_metadata_updater_get_priv(mu);
/* We need to send message to updater thread because
* kick can happen from any thread */
spdk_thread_send_msg(md_thread, vbdev_ocf_md_kick, mu);
}
/* This function is main way by which OCF communicates with user
@ -362,10 +516,11 @@ static const struct ocf_ctx_config vbdev_ocf_ctx_cfg = {
.cleaner = {
.init = vbdev_ocf_ctx_cleaner_init,
.stop = vbdev_ocf_ctx_cleaner_stop,
.kick = vbdev_ocf_ctx_cleaner_kick,
},
.logger = {
.printf = vbdev_ocf_ctx_log_printf,
.print = vbdev_ocf_ctx_log_printf,
.dump_stack = NULL,
},

View File

@ -35,6 +35,7 @@
#define VBDEV_OCF_CTX_H
#include <ocf/ocf.h>
#include "spdk/thread.h"
extern ocf_ctx_t vbdev_ocf_ctx;
@ -42,7 +43,24 @@ extern ocf_ctx_t vbdev_ocf_ctx;
#define SPDK_OBJECT 1
/* Context of cache instance */
struct vbdev_ocf_cache_ctx {
ocf_queue_t mngt_queue;
ocf_queue_t cleaner_queue;
struct spdk_io_channel *management_channel;
pthread_mutex_t lock;
env_atomic refcnt;
};
void vbdev_ocf_cache_ctx_put(struct vbdev_ocf_cache_ctx *ctx);
void vbdev_ocf_cache_ctx_get(struct vbdev_ocf_cache_ctx *ctx);
int vbdev_ocf_ctx_init(void);
void vbdev_ocf_ctx_cleanup(void);
/* Thread safe queue creation and deletion
* These are wrappers for original ocf_queue_create() and ocf_queue_put() */
int vbdev_ocf_queue_create(ocf_cache_t cache, ocf_queue_t *queue, const struct ocf_queue_ops *ops);
void vbdev_ocf_queue_put(ocf_queue_t queue);
#endif

View File

@ -145,6 +145,17 @@ static inline void *env_vzalloc(size_t size)
SPDK_MALLOC_DMA);
}
static inline void *env_secure_alloc(size_t size)
{
return spdk_zmalloc(size, 0, NULL, SPDK_ENV_LCORE_ID_ANY,
SPDK_MALLOC_DMA);
}
static inline void env_secure_free(const void *ptr, size_t size)
{
return spdk_free((void *)ptr);
}
static inline void env_vfree(const void *ptr)
{
return spdk_free((void *)ptr);

View File

@ -74,7 +74,12 @@ mngt_poll_fn(void *opaque)
struct vbdev_ocf *vbdev = opaque;
if (vbdev->mngt_ctx.poller_fn) {
vbdev->mngt_ctx.poller_fn(vbdev);
if (vbdev->mngt_ctx.timeout_ts &&
spdk_get_ticks() >= vbdev->mngt_ctx.timeout_ts) {
vbdev_ocf_mngt_continue(vbdev, -ETIMEDOUT);
} else {
vbdev->mngt_ctx.poller_fn(vbdev);
}
}
return 0;
@ -104,11 +109,34 @@ vbdev_ocf_mngt_start(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn *path,
return 0;
}
static void
vbdev_ocf_mngt_poll_set_timeout(struct vbdev_ocf *vbdev, uint64_t millisec)
{
uint64_t ticks;
ticks = millisec * spdk_get_ticks_hz() / 1000;
vbdev->mngt_ctx.timeout_ts = spdk_get_ticks() + ticks;
}
void
vbdev_ocf_mngt_poll(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn fn)
{
assert(vbdev->mngt_ctx.poller != NULL);
vbdev->mngt_ctx.poller_fn = fn;
vbdev_ocf_mngt_poll_set_timeout(vbdev, 5000);
}
void
vbdev_ocf_mngt_stop(struct vbdev_ocf *vbdev)
{
spdk_poller_unregister(&vbdev->mngt_ctx.poller);
if (vbdev->mngt_ctx.cb) {
vbdev->mngt_ctx.cb(vbdev->mngt_ctx.status, vbdev, vbdev->mngt_ctx.cb_arg);
}
memset(&vbdev->mngt_ctx, 0, sizeof(vbdev->mngt_ctx));
}
void
@ -129,9 +157,5 @@ vbdev_ocf_mngt_continue(struct vbdev_ocf *vbdev, int status)
return;
}
spdk_poller_unregister(&vbdev->mngt_ctx.poller);
if (vbdev->mngt_ctx.cb) {
vbdev->mngt_ctx.cb(vbdev->mngt_ctx.status, vbdev->mngt_ctx.cb_arg);
}
memset(&vbdev->mngt_ctx, 0, sizeof(vbdev->mngt_ctx));
vbdev_ocf_mngt_stop(vbdev);
}

View File

@ -49,11 +49,15 @@ int vbdev_ocf_mngt_start(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn *path,
vbdev_ocf_mngt_callback cb, void *cb_arg);
/* Continue execution with polling operation (fn)
* fn must invoke vbdev_ocf_mngt_continue() to stop polling */
* fn must invoke vbdev_ocf_mngt_continue() to stop polling
* Poller has default timeout of 5 seconds */
void vbdev_ocf_mngt_poll(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn fn);
/* Continue execution with next function that is on path
* If next function is NULL, finish management operation and invoke callback */
void vbdev_ocf_mngt_continue(struct vbdev_ocf *vbdev, int status);
/* Stop the execution and invoke callback with last status returned */
void vbdev_ocf_mngt_stop(struct vbdev_ocf *vbdev);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,8 @@
#include "spdk/bdev.h"
#include "spdk/bdev_module.h"
#define VBDEV_OCF_MD_MAX_LEN 4096
struct vbdev_ocf;
/* Context for OCF queue poller
@ -65,6 +67,8 @@ struct vbdev_ocf_state {
bool doing_reset;
/* From the moment when exp_bdev is registered */
bool started;
/* Status of last attempt for stopping this device */
int stop_status;
};
/*
@ -79,11 +83,15 @@ struct vbdev_ocf_config {
/* Core initial config */
struct ocf_mngt_core_config core;
/* Load flag, if set to true, then we will try load cache instance from disk,
* otherwise we will create new cache on that disk */
bool loadq;
};
/* Types for management operations */
typedef void (*vbdev_ocf_mngt_fn)(struct vbdev_ocf *);
typedef void (*vbdev_ocf_mngt_callback)(int, void *);
typedef void (*vbdev_ocf_mngt_callback)(int, struct vbdev_ocf *, void *);
/* Context for asynchronous management operations
* Single management operation usually contains a list of sub procedures,
@ -97,6 +105,8 @@ struct vbdev_ocf_mngt_ctx {
struct spdk_poller *poller;
/* Function that gets invoked by poller on each iteration */
vbdev_ocf_mngt_fn poller_fn;
/* Poller timeout time stamp - when the poller should stop with error */
uint64_t timeout_ts;
/* Status of management operation */
int status;
@ -126,6 +136,9 @@ struct vbdev_ocf_base {
/* True if SPDK bdev has been claimed and opened for writing */
bool attached;
/* Channel for cleaner operations */
struct spdk_io_channel *management_channel;
/* Reference to main vbdev */
struct vbdev_ocf *parent;
};
@ -152,19 +165,27 @@ struct vbdev_ocf {
/* Management context */
struct vbdev_ocf_mngt_ctx mngt_ctx;
/* Cache conext */
struct vbdev_ocf_cache_ctx *cache_ctx;
/* Exposed SPDK bdev. Registered in bdev layer */
struct spdk_bdev exp_bdev;
/* OCF uuid for core device of this vbdev */
char uuid[VBDEV_OCF_MD_MAX_LEN];
/* Link to global list of this type structures */
TAILQ_ENTRY(vbdev_ocf) tailq;
};
int vbdev_ocf_construct(
void vbdev_ocf_construct(
const char *vbdev_name,
const char *cache_mode_name,
const char *cache_name,
const char *core_name);
const char *core_name,
bool loadq,
void (*cb)(int, struct vbdev_ocf *, void *),
void *cb_arg);
/* If vbdev is online, return its object */
struct vbdev_ocf *vbdev_ocf_get_by_name(const char *name);

View File

@ -62,13 +62,31 @@ static const struct spdk_json_object_decoder rpc_construct_ocf_bdev_decoders[] =
{"core_bdev_name", offsetof(struct rpc_construct_ocf_bdev, core_bdev_name), spdk_json_decode_string},
};
static void
construct_cb(int status, struct vbdev_ocf *vbdev, void *cb_arg)
{
struct spdk_jsonrpc_request *request = cb_arg;
struct spdk_json_write_ctx *w;
if (status) {
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"Could not create OCF vbdev: %d",
status);
} else {
w = spdk_jsonrpc_begin_result(request);
if (w) {
spdk_json_write_string(w, vbdev->name);
spdk_jsonrpc_end_result(request, w);
}
}
}
static void
spdk_rpc_construct_ocf_bdev(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
int ret = 0;
struct rpc_construct_ocf_bdev req = {NULL};
struct spdk_json_write_ctx *w;
int ret;
ret = spdk_json_decode_object(params, rpc_construct_ocf_bdev_decoders,
SPDK_COUNTOF(rpc_construct_ocf_bdev_decoders),
@ -76,24 +94,12 @@ spdk_rpc_construct_ocf_bdev(struct spdk_jsonrpc_request *request,
if (ret) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"Invalid parameters");
goto end;
free_rpc_construct_ocf_bdev(&req);
return;
}
ret = vbdev_ocf_construct(req.name, req.mode, req.cache_bdev_name, req.core_bdev_name);
if (ret) {
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
"Could not create OCF vbdev: %s",
spdk_strerror(-ret));
goto end;
}
w = spdk_jsonrpc_begin_result(request);
if (w) {
spdk_json_write_string(w, req.name);
spdk_jsonrpc_end_result(request, w);
}
end:
vbdev_ocf_construct(req.name, req.mode, req.cache_bdev_name, req.core_bdev_name, false,
construct_cb, request);
free_rpc_construct_ocf_bdev(&req);
}
SPDK_RPC_REGISTER("construct_ocf_bdev", spdk_rpc_construct_ocf_bdev, SPDK_RPC_RUNTIME)

View File

@ -44,14 +44,18 @@
#include "vbdev_ocf.h"
static int
vbdev_ocf_volume_open(ocf_volume_t volume)
vbdev_ocf_volume_open(ocf_volume_t volume, void *opts)
{
struct vbdev_ocf_base **priv = ocf_volume_get_priv(volume);
struct vbdev_ocf_base *base = vbdev_ocf_get_base_by_name(ocf_volume_get_uuid(volume)->data);
struct vbdev_ocf_base *base;
if (base == NULL) {
assert(false);
return -EINVAL;
if (opts) {
base = opts;
} else {
base = vbdev_ocf_get_base_by_name(ocf_volume_get_uuid(volume)->data);
if (base == NULL) {
return -ENODEV;
}
}
*priv = base;
@ -167,23 +171,14 @@ vbdev_ocf_volume_submit_io_cb(struct spdk_bdev_io *bdev_io, bool success, void *
io = opaque;
io_ctx = ocf_get_io_ctx(io);
assert(io_ctx != NULL);
if (!success) {
io_ctx->error |= 1;
}
if (io_ctx->offset && bdev_io != NULL) {
switch (bdev_io->type) {
case SPDK_BDEV_IO_TYPE_READ:
case SPDK_BDEV_IO_TYPE_WRITE:
env_free(bdev_io->u.bdev.iovs);
break;
default:
assert(false);
break;
}
if (io_ctx->iovs_allocated && bdev_io != NULL) {
env_free(bdev_io->u.bdev.iovs);
}
if (io_ctx->error) {
@ -212,6 +207,8 @@ prepare_submit(struct ocf_io *io)
struct vbdev_ocf_qcxt *qctx;
struct vbdev_ocf_base *base;
ocf_queue_t q = io->io_queue;
ocf_cache_t cache;
struct vbdev_ocf_cache_ctx *cctx;
int rc = 0;
io_ctx->rq_cnt++;
@ -232,6 +229,14 @@ prepare_submit(struct ocf_io *io)
return 0;
}
cache = ocf_queue_get_cache(q);
cctx = ocf_cache_get_priv(cache);
if (q == cctx->cleaner_queue || q == cctx->mngt_queue) {
io_ctx->ch = base->management_channel;
return 0;
}
qctx = ocf_queue_get_priv(q);
if (qctx == NULL) {
return -EFAULT;
@ -253,11 +258,6 @@ vbdev_ocf_volume_submit_flush(struct ocf_io *io)
struct ocf_io_ctx *io_ctx = ocf_get_io_ctx(io);
int status;
if (base->is_cache) {
io->end(io, 0);
return;
}
status = prepare_submit(io);
if (status) {
SPDK_ERRLOG("Preparing io failed with status=%d\n", status);
@ -302,27 +302,41 @@ vbdev_ocf_volume_submit_io(struct ocf_io *io)
len = io->bytes;
offset = io_ctx->offset;
if (offset) {
i = get_starting_vec(io_ctx->data->iovs, io_ctx->data->iovcnt, &offset);
if (len < io_ctx->data->size) {
if (io_ctx->data->iovcnt == 1) {
if (io->dir == OCF_READ) {
status = spdk_bdev_read(base->desc, io_ctx->ch,
io_ctx->data->iovs[0].iov_base + offset, addr, len,
vbdev_ocf_volume_submit_io_cb, io);
} else if (io->dir == OCF_WRITE) {
status = spdk_bdev_write(base->desc, io_ctx->ch,
io_ctx->data->iovs[0].iov_base + offset, addr, len,
vbdev_ocf_volume_submit_io_cb, io);
}
goto end;
} else {
i = get_starting_vec(io_ctx->data->iovs, io_ctx->data->iovcnt, &offset);
if (i < 0) {
SPDK_ERRLOG("offset bigger than data size\n");
vbdev_ocf_volume_submit_io_cb(NULL, false, io);
return;
if (i < 0) {
SPDK_ERRLOG("offset bigger than data size\n");
vbdev_ocf_volume_submit_io_cb(NULL, false, io);
return;
}
iovcnt = io_ctx->data->iovcnt - i;
io_ctx->iovs_allocated = true;
iovs = env_malloc(sizeof(*iovs) * iovcnt, ENV_MEM_NOIO);
if (!iovs) {
SPDK_ERRLOG("allocation failed\n");
vbdev_ocf_volume_submit_io_cb(NULL, false, io);
return;
}
initialize_cpy_vector(iovs, io_ctx->data->iovcnt, &io_ctx->data->iovs[i],
iovcnt, offset, len);
}
iovcnt = io_ctx->data->iovcnt - i;
iovs = env_malloc(sizeof(*iovs) * iovcnt, ENV_MEM_NOIO);
if (!iovs) {
SPDK_ERRLOG("allocation failed\n");
vbdev_ocf_volume_submit_io_cb(NULL, false, io);
return;
}
initialize_cpy_vector(iovs, io_ctx->data->iovcnt, &io_ctx->data->iovs[i],
iovcnt, offset, len);
} else {
iovs = io_ctx->data->iovs;
iovcnt = io_ctx->data->iovcnt;
@ -336,6 +350,7 @@ vbdev_ocf_volume_submit_io(struct ocf_io *io)
iovs, iovcnt, addr, len, vbdev_ocf_volume_submit_io_cb, io);
}
end:
if (status) {
/* TODO [ENOMEM]: implement ENOMEM handling when submitting IO to base device */

View File

@ -49,6 +49,7 @@ struct ocf_io_ctx {
int ref;
int rq_cnt;
int error;
bool iovs_allocated;
};
int vbdev_ocf_volume_init(void);

View File

@ -633,6 +633,7 @@ vbdev_passthru_register(struct spdk_bdev *bdev)
rc = spdk_bdev_register(&pt_node->pt_bdev);
if (rc) {
SPDK_ERRLOG("could not register pt_bdev\n");
spdk_bdev_module_release_bdev(&pt_node->pt_bdev);
spdk_bdev_close(pt_node->base_desc);
TAILQ_REMOVE(&g_pt_nodes, pt_node, link);
spdk_io_device_unregister(pt_node, NULL);

View File

@ -1848,6 +1848,17 @@ raid_bdev_remove_base_devices(struct raid_bdev_config *raid_cfg,
return;
}
if (raid_bdev->destroy_started) {
SPDK_DEBUGLOG(SPDK_LOG_BDEV_RAID, "destroying raid bdev %s is already started\n",
raid_cfg->name);
if (cb_fn) {
cb_fn(cb_arg, -EALREADY);
}
return;
}
raid_bdev->destroy_started = true;
for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
info = &raid_bdev->base_bdev_info[i];

View File

@ -127,6 +127,9 @@ struct raid_bdev {
/* Set to true if destruct is called for this raid bdev */
bool destruct_called;
/* Set to true if destroy of this raid bdev is started. */
bool destroy_started;
};
/*

View File

@ -337,32 +337,51 @@ static const struct spdk_json_object_decoder rpc_destroy_raid_bdev_decoders[] =
{"name", offsetof(struct rpc_destroy_raid_bdev, name), spdk_json_decode_string},
};
struct rpc_destroy_raid_bdev_ctx {
struct rpc_destroy_raid_bdev req;
struct raid_bdev_config *raid_cfg;
struct spdk_jsonrpc_request *request;
};
/*
* brief:
* Since destroying raid_bdev is asynchronous operation, so this function is
* used to check if raid bdev still exists. If raid bdev is still there it will create
* event and check later, otherwise it will proceed with cleanup
* params:
* arg - pointer to raid bdev cfg
* cb_arg - pointer to the callback context.
* rc - return code of the destruction of the raid bdev.
* returns:
* none
*/
static void
raid_bdev_config_destroy(void *arg)
destroy_raid_bdev_done(void *cb_arg, int rc)
{
struct raid_bdev_config *raid_cfg = arg;
struct rpc_destroy_raid_bdev_ctx *ctx = cb_arg;
struct raid_bdev_config *raid_cfg;
struct spdk_jsonrpc_request *request = ctx->request;
struct spdk_json_write_ctx *w;
assert(raid_cfg != NULL);
if (raid_cfg->raid_bdev != NULL) {
/*
* If raid bdev exists for this config, wait for raid bdev to get
* destroyed and come back later
*/
spdk_thread_send_msg(spdk_get_thread(), raid_bdev_config_destroy,
raid_cfg);
} else {
raid_bdev_config_cleanup(raid_cfg);
if (rc != 0) {
SPDK_ERRLOG("Failed to destroy raid bdev %s (%d): %s\n",
ctx->req.name, rc, spdk_strerror(-rc));
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
spdk_strerror(-rc));
goto exit;
}
raid_cfg = ctx->raid_cfg;
assert(raid_cfg->raid_bdev == NULL);
raid_bdev_config_cleanup(raid_cfg);
w = spdk_jsonrpc_begin_result(request);
if (w == NULL) {
goto exit;
}
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(request, w);
exit:
free_rpc_destroy_raid_bdev(&ctx->req);
free(ctx);
}
/*
@ -379,42 +398,39 @@ raid_bdev_config_destroy(void *arg)
static void
spdk_rpc_destroy_raid_bdev(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
{
struct rpc_destroy_raid_bdev req = {};
struct spdk_json_write_ctx *w;
struct raid_bdev_config *raid_cfg = NULL;
struct rpc_destroy_raid_bdev_ctx *ctx;
ctx = calloc(1, sizeof(*ctx));
if (!ctx) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
spdk_strerror(ENOMEM));
return;
}
if (spdk_json_decode_object(params, rpc_destroy_raid_bdev_decoders,
SPDK_COUNTOF(rpc_destroy_raid_bdev_decoders),
&req)) {
&ctx->req)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"Invalid parameters");
goto invalid;
}
raid_cfg = raid_bdev_config_find_by_name(req.name);
if (raid_cfg == NULL) {
ctx->raid_cfg = raid_bdev_config_find_by_name(ctx->req.name);
if (ctx->raid_cfg == NULL) {
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"raid bdev %s is not found in config", req.name);
"raid bdev %s is not found in config", ctx->req.name);
goto invalid;
}
ctx->request = request;
/* Remove all the base bdevs from this raid bdev before destroying the raid bdev */
raid_bdev_remove_base_devices(raid_cfg, NULL, NULL);
raid_bdev_remove_base_devices(ctx->raid_cfg, destroy_raid_bdev_done, ctx);
raid_bdev_config_destroy(raid_cfg);
free_rpc_destroy_raid_bdev(&req);
w = spdk_jsonrpc_begin_result(request);
if (w == NULL) {
return;
}
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(request, w);
return;
invalid:
free_rpc_destroy_raid_bdev(&req);
free_rpc_destroy_raid_bdev(&ctx->req);
free(ctx);
}
SPDK_RPC_REGISTER("destroy_raid_bdev", spdk_rpc_destroy_raid_bdev, SPDK_RPC_RUNTIME)

View File

@ -49,6 +49,12 @@
#define BLOB_CRC32C_INITIAL 0xffffffffUL
#ifdef SPDK_ENABLE_SNAPSHOT_DELETION
bool g_delete_snapshot_enabled = true;
#else
bool g_delete_snapshot_enabled = false;
#endif
static int spdk_bs_register_md_thread(struct spdk_blob_store *bs);
static int spdk_bs_unregister_md_thread(struct spdk_blob_store *bs);
static void _spdk_blob_close_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno);
@ -2544,6 +2550,8 @@ struct spdk_bs_load_ctx {
spdk_bs_sequence_t *seq;
spdk_blob_op_with_handle_complete iter_cb_fn;
void *iter_cb_arg;
struct spdk_blob *blob;
spdk_blob_id blobid;
};
static void
@ -2693,20 +2701,154 @@ _spdk_bs_write_used_blobids(spdk_bs_sequence_t *seq, void *arg, spdk_bs_sequence
}
static void
_spdk_bs_load_iter(void *arg, struct spdk_blob *blob, int bserrno)
_spdk_blob_set_thin_provision(struct spdk_blob *blob)
{
struct spdk_bs_load_ctx *ctx = arg;
_spdk_blob_verify_md_op(blob);
blob->invalid_flags |= SPDK_BLOB_THIN_PROV;
blob->state = SPDK_BLOB_STATE_DIRTY;
}
if (bserrno == 0) {
if (ctx->iter_cb_fn) {
ctx->iter_cb_fn(ctx->iter_cb_arg, blob, 0);
}
_spdk_bs_blob_list_add(blob);
spdk_bs_iter_next(ctx->bs, blob, _spdk_bs_load_iter, ctx);
static void _spdk_bs_load_iter(void *arg, struct spdk_blob *blob, int bserrno);
static void
_spdk_bs_delete_corrupted_blob_cpl(void *cb_arg, int bserrno)
{
struct spdk_bs_load_ctx *ctx = cb_arg;
spdk_blob_id id;
int64_t page_num;
/* Iterate to next blob (we can't use spdk_bs_iter_next function as our
* last blob has been removed */
page_num = _spdk_bs_blobid_to_page(ctx->blobid);
page_num++;
page_num = spdk_bit_array_find_first_set(ctx->bs->used_blobids, page_num);
if (page_num >= spdk_bit_array_capacity(ctx->bs->used_blobids)) {
_spdk_bs_load_iter(ctx, NULL, -ENOENT);
return;
}
if (bserrno == -ENOENT) {
id = _spdk_bs_page_to_blobid(page_num);
spdk_bs_open_blob(ctx->bs, id, _spdk_bs_load_iter, ctx);
}
static void
_spdk_bs_delete_corrupted_close_cb(void *cb_arg, int bserrno)
{
struct spdk_bs_load_ctx *ctx = cb_arg;
if (bserrno != 0) {
SPDK_ERRLOG("Failed to close corrupted blob\n");
spdk_bs_iter_next(ctx->bs, ctx->blob, _spdk_bs_load_iter, ctx);
return;
}
spdk_bs_delete_blob(ctx->bs, ctx->blobid, _spdk_bs_delete_corrupted_blob_cpl, ctx);
}
static void
_spdk_bs_delete_corrupted_blob(void *cb_arg, int bserrno)
{
struct spdk_bs_load_ctx *ctx = cb_arg;
uint64_t i;
if (bserrno != 0) {
SPDK_ERRLOG("Failed to close clone of a corrupted blob\n");
spdk_bs_iter_next(ctx->bs, ctx->blob, _spdk_bs_load_iter, ctx);
return;
}
/* Snapshot and clone have the same copy of cluster map at this point.
* Let's clear cluster map for snpashot now so that it won't be cleared
* for clone later when we remove snapshot. Also set thin provision to
* pass data corruption check */
for (i = 0; i < ctx->blob->active.num_clusters; i++) {
ctx->blob->active.clusters[i] = 0;
}
ctx->blob->md_ro = false;
_spdk_blob_set_thin_provision(ctx->blob);
ctx->blobid = ctx->blob->id;
spdk_blob_close(ctx->blob, _spdk_bs_delete_corrupted_close_cb, ctx);
}
static void
_spdk_bs_update_corrupted_blob(void *cb_arg, int bserrno)
{
struct spdk_bs_load_ctx *ctx = cb_arg;
if (bserrno != 0) {
SPDK_ERRLOG("Failed to close clone of a corrupted blob\n");
spdk_bs_iter_next(ctx->bs, ctx->blob, _spdk_bs_load_iter, ctx);
return;
}
ctx->blob->md_ro = false;
_spdk_blob_remove_xattr(ctx->blob, SNAPSHOT_PENDING_REMOVAL, true);
spdk_blob_set_read_only(ctx->blob);
if (ctx->iter_cb_fn) {
ctx->iter_cb_fn(ctx->iter_cb_arg, ctx->blob, 0);
}
_spdk_bs_blob_list_add(ctx->blob);
spdk_bs_iter_next(ctx->bs, ctx->blob, _spdk_bs_load_iter, ctx);
}
static void
_spdk_bs_examine_clone(void *cb_arg, struct spdk_blob *blob, int bserrno)
{
struct spdk_bs_load_ctx *ctx = cb_arg;
if (bserrno != 0) {
SPDK_ERRLOG("Failed to open clone of a corrupted blob\n");
spdk_bs_iter_next(ctx->bs, ctx->blob, _spdk_bs_load_iter, ctx);
return;
}
if (blob->parent_id == ctx->blob->id) {
/* Power failure occured before updating clone - keep snapshot */
spdk_blob_close(blob, _spdk_bs_update_corrupted_blob, ctx);
} else {
/* Power failure occured after updating clone - remove snapshot */
spdk_blob_close(blob, _spdk_bs_delete_corrupted_blob, ctx);
}
}
static void
_spdk_bs_load_iter(void *arg, struct spdk_blob *blob, int bserrno)
{
struct spdk_bs_load_ctx *ctx = arg;
const void *value;
size_t len;
int rc = 0;
if (bserrno == 0) {
/* Examine blob if it is corrupted after power failure. Fix
* the ones that can be fixed and remove any other corrupted
* ones. If it is not corrupted just process it */
rc = _spdk_blob_get_xattr_value(blob, SNAPSHOT_PENDING_REMOVAL, &value, &len, true);
if (rc != 0) {
/* Not corrupted - process it and continue with iterating through blobs */
if (ctx->iter_cb_fn) {
ctx->iter_cb_fn(ctx->iter_cb_arg, blob, 0);
}
_spdk_bs_blob_list_add(blob);
spdk_bs_iter_next(ctx->bs, blob, _spdk_bs_load_iter, ctx);
return;
}
assert(len == sizeof(spdk_blob_id));
ctx->blob = blob;
/* Open clone to check if we are able to fix this blob or should we remove it */
spdk_bs_open_blob(ctx->bs, *(spdk_blob_id *)value, _spdk_bs_examine_clone, ctx);
return;
} else if (bserrno == -ENOENT) {
bserrno = 0;
} else {
/*
@ -4123,14 +4265,6 @@ _spdk_blob_set_xattrs(struct spdk_blob *blob, const struct spdk_blob_xattr_opts
return 0;
}
static void
_spdk_blob_set_thin_provision(struct spdk_blob *blob)
{
_spdk_blob_verify_md_op(blob);
blob->invalid_flags |= SPDK_BLOB_THIN_PROV;
blob->state = SPDK_BLOB_STATE_DIRTY;
}
static void
_spdk_bs_create_blob(struct spdk_blob_store *bs,
const struct spdk_blob_opts *opts,
@ -4371,7 +4505,7 @@ _spdk_bs_snapshot_origblob_sync_cpl(void *cb_arg, int bserrno)
if (bserrno != 0) {
_spdk_bs_snapshot_swap_cluster_maps(newblob, origblob);
_spdk_bs_clone_snapshot_newblob_cleanup(ctx, bserrno);
_spdk_bs_clone_snapshot_origblob_cleanup(ctx, bserrno);
return;
}
@ -5010,14 +5144,6 @@ spdk_blob_resize(struct spdk_blob *blob, uint64_t sz, spdk_blob_op_complete cb_f
/* START spdk_bs_delete_blob */
static void
_spdk_bs_delete_ebusy_close_cpl(void *cb_arg, int bserrno)
{
spdk_bs_sequence_t *seq = cb_arg;
spdk_bs_sequence_finish(seq, -EBUSY);
}
static void
_spdk_bs_delete_close_cpl(void *cb_arg, int bserrno)
{
@ -5052,6 +5178,301 @@ _spdk_bs_delete_persist_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)
spdk_blob_close(blob, _spdk_bs_delete_close_cpl, seq);
}
struct delete_snapshot_ctx {
struct spdk_blob_list *parent_snapshot_entry;
struct spdk_blob *snapshot;
bool snapshot_md_ro;
struct spdk_blob *clone;
bool clone_md_ro;
spdk_blob_op_with_handle_complete cb_fn;
void *cb_arg;
int bserrno;
};
static void
_spdk_delete_blob_cleanup_finish(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
if (bserrno != 0) {
SPDK_ERRLOG("Snapshot cleanup error %d\n", bserrno);
}
assert(ctx != NULL);
if (bserrno != 0 && ctx->bserrno == 0) {
ctx->bserrno = bserrno;
}
ctx->cb_fn(ctx->cb_arg, ctx->snapshot, ctx->bserrno);
free(ctx);
}
static void
_spdk_delete_snapshot_cleanup_snapshot(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
if (bserrno != 0) {
ctx->bserrno = bserrno;
SPDK_ERRLOG("Clone cleanup error %d\n", bserrno);
}
/* open_ref == 1 menas that only deletion context has opened this snapshot
* open_ref == 2 menas that clone has opened this snapshot as well,
* so we have to add it back to the blobs list */
if (ctx->snapshot->open_ref == 2) {
TAILQ_INSERT_HEAD(&ctx->snapshot->bs->blobs, ctx->snapshot, link);
}
ctx->snapshot->locked_operation_in_progress = false;
ctx->snapshot->md_ro = ctx->snapshot_md_ro;
spdk_blob_close(ctx->snapshot, _spdk_delete_blob_cleanup_finish, ctx);
}
static void
_spdk_delete_snapshot_cleanup_clone(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
ctx->clone->locked_operation_in_progress = false;
ctx->clone->md_ro = ctx->clone_md_ro;
spdk_blob_close(ctx->clone, _spdk_delete_snapshot_cleanup_snapshot, ctx);
}
static void
_spdk_delete_snapshot_unfreeze_cpl(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
if (bserrno) {
ctx->bserrno = bserrno;
_spdk_delete_snapshot_cleanup_clone(ctx, 0);
return;
}
ctx->clone->locked_operation_in_progress = false;
spdk_blob_close(ctx->clone, _spdk_delete_blob_cleanup_finish, ctx);
}
static void
_spdk_delete_snapshot_sync_snapshot_cpl(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
struct spdk_blob_list *parent_snapshot_entry = NULL;
struct spdk_blob_list *snapshot_entry = NULL;
struct spdk_blob_list *clone_entry = NULL;
struct spdk_blob_list *snapshot_clone_entry = NULL;
if (bserrno) {
SPDK_ERRLOG("Failed to sync MD on blob\n");
ctx->bserrno = bserrno;
_spdk_delete_snapshot_cleanup_clone(ctx, 0);
return;
}
/* Get snapshot entry for the snapshot we want to remove */
snapshot_entry = _spdk_bs_get_snapshot_entry(ctx->snapshot->bs, ctx->snapshot->id);
assert(snapshot_entry != NULL);
/* Remove clone entry in this snapshot (at this point there can be only one clone) */
clone_entry = TAILQ_FIRST(&snapshot_entry->clones);
assert(clone_entry != NULL);
TAILQ_REMOVE(&snapshot_entry->clones, clone_entry, link);
snapshot_entry->clone_count--;
assert(TAILQ_EMPTY(&snapshot_entry->clones));
if (ctx->snapshot->parent_id != SPDK_BLOBID_INVALID) {
/* This snapshot is at the same time a clone of another snapshot - we need to
* update parent snapshot (remove current clone, add new one inherited from
* the snapshot that is being removed) */
/* Get snapshot entry for parent snapshot and clone entry within that snapshot for
* snapshot that we are removing */
_spdk_blob_get_snapshot_and_clone_entries(ctx->snapshot, &parent_snapshot_entry,
&snapshot_clone_entry);
/* Switch clone entry in parent snapshot */
TAILQ_INSERT_TAIL(&parent_snapshot_entry->clones, clone_entry, link);
TAILQ_REMOVE(&parent_snapshot_entry->clones, snapshot_clone_entry, link);
free(snapshot_clone_entry);
} else {
/* No parent snapshot - just remove clone entry */
free(clone_entry);
}
/* Restore md_ro flags */
ctx->clone->md_ro = ctx->clone_md_ro;
ctx->snapshot->md_ro = ctx->snapshot_md_ro;
_spdk_blob_unfreeze_io(ctx->clone, _spdk_delete_snapshot_unfreeze_cpl, ctx);
}
static void
_spdk_delete_snapshot_sync_clone_cpl(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
uint64_t i;
ctx->snapshot->md_ro = false;
if (bserrno) {
SPDK_ERRLOG("Failed to sync MD on clone\n");
ctx->bserrno = bserrno;
/* Restore snapshot to previous state */
bserrno = _spdk_blob_remove_xattr(ctx->snapshot, SNAPSHOT_PENDING_REMOVAL, true);
if (bserrno != 0) {
_spdk_delete_snapshot_cleanup_clone(ctx, bserrno);
return;
}
spdk_blob_sync_md(ctx->snapshot, _spdk_delete_snapshot_cleanup_clone, ctx);
return;
}
/* Clear cluster map entries for snapshot */
for (i = 0; i < ctx->snapshot->active.num_clusters && i < ctx->clone->active.num_clusters; i++) {
if (ctx->clone->active.clusters[i] == ctx->snapshot->active.clusters[i]) {
ctx->snapshot->active.clusters[i] = 0;
}
}
ctx->snapshot->state = SPDK_BLOB_STATE_DIRTY;
if (ctx->parent_snapshot_entry != NULL) {
ctx->snapshot->back_bs_dev = NULL;
}
spdk_blob_sync_md(ctx->snapshot, _spdk_delete_snapshot_sync_snapshot_cpl, ctx);
}
static void
_spdk_delete_snapshot_sync_snapshot_xattr_cpl(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
uint64_t i;
/* Temporarily override md_ro flag for clone for MD modification */
ctx->clone_md_ro = ctx->clone->md_ro;
ctx->clone->md_ro = false;
if (bserrno) {
SPDK_ERRLOG("Failed to sync MD with xattr on blob\n");
ctx->bserrno = bserrno;
_spdk_delete_snapshot_cleanup_clone(ctx, 0);
return;
}
/* Copy snapshot map to clone map (only unallocated clusters in clone) */
for (i = 0; i < ctx->snapshot->active.num_clusters && i < ctx->clone->active.num_clusters; i++) {
if (ctx->clone->active.clusters[i] == 0) {
ctx->clone->active.clusters[i] = ctx->snapshot->active.clusters[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;
_spdk_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 = spdk_bs_create_zeroes_dev();
_spdk_blob_remove_xattr(ctx->clone, BLOB_SNAPSHOT, true);
}
spdk_blob_sync_md(ctx->clone, _spdk_delete_snapshot_sync_clone_cpl, ctx);
}
static void
_spdk_delete_snapshot_freeze_io_cb(void *cb_arg, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
if (bserrno) {
SPDK_ERRLOG("Failed to freeze I/O on clone\n");
ctx->bserrno = bserrno;
_spdk_delete_snapshot_cleanup_clone(ctx, 0);
return;
}
/* Temporarily override md_ro flag for snapshot for MD modification */
ctx->snapshot_md_ro = ctx->snapshot->md_ro;
ctx->snapshot->md_ro = false;
/* Mark blob as pending for removal for power failure safety, use clone id for recovery */
ctx->bserrno = _spdk_blob_set_xattr(ctx->snapshot, SNAPSHOT_PENDING_REMOVAL, &ctx->clone->id,
sizeof(spdk_blob_id), true);
if (ctx->bserrno != 0) {
_spdk_delete_snapshot_cleanup_clone(ctx, 0);
return;
}
spdk_blob_sync_md(ctx->snapshot, _spdk_delete_snapshot_sync_snapshot_xattr_cpl, ctx);
}
static void
_spdk_delete_snapshot_open_clone_cb(void *cb_arg, struct spdk_blob *clone, int bserrno)
{
struct delete_snapshot_ctx *ctx = cb_arg;
if (bserrno) {
SPDK_ERRLOG("Failed to open clone\n");
ctx->bserrno = bserrno;
_spdk_delete_snapshot_cleanup_snapshot(ctx, 0);
return;
}
ctx->clone = clone;
if (clone->locked_operation_in_progress) {
SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Cannot remove blob - another operation in progress on its clone\n");
ctx->bserrno = -EBUSY;
spdk_blob_close(ctx->clone, _spdk_delete_snapshot_cleanup_snapshot, ctx);
return;
}
clone->locked_operation_in_progress = true;
_spdk_blob_freeze_io(clone, _spdk_delete_snapshot_freeze_io_cb, ctx);
}
static void
_spdk_update_clone_on_snapshot_deletion(struct spdk_blob *snapshot, struct delete_snapshot_ctx *ctx)
{
struct spdk_blob_list *snapshot_entry = NULL;
struct spdk_blob_list *clone_entry = NULL;
struct spdk_blob_list *snapshot_clone_entry = NULL;
/* Get snapshot entry for the snapshot we want to remove */
snapshot_entry = _spdk_bs_get_snapshot_entry(snapshot->bs, snapshot->id);
assert(snapshot_entry != NULL);
/* Get clone of the snapshot (at this point there can be only one clone) */
clone_entry = TAILQ_FIRST(&snapshot_entry->clones);
assert(snapshot_entry->clone_count == 1);
assert(clone_entry != NULL);
/* Get snapshot entry for parent snapshot and clone entry within that snapshot for
* snapshot that we are removing */
_spdk_blob_get_snapshot_and_clone_entries(snapshot, &ctx->parent_snapshot_entry,
&snapshot_clone_entry);
spdk_bs_open_blob(snapshot->bs, clone_entry->id, _spdk_delete_snapshot_open_clone_cb, ctx);
}
static void
_spdk_bs_delete_blob_finish(void *cb_arg, struct spdk_blob *blob, int bserrno)
{
@ -5082,32 +5503,72 @@ _spdk_bs_delete_blob_finish(void *cb_arg, struct spdk_blob *blob, int bserrno)
}
static int
_spdk_bs_is_blob_deletable(struct spdk_blob *blob)
_spdk_bs_is_blob_deletable(struct spdk_blob *blob, bool *update_clone)
{
struct spdk_blob_list *snapshot_entry = NULL;
if (blob->open_ref > 1) {
/* Someone has this blob open (besides this delete context). */
return -EBUSY;
}
struct spdk_blob_list *clone_entry = NULL;
struct spdk_blob *clone = NULL;
bool has_one_clone = false;
/* Check if this is a snapshot with clones */
snapshot_entry = _spdk_bs_get_snapshot_entry(blob->bs, blob->id);
if (snapshot_entry != NULL) {
/* If snapshot have clones, we cannot remove it */
if (!TAILQ_EMPTY(&snapshot_entry->clones)) {
if (snapshot_entry->clone_count > 0 && !g_delete_snapshot_enabled) {
SPDK_ERRLOG("Cannot remove snapshot with clones\n");
return -EBUSY;
}
if (snapshot_entry->clone_count > 1) {
SPDK_ERRLOG("Cannot remove snapshot with more than one clone\n");
return -EBUSY;
} else if (snapshot_entry->clone_count == 1) {
has_one_clone = true;
}
}
/* Check if someone has this blob open (besides this delete context):
* - open_ref = 1 - only this context opened blob, so it is ok to remove it
* - open_ref <= 2 && has_one_clone = true - clone is holding snapshot
* and that is ok, because we will update it accordingly */
if (blob->open_ref <= 2 && has_one_clone) {
clone_entry = TAILQ_FIRST(&snapshot_entry->clones);
assert(clone_entry != NULL);
clone = _spdk_blob_lookup(blob->bs, clone_entry->id);
if (blob->open_ref == 2 && clone == NULL) {
/* Clone is closed and someone else opened this blob */
SPDK_ERRLOG("Cannot remove snapshot because it is open\n");
return -EBUSY;
}
*update_clone = true;
return 0;
}
if (blob->open_ref > 1) {
SPDK_ERRLOG("Cannot remove snapshot because it is open\n");
return -EBUSY;
}
assert(has_one_clone == false);
*update_clone = false;
return 0;
}
static void
_spdk_bs_delete_enomem_close_cpl(void *cb_arg, int bserrno)
{
spdk_bs_sequence_t *seq = cb_arg;
spdk_bs_sequence_finish(seq, -ENOMEM);
}
static void
_spdk_bs_delete_open_cpl(void *cb_arg, struct spdk_blob *blob, int bserrno)
{
spdk_bs_sequence_t *seq = cb_arg;
struct delete_snapshot_ctx *ctx;
bool update_clone = false;
if (bserrno != 0) {
spdk_bs_sequence_finish(seq, bserrno);
@ -5116,17 +5577,27 @@ _spdk_bs_delete_open_cpl(void *cb_arg, struct spdk_blob *blob, int bserrno)
_spdk_blob_verify_md_op(blob);
bserrno = _spdk_bs_is_blob_deletable(blob);
if (bserrno) {
spdk_blob_close(blob, _spdk_bs_delete_ebusy_close_cpl, seq);
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
spdk_blob_close(blob, _spdk_bs_delete_enomem_close_cpl, seq);
return;
}
_spdk_bs_blob_list_remove(blob);
ctx->snapshot = blob;
ctx->cb_fn = _spdk_bs_delete_blob_finish;
ctx->cb_arg = seq;
/* Check if blob can be removed and if it is a snapshot with clone on top of it */
ctx->bserrno = _spdk_bs_is_blob_deletable(blob, &update_clone);
if (ctx->bserrno) {
spdk_blob_close(blob, _spdk_delete_blob_cleanup_finish, ctx);
return;
}
if (blob->locked_operation_in_progress) {
SPDK_DEBUGLOG(SPDK_LOG_BLOB, "Cannot remove blob - another operation in progress\n");
spdk_blob_close(blob, _spdk_bs_delete_ebusy_close_cpl, seq);
ctx->bserrno = -EBUSY;
spdk_blob_close(blob, _spdk_delete_blob_cleanup_finish, ctx);
return;
}
@ -5138,7 +5609,15 @@ _spdk_bs_delete_open_cpl(void *cb_arg, struct spdk_blob *blob, int bserrno)
*/
TAILQ_REMOVE(&blob->bs->blobs, blob, link);
_spdk_bs_delete_blob_finish(seq, blob, 0);
if (update_clone) {
/* This blob is a snapshot with active clone - update clone first */
_spdk_update_clone_on_snapshot_deletion(blob, ctx);
} else {
/* This blob does not have any clones - just remove it */
_spdk_bs_blob_list_remove(blob);
_spdk_bs_delete_blob_finish(seq, blob, 0);
free(ctx);
}
}
void

View File

@ -215,6 +215,7 @@ enum spdk_blob_op_type {
#define BLOB_SNAPSHOT "SNAP"
#define SNAPSHOT_IN_PROGRESS "SNAPTMP"
#define SNAPSHOT_PENDING_REMOVAL "SNAPRM"
struct spdk_blob_bs_dev {
struct spdk_bs_dev bs_dev;

View File

@ -77,6 +77,7 @@ struct spdk_file {
bool is_deleted;
bool open_for_writing;
uint64_t length_flushed;
uint64_t length_xattr;
uint64_t append_pos;
uint64_t seq_byte_count;
uint64_t next_seq_offset;
@ -168,9 +169,16 @@ struct spdk_fs_cb_args {
uint64_t offset;
} readahead;
struct {
/* offset of the file when the sync request was made */
uint64_t offset;
TAILQ_ENTRY(spdk_fs_request) tailq;
bool xattr_in_progress;
/* length written to the xattr for this file - this should
* always be the same as the offset if only one thread is
* writing to the file, but could differ if multiple threads
* are appending
*/
uint64_t length;
} sync;
struct {
uint32_t num_clusters;
@ -667,6 +675,7 @@ iter_cb(void *ctx, struct spdk_blob *blob, int rc)
f->blobid = spdk_blob_get_id(blob);
f->length = *length;
f->length_flushed = *length;
f->length_xattr = *length;
f->append_pos = *length;
SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "added file %s length=%ju\n", f->name, f->length);
} else {
@ -1955,6 +1964,7 @@ __file_cache_finish_sync(void *ctx, int bserrno)
pthread_spin_lock(&file->lock);
sync_req = TAILQ_FIRST(&file->sync_requests);
sync_args = &sync_req->args;
file->length_xattr = sync_args->op.sync.length;
assert(sync_args->op.sync.offset <= file->length_flushed);
BLOBFS_TRACE(file, "sync done offset=%jx\n", sync_args->op.sync.offset);
TAILQ_REMOVE(&file->sync_requests, sync_req, args.op.sync.tailq);
@ -1984,6 +1994,7 @@ __check_sync_reqs(struct spdk_file *file)
if (sync_req != NULL && !sync_req->args.op.sync.xattr_in_progress) {
BLOBFS_TRACE(file, "set xattr length 0x%jx\n", file->length_flushed);
sync_req->args.op.sync.xattr_in_progress = true;
sync_req->args.op.sync.length = file->length_flushed;
spdk_blob_set_xattr(file->blob, "length", &file->length_flushed,
sizeof(file->length_flushed));
@ -2042,11 +2053,15 @@ __file_flush(void *ctx)
pthread_spin_lock(&file->lock);
next = spdk_tree_find_buffer(file->tree, file->length_flushed);
if (next == NULL || next->in_progress) {
if (next == NULL || next->in_progress ||
((next->bytes_filled < next->buf_size) && TAILQ_EMPTY(&file->sync_requests))) {
/*
* There is either no data to flush, or a flush I/O is already in
* progress. So return immediately - if a flush I/O is in
* progress we will flush more data after that is completed.
* There is either no data to flush, a flush I/O is already in
* progress, or the next buffer is partially filled but there's no
* outstanding request to sync it.
* So return immediately - if a flush I/O is in progress we will flush
* more data after that is completed, or a partial buffer will get flushed
* when it is either filled or the file is synced.
*/
free_fs_request(req);
if (next == NULL) {
@ -2074,6 +2089,11 @@ __file_flush(void *ctx)
if (length == 0) {
free_fs_request(req);
pthread_spin_unlock(&file->lock);
/*
* There is no data to flush, but we still need to check for any
* outstanding sync requests to make sure metadata gets updated.
*/
__check_sync_reqs(file);
return;
}
args->op.flush.length = length;
@ -2436,6 +2456,8 @@ spdk_file_read(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx,
if (length > (final_offset - offset)) {
length = final_offset - offset;
}
sub_reads++;
rc = __file_read(file, payload, offset, length, channel);
if (rc == 0) {
final_length += length;
@ -2444,7 +2466,6 @@ spdk_file_read(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx,
}
payload += length;
offset += length;
sub_reads++;
}
pthread_spin_unlock(&file->lock);
while (sub_reads-- > 0) {
@ -2469,8 +2490,8 @@ _file_sync(struct spdk_file *file, struct spdk_fs_channel *channel,
BLOBFS_TRACE(file, "offset=%jx\n", file->append_pos);
pthread_spin_lock(&file->lock);
if (file->append_pos <= file->length_flushed) {
BLOBFS_TRACE(file, "done - no data to flush\n");
if (file->append_pos <= file->length_xattr) {
BLOBFS_TRACE(file, "done - file already synced\n");
pthread_spin_unlock(&file->lock);
cb_fn(cb_arg, 0);
return;
@ -2639,7 +2660,7 @@ spdk_file_close(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx)
args->file = file;
args->sem = &channel->sem;
args->fn.file_op = __wake_caller;
args->arg = req;
args->arg = args;
channel->send_request(__file_close, req);
sem_wait(&channel->sem);

View File

@ -36,6 +36,7 @@
#include "env_internal.h"
#include <rte_config.h>
#include <rte_memory.h>
#include <rte_eal_memconfig.h>
#include "spdk_internal/assert.h"

View File

@ -623,7 +623,7 @@ spdk_app_start(struct spdk_app_opts *opts, spdk_msg_fn start_fn,
goto app_start_setup_conf_err;
}
spdk_log_open();
spdk_log_open(opts->log);
SPDK_NOTICELOG("Total cores available: %d\n", spdk_env_get_core_count());
/*

View File

@ -1452,6 +1452,10 @@ static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[]
"max_srq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_srq_depth),
spdk_json_decode_uint32, true
},
{
"no_srq", offsetof(struct nvmf_rpc_create_transport_ctx, opts.no_srq),
spdk_json_decode_bool, true
},
};
static void
@ -1585,6 +1589,10 @@ dump_nvmf_transport(struct spdk_json_write_ctx *w, struct spdk_nvmf_transport *t
spdk_json_write_named_uint32(w, "max_aq_depth", opts->max_aq_depth);
spdk_json_write_named_uint32(w, "num_shared_buffers", opts->num_shared_buffers);
spdk_json_write_named_uint32(w, "buf_cache_size", opts->buf_cache_size);
if (type == SPDK_NVME_TRANSPORT_RDMA) {
spdk_json_write_named_uint32(w, "max_srq_depth", opts->max_srq_depth);
spdk_json_write_named_bool(w, "no_srq", opts->no_srq);
}
spdk_json_write_object_end(w);
}

View File

@ -402,7 +402,7 @@ ftl_anm_unregister_device(struct spdk_ftl_dev *dev)
pthread_mutex_lock(&g_anm.lock);
ctrlr = ftl_anm_find_ctrlr(&g_anm, dev->ctrlr);
assert(ctrlr != NULL);
pthread_mutex_lock(&ctrlr->lock);
LIST_FOREACH_SAFE(poller, &ctrlr->pollers, list_entry, temp_poller) {

View File

@ -368,6 +368,7 @@ spdk_iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pd
conn->data_in_cnt--;
spdk_iscsi_task_put(spdk_iscsi_task_get_primary(pdu->task));
}
spdk_iscsi_conn_handle_queued_datain_tasks(conn);
}
} else if (pdu->bhs.opcode == ISCSI_OP_SCSI_RSP &&
pdu->task->scsi.status != SPDK_SCSI_STATUS_GOOD) {
@ -678,7 +679,13 @@ _iscsi_conn_remove_lun(void *arg1, void *arg2)
spdk_clear_all_transfer_task(conn, lun, NULL);
TAILQ_FOREACH_SAFE(pdu, &conn->write_pdu_list, tailq, tmp_pdu) {
if (pdu->task && (lun == pdu->task->scsi.lun)) {
/* If the pdu's LUN matches the LUN that was removed, free this
* PDU immediately. If the pdu's LUN is NULL, then we know
* the datain handling code already detected the hot removal,
* so we can free that PDU as well.
*/
if (pdu->task &&
(lun == pdu->task->scsi.lun || NULL == pdu->task->scsi.lun)) {
TAILQ_REMOVE(&conn->write_pdu_list, pdu, tailq);
spdk_iscsi_conn_free_pdu(conn, pdu);
}
@ -1061,8 +1068,6 @@ process_read_task_completion(struct spdk_iscsi_conn *conn,
spdk_iscsi_task_put(task);
}
process_completed_read_subtask_list(conn, primary);
spdk_iscsi_conn_handle_queued_datain_tasks(conn);
}
void

View File

@ -1309,6 +1309,7 @@ iscsi_parse_globals(void)
if (rc != 0) {
SPDK_ERRLOG("spdk_initialize_all_pools() failed\n");
free(g_spdk_iscsi.session);
g_spdk_iscsi.session = NULL;
return -1;
}
@ -1316,6 +1317,7 @@ iscsi_parse_globals(void)
if (rc < 0) {
SPDK_ERRLOG("spdk_initialize_iscsi_conns() failed\n");
free(g_spdk_iscsi.session);
g_spdk_iscsi.session = NULL;
return rc;
}

View File

@ -50,16 +50,24 @@ static const char *const spdk_level_names[] = {
#define MAX_TMPBUF 1024
static logfunc *g_log = NULL;
void
spdk_log_open(void)
spdk_log_open(logfunc *logf)
{
openlog("spdk", LOG_PID, LOG_LOCAL7);
if (logf) {
g_log = logf;
} else {
openlog("spdk", LOG_PID, LOG_LOCAL7);
}
}
void
spdk_log_close(void)
{
closelog();
if (!g_log) {
closelog();
}
}
#ifdef SPDK_LOG_BACKTRACE_LVL
@ -126,20 +134,25 @@ spdk_log(enum spdk_log_level level, const char *file, const int line, const char
return;
}
va_start(ap, format);
if (g_log) {
g_log(level, file, line, func, format);
vsnprintf(buf, sizeof(buf), format, ap);
} else {
va_start(ap, format);
if (level <= g_spdk_log_print_level) {
fprintf(stderr, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf);
spdk_log_unwind_stack(stderr, level);
vsnprintf(buf, sizeof(buf), format, ap);
if (level <= g_spdk_log_print_level) {
fprintf(stderr, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf);
spdk_log_unwind_stack(stderr, level);
}
if (level <= g_spdk_log_level) {
syslog(severity, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf);
}
va_end(ap);
}
if (level <= g_spdk_log_level) {
syslog(severity, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf);
}
va_end(ap);
}
static void

View File

@ -881,6 +881,7 @@ nvme_allocate_request(struct spdk_nvme_qpair *qpair,
req->payload_size = payload_size;
req->qpair = qpair;
req->pid = g_spdk_nvme_pid;
req->submit_tick = 0;
return req;
}

View File

@ -1137,7 +1137,6 @@ nvme_rdma_build_sgl_inline_request(struct nvme_rdma_qpair *rqpair,
struct ibv_mr *mr;
uint32_t length;
uint64_t requested_size;
uint32_t remaining_payload;
void *virt_addr;
int rc, i;
@ -1147,48 +1146,42 @@ nvme_rdma_build_sgl_inline_request(struct nvme_rdma_qpair *rqpair,
assert(req->payload.next_sge_fn != NULL);
req->payload.reset_sgl_fn(req->payload.contig_or_cb_arg, req->payload_offset);
remaining_payload = req->payload_size;
rdma_req->send_wr.num_sge = 1;
do {
rc = req->payload.next_sge_fn(req->payload.contig_or_cb_arg, &virt_addr, &length);
if (rc) {
return -1;
}
if (length > remaining_payload) {
length = remaining_payload;
}
requested_size = length;
mr = (struct ibv_mr *)spdk_mem_map_translate(rqpair->mr_map->map, (uint64_t)virt_addr,
&requested_size);
if (mr == NULL || requested_size < length) {
for (i = 1; i < rdma_req->send_wr.num_sge; i++) {
rdma_req->send_sgl[i].addr = 0;
rdma_req->send_sgl[i].length = 0;
rdma_req->send_sgl[i].lkey = 0;
}
if (mr) {
SPDK_ERRLOG("Data buffer split over multiple RDMA Memory Regions\n");
}
return -1;
}
rdma_req->send_sgl[rdma_req->send_wr.num_sge].addr = (uint64_t)virt_addr;
rdma_req->send_sgl[rdma_req->send_wr.num_sge].length = length;
rdma_req->send_sgl[rdma_req->send_wr.num_sge].lkey = mr->lkey;
rdma_req->send_wr.num_sge++;
remaining_payload -= length;
} while (remaining_payload && rdma_req->send_wr.num_sge < (int64_t)rqpair->max_send_sge);
if (remaining_payload) {
SPDK_ERRLOG("Unable to prepare request. Too many SGL elements\n");
rc = req->payload.next_sge_fn(req->payload.contig_or_cb_arg, &virt_addr, &length);
if (rc) {
return -1;
}
if (length < req->payload_size) {
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Inline SGL request split so sending separately.\n");
return nvme_rdma_build_sgl_request(rqpair, rdma_req);
}
if (length > req->payload_size) {
length = req->payload_size;
}
requested_size = length;
mr = (struct ibv_mr *)spdk_mem_map_translate(rqpair->mr_map->map, (uint64_t)virt_addr,
&requested_size);
if (mr == NULL || requested_size < length) {
for (i = 1; i < rdma_req->send_wr.num_sge; i++) {
rdma_req->send_sgl[i].addr = 0;
rdma_req->send_sgl[i].length = 0;
rdma_req->send_sgl[i].lkey = 0;
}
if (mr) {
SPDK_ERRLOG("Data buffer split over multiple RDMA Memory Regions\n");
}
return -1;
}
rdma_req->send_sgl[1].addr = (uint64_t)virt_addr;
rdma_req->send_sgl[1].length = length;
rdma_req->send_sgl[1].lkey = mr->lkey;
rdma_req->send_wr.num_sge = 2;
/* The first element of this SGL is pointing at an
* spdk_nvmf_cmd object. For this particular command,
* we only need the first 64 bytes corresponding to

View File

@ -429,6 +429,8 @@ struct spdk_nvmf_rdma_device {
struct spdk_mem_map *map;
struct ibv_pd *pd;
int num_srq;
TAILQ_ENTRY(spdk_nvmf_rdma_device) link;
};
@ -2041,12 +2043,13 @@ spdk_nvmf_rdma_request_process(struct spdk_nvmf_rdma_transport *rtransport,
#define SPDK_NVMF_RDMA_DEFAULT_MAX_QUEUE_DEPTH 128
#define SPDK_NVMF_RDMA_DEFAULT_AQ_DEPTH 128
#define SPDK_NVMF_RDMA_DEFAULT_SRQ_DEPTH 4096
#define SPDK_NVMF_RDMA_DEFAULT_MAX_QPAIRS_PER_CTRLR 64
#define SPDK_NVMF_RDMA_DEFAULT_MAX_QPAIRS_PER_CTRLR 128
#define SPDK_NVMF_RDMA_DEFAULT_IN_CAPSULE_DATA_SIZE 4096
#define SPDK_NVMF_RDMA_DEFAULT_MAX_IO_SIZE 131072
#define SPDK_NVMF_RDMA_MIN_IO_BUFFER_SIZE (SPDK_NVMF_RDMA_DEFAULT_MAX_IO_SIZE / SPDK_NVMF_MAX_SGL_ENTRIES)
#define SPDK_NVMF_RDMA_DEFAULT_NUM_SHARED_BUFFERS 4096
#define SPDK_NVMF_RDMA_DEFAULT_BUFFER_CACHE_SIZE 32
#define SPDK_NVMF_RDMA_DEFAULT_NO_SRQ false;
static void
spdk_nvmf_rdma_opts_init(struct spdk_nvmf_transport_opts *opts)
@ -2060,6 +2063,7 @@ spdk_nvmf_rdma_opts_init(struct spdk_nvmf_transport_opts *opts)
opts->num_shared_buffers = SPDK_NVMF_RDMA_DEFAULT_NUM_SHARED_BUFFERS;
opts->buf_cache_size = SPDK_NVMF_RDMA_DEFAULT_BUFFER_CACHE_SIZE;
opts->max_srq_depth = SPDK_NVMF_RDMA_DEFAULT_SRQ_DEPTH;
opts->no_srq = SPDK_NVMF_RDMA_DEFAULT_NO_SRQ
}
const struct spdk_mem_map_ops g_nvmf_rdma_map_ops = {
@ -2103,7 +2107,7 @@ spdk_nvmf_rdma_create(struct spdk_nvmf_transport_opts *opts)
" Transport opts: max_ioq_depth=%d, max_io_size=%d,\n"
" max_qpairs_per_ctrlr=%d, io_unit_size=%d,\n"
" in_capsule_data_size=%d, max_aq_depth=%d,\n"
" num_shared_buffers=%d, max_srq_depth=%d\n",
" num_shared_buffers=%d, max_srq_depth=%d, no_srq=%d\n",
opts->max_queue_depth,
opts->max_io_size,
opts->max_qpairs_per_ctrlr,
@ -2111,7 +2115,8 @@ spdk_nvmf_rdma_create(struct spdk_nvmf_transport_opts *opts)
opts->in_capsule_data_size,
opts->max_aq_depth,
opts->num_shared_buffers,
opts->max_srq_depth);
opts->max_srq_depth,
opts->no_srq);
/* I/O unit size cannot be larger than max I/O size */
if (opts->io_unit_size > opts->max_io_size) {
@ -2940,9 +2945,10 @@ spdk_nvmf_rdma_poll_group_create(struct spdk_nvmf_transport *transport)
TAILQ_INIT(&poller->qpairs);
TAILQ_INSERT_TAIL(&rgroup->pollers, poller, link);
if (device->attr.max_srq != 0) {
if (transport->opts.no_srq == false && device->num_srq < device->attr.max_srq) {
poller->max_srq_depth = transport->opts.max_srq_depth;
device->num_srq++;
memset(&srq_init_attr, 0, sizeof(struct ibv_srq_init_attr));
srq_init_attr.attr.max_wr = poller->max_srq_depth;
srq_init_attr.attr.max_sge = spdk_min(device->attr.max_sge, NVMF_DEFAULT_RX_SGE);

View File

@ -2117,7 +2117,7 @@ spdk_nvmf_tcp_req_fill_iovs(struct spdk_nvmf_tcp_transport *ttransport,
i++;
}
assert(tcp_req->req.iovcnt < SPDK_NVMF_MAX_SGL_ENTRIES);
assert(tcp_req->req.iovcnt <= SPDK_NVMF_MAX_SGL_ENTRIES);
tcp_req->data_from_pool = true;
return 0;
@ -2784,7 +2784,7 @@ spdk_nvmf_tcp_qpair_set_sq_size(struct spdk_nvmf_qpair *qpair)
#define SPDK_NVMF_TCP_DEFAULT_MAX_QUEUE_DEPTH 128
#define SPDK_NVMF_TCP_DEFAULT_AQ_DEPTH 128
#define SPDK_NVMF_TCP_DEFAULT_MAX_QPAIRS_PER_CTRLR 64
#define SPDK_NVMF_TCP_DEFAULT_MAX_QPAIRS_PER_CTRLR 128
#define SPDK_NVMF_TCP_DEFAULT_IN_CAPSULE_DATA_SIZE 4096
#define SPDK_NVMF_TCP_DEFAULT_MAX_IO_SIZE 131072
#define SPDK_NVMF_TCP_DEFAULT_IO_UNIT_SIZE 131072

View File

@ -319,6 +319,7 @@ spdk_rpc_get_version(struct spdk_jsonrpc_request *request, const struct spdk_jso
if (params != NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"get_spdk_version method requires no parameters");
return;
}
w = spdk_jsonrpc_begin_result(request);

View File

@ -506,6 +506,7 @@ spdk_posix_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct
#if defined(__linux__)
struct epoll_event event;
memset(&event, 0, sizeof(event));
event.events = EPOLLIN;
event.data.ptr = sock;

View File

@ -557,6 +557,7 @@ spdk_vpp_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct sp
assert(group != NULL);
assert(g_vpp_initialized);
memset(&event, 0, sizeof(event));
event.events = EPOLLIN;
event.data.ptr = sock;

View File

@ -780,7 +780,6 @@ spdk_for_each_thread(spdk_msg_fn fn, void *ctx, spdk_msg_fn cpl)
ct->ctx = ctx;
ct->cpl = cpl;
pthread_mutex_lock(&g_devlist_mutex);
thread = _get_thread();
if (!thread) {
SPDK_ERRLOG("No thread allocated\n");
@ -789,6 +788,8 @@ spdk_for_each_thread(spdk_msg_fn fn, void *ctx, spdk_msg_fn cpl)
return;
}
ct->orig_thread = thread;
pthread_mutex_lock(&g_devlist_mutex);
ct->cur_thread = TAILQ_FIRST(&g_threads);
pthread_mutex_unlock(&g_devlist_mutex);

View File

@ -220,7 +220,7 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
return;
}
vid = vhost_new_device(vsocket->features);
vid = vhost_new_device(vsocket->features, vsocket->notify_ops);
if (vid == -1) {
goto err;
}

View File

@ -181,7 +181,7 @@ reset_device(struct virtio_net *dev)
* there is a new virtio device being attached).
*/
int
vhost_new_device(uint64_t features)
vhost_new_device(uint64_t features, struct vhost_device_ops const *ops)
{
struct virtio_net *dev;
int i;
@ -207,6 +207,7 @@ vhost_new_device(uint64_t features)
vhost_devices[i] = dev;
dev->vid = i;
dev->features = features;
dev->notify_ops = ops;
return i;
}

View File

@ -167,6 +167,13 @@ struct guest_page {
uint64_t size;
};
/* struct ether_addr was renamed to struct rte_ether_addr at one point */
#ifdef RTE_ETHER_ADDR_LEN
struct ether_addr {
uint8_t addr_bytes[RTE_ETHER_ADDR_LEN];
} __attribute__((__packed__));
#endif
/**
* Device structure contains all configuration information relating
* to the device.
@ -301,7 +308,7 @@ gpa_to_hpa(struct virtio_net *dev, uint64_t gpa, uint64_t size)
struct virtio_net *get_device(int vid);
int vhost_new_device(uint64_t features);
int vhost_new_device(uint64_t features, struct vhost_device_ops const *ops);
void cleanup_device(struct virtio_net *dev, int destroy);
void reset_device(struct virtio_net *dev);
void vhost_destroy_device(int);

View File

@ -1217,16 +1217,6 @@ vhost_user_msg_handler(int vid, int fd)
if (dev == NULL)
return -1;
if (!dev->notify_ops) {
dev->notify_ops = vhost_driver_callback_get(dev->ifname);
if (!dev->notify_ops) {
RTE_LOG(ERR, VHOST_CONFIG,
"failed to get callback ops for driver %s\n",
dev->ifname);
return -1;
}
}
ret = read_vhost_message(fd, &msg);
if (ret <= 0 || msg.request >= VHOST_USER_MAX) {
if (ret < 0)

View File

@ -83,6 +83,7 @@ COMMON_CFLAGS += -march=native
endif
ifeq ($(TARGET_MACHINE),aarch64)
COMMON_CFLAGS += -march=armv8-a+crc
COMMON_CFLAGS += -DPAGE_SIZE=$(shell getconf PAGESIZE)
endif
ifeq ($(CONFIG_WERROR), y)
@ -265,7 +266,7 @@ SO_SUFFIX_ALL := $(SO_VER).$(SO_MINOR)
# Provide function to ease build of a shared lib
define spdk_build_realname_shared_lib
$(CC) -o $@ -shared $(CPPFLAGS) $(LDFLAGS) \
-Wl,--soname,$(patsubst %.so.$(SO_SUFFIX_ALL),%.so.$(SO_VER),$(notdir $@)) \
-Wl,--soname,$(patsubst %.so.$(SO_SUFFIX_ALL),%.so.$(SO_SUFFIX_ALL),$(notdir $@)) \
-Wl,--whole-archive $(1) -Wl,--no-whole-archive \
-Wl,--version-script=$(2) \
$(3)

2
ocf

@ -1 +1 @@
Subproject commit bd19b9c12f924b3bfd5d228c3dc4a16d807595d0
Subproject commit 515137f25ec71dca0c268fbd1437dd7d177e4f8d

View File

@ -2,12 +2,12 @@
%bcond_with doc
Name: spdk
Version: 19.04
Version: 19.04.x
Release: 0%{?dist}
Epoch: 0
URL: http://spdk.io
Source: https://github.com/spdk/spdk/archive/v19.04.tar.gz
Source: https://github.com/spdk/spdk/archive/v19.04.x.tar.gz
Summary: Set of libraries and utilities for high performance user-mode storage
%define package_version %{epoch}:%{version}-%{release}

View File

@ -61,3 +61,18 @@ Fio job parameters.
- run_time: time (in seconds) to run workload
- ramp_time: time (in seconds) to run workload before statistics are gathered
- run_num: how many times to run given workload in loop
# Running Test
Before running the test script use the setup.sh script to bind the devices you want to
use in the test to the VFIO/UIO driver.
Run the script on the NVMe-oF target system:
cd spdk
sudo PYTHONPATH=$PYTHONPATH:$PWD/scripts scripts/perf/nvmf/run_nvmf.py
The script uses another spdk script (scripts/rpc.py) so we pass the path to rpc.py by setting the Python path
as a runtime environment parameter.
# Test Results
When the test completes, you will find a csv file (nvmf_results.csv) containing the results in the target node
directory /tmp/results.

View File

@ -5,7 +5,7 @@
"transport": "transport_type"
},
"target": {
"rdma_ips": ["192.0.1.1", "192.0.2.1"],
"nic_ips": ["192.0.1.1", "192.0.2.1"],
"mode": "spdk",
"use_null_block": false,
"nvmet_dir": "/path/to/nvmetcli",
@ -14,19 +14,19 @@
},
"initiator1": {
"ip": "10.0.0.1",
"rdma_ips": ["192.0.1.1"],
"nic_ips": ["192.0.1.1"],
"mode": "spdk",
"nvmecli_dir": "/path/to/nvmecli"
},
"initiator2": {
"ip": "10.0.0.2",
"rdma_ips": ["192.0.2.1"],
"nic_ips": ["192.0.2.1"],
"mode": "spdk"
},
"fio": {
"bs": ["4k"],
"qd": [128],
"rw": ["read"],
"rw": ["randrw"],
"rwmixread": 100,
"run_time": 5,
"ramp_time": 1,

View File

@ -159,6 +159,7 @@ class Target(Server):
for row in rows:
with open(os.path.join(results_dir, csv_file), "a") as fh:
fh.write(row + "\n")
self.log_print("You can find the test results in the file %s" % os.path.join(results_dir, csv_file))
def measure_sar(self, results_dir, sar_file_name):
self.log_print("Waiting %d delay before measuring SAR stats" % self.sar_delay)
@ -186,7 +187,7 @@ class Initiator(Server):
self.nvmecli_bin = "nvme" # Use system-wide nvme-cli
self.ssh_connection = paramiko.SSHClient()
self.ssh_connection.set_missing_host_key_policy(paramiko.AutoAddPolicy)
self.ssh_connection.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh_connection.connect(self.ip, username=self.username, password=self.password)
self.remote_call("sudo rm -rf %s/nvmf_perf" % self.spdk_dir)
self.remote_call("mkdir -p %s" % self.spdk_dir)

View File

@ -92,6 +92,8 @@ elif [ -f /etc/debian_version ]; then
"Note: Some SPDK CLI dependencies could not be installed."
# Additional dependencies for ISA-L used in compression
apt-get install -y autoconf automake libtool help2man
# Additional dependecies for nvmf performance test script
apt-get install -y python3-paramiko
elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]; then
zypper install -y gcc gcc-c++ make cunit-devel libaio-devel libopenssl-devel \
git-core lcov python-base python-pycodestyle libuuid-devel sg3_utils pciutils

View File

@ -6,6 +6,7 @@ import logging
import argparse
import rpc
import sys
import shlex
try:
from shlex import quote
@ -182,7 +183,7 @@ if __name__ == "__main__":
p = subparsers.add_parser('construct_ocf_bdev',
help='Add an OCF block device')
p.add_argument('name', help='Name of resulting OCF bdev')
p.add_argument('mode', help='OCF cache mode', choices=['wt', 'pt'])
p.add_argument('mode', help='OCF cache mode', choices=['wb', 'wt', 'pt'])
p.add_argument('cache_bdev_name', help='Name of underlying cache bdev')
p.add_argument('core_bdev_name', help='Name of unerlying core bdev')
p.set_defaults(func=construct_ocf_bdev)
@ -1403,7 +1404,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
max_aq_depth=args.max_aq_depth,
num_shared_buffers=args.num_shared_buffers,
buf_cache_size=args.buf_cache_size,
max_srq_depth=args.max_srq_depth)
max_srq_depth=args.max_srq_depth,
no_srq=args.no_srq)
p = subparsers.add_parser('nvmf_create_transport', help='Create NVMf transport')
p.add_argument('-t', '--trtype', help='Transport type (ex. RDMA)', type=str, required=True)
@ -1416,6 +1418,7 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p.add_argument('-n', '--num-shared-buffers', help='The number of pooled data buffers available to the transport', type=int)
p.add_argument('-b', '--buf-cache-size', help='The number of shared buffers to reserve for each poll group', type=int)
p.add_argument('-s', '--max-srq-depth', help='Max number of outstanding I/O per SRQ. Relevant only for RDMA transport', type=int)
p.add_argument('-r', '--no-srq', action='store_true', help='Disable per-thread shared receive queue. Relevant only for RDMA transport')
p.set_defaults(func=nvmf_create_transport)
def get_nvmf_transports(args):
@ -1792,13 +1795,27 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p.add_argument('-n', '--max', help="""Maximum number of notifications to return in response""", type=int)
p.set_defaults(func=get_notifications)
args = parser.parse_args()
with rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, log_level=getattr(logging, args.verbose.upper())) as client:
def call_rpc_func(args):
try:
args.client = client
args.func(args)
except JSONRPCException as ex:
print("Exception:")
print(ex.message)
exit(1)
def execute_script(parser, client, fd):
for rpc_call in map(str.rstrip, fd):
args = parser.parse_args(shlex.split(rpc_call))
args.client = client
call_rpc_func(args)
args = parser.parse_args()
args.client = rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, log_level=getattr(logging, args.verbose.upper()))
if hasattr(args, 'func'):
call_rpc_func(args)
elif sys.stdin.isatty():
# No arguments and no data piped through stdin
parser.print_help()
exit(1)
else:
execute_script(parser, args.client, sys.stdin)

View File

@ -73,7 +73,7 @@ def construct_ocf_bdev(client, name, mode, cache_bdev_name, core_bdev_name):
Args:
name: name of constructed OCF bdev
mode: OCF cache mode: {'wt', 'pt'}
mode: OCF cache mode: {'wb', 'wt', 'pt'}
cache_bdev_name: name of underlying cache bdev
core_bdev_name: name of underlying core bdev

View File

@ -45,7 +45,8 @@ def nvmf_create_transport(client,
max_aq_depth=None,
num_shared_buffers=None,
buf_cache_size=None,
max_srq_depth=None):
max_srq_depth=None,
no_srq=False):
"""NVMf Transport Create options.
Args:
@ -57,8 +58,9 @@ def nvmf_create_transport(client,
io_unit_size: I/O unit size in bytes (optional)
max_aq_depth: Max size admin quque per controller (optional)
num_shared_buffers: The number of pooled data buffers available to the transport (optional)
buf_cache_size: The number of shared buffers to reserve for each poll group(optional)
max_srq_depth: Max number of outstanding I/O per shared receive queue (optional)
buf_cache_size: The number of shared buffers to reserve for each poll group (optional)
max_srq_depth: Max number of outstanding I/O per shared receive queue - RDMA specific (optional)
no_srq: Boolean flag to disable SRQ even for devices that support it - RDMA specific (optional)
Returns:
True or False
@ -84,6 +86,8 @@ def nvmf_create_transport(client,
params['buf_cache_size'] = buf_cache_size
if max_srq_depth:
params['max_srq_depth'] = max_srq_depth
if no_srq:
params['no_srq'] = no_srq
return client.call('nvmf_create_transport', params)

View File

@ -4,7 +4,8 @@ set -e
testdir=$(readlink -f $(dirname $0))
rootdir=$(readlink -f $testdir/../..)
rpc_py="$rootdir/scripts/rpc.py"
rpc_server=/var/tmp/spdk-raid.sock
rpc_py="$rootdir/scripts/rpc.py -s $rpc_server"
tmp_file=/tmp/raidrandtest
source $rootdir/test/common/autotest_common.sh
@ -54,30 +55,35 @@ function on_error_exit() {
killprocess $raid_pid
fi
rm -f $testdir/bdev.conf
rm -f $tmp_file
print_backtrace
exit 1
}
function configure_raid_bdev() {
rm -rf $testdir/rpcs.txt
echo construct_malloc_bdev 32 512 -b Base_1 >> $testdir/rpcs.txt
echo construct_malloc_bdev 32 512 -b Base_2 >> $testdir/rpcs.txt
echo construct_raid_bdev -z 64 -r 0 -b \"Base_1 Base_2\" -n raid0 >> $testdir/rpcs.txt
$rpc_py < $testdir/rpcs.txt
rm -rf $testdir/rpcs.txt
}
function raid_function_test() {
if [ $(uname -s) = Linux ] && modprobe -n nbd; then
local rpc_server=/var/tmp/spdk-raid.sock
local conf=$1
local nbd=/dev/nbd0
local raid_bdev
if [ ! -e $conf ]; then
return 1
fi
modprobe nbd
$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 -c ${conf} -L bdev_raid &
$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 -L bdev_raid &
raid_pid=$!
echo "Process raid pid: $raid_pid"
waitforlisten $raid_pid $rpc_server
raid_bdev=$($rootdir/scripts/rpc.py -s $rpc_server get_raid_bdevs online | cut -d ' ' -f 1)
configure_raid_bdev
raid_bdev=$($rpc_py get_raid_bdevs online | cut -d ' ' -f 1)
if [ $raid_bdev = "" ]; then
echo "No raid0 device in SPDK app"
return 1
@ -106,10 +112,8 @@ function raid_function_test() {
timing_enter bdev_raid
trap 'on_error_exit;' ERR
cp $testdir/bdev.conf.in $testdir/bdev.conf
raid_function_test $testdir/bdev.conf
raid_function_test
rm -f $testdir/bdev.conf
rm -f $tmp_file
report_test_completion "bdev_raid"
timing_exit bdev_raid

View File

@ -824,7 +824,12 @@ blockdev_test_reset(void)
target = g_io_targets;
while (target != NULL) {
blockdev_reset(target);
CU_ASSERT_EQUAL(g_completion_success, true);
/* Workaround: NVMe-oF target doesn't support reset yet - so for now
* don't fail the test if it's an NVMe bdev.
*/
if (!spdk_bdev_io_type_supported(target->bdev, SPDK_BDEV_IO_TYPE_NVME_IO)) {
CU_ASSERT_EQUAL(g_completion_success, true);
}
target = target->next;
}

View File

@ -0,0 +1 @@
leak:spdk_fs_alloc_thread_ctx

View File

@ -13,6 +13,11 @@ run_step() {
echo "--spdk_cache_size=$CACHE_SIZE" >> "$1"_flags.txt
echo -n Start $1 test phase...
# ASAN has some bugs around thread_local variables. We have a destructor in place
# to free the thread contexts, but ASAN complains about the leak before those
# destructors have a chance to run. So suppress this one specific leak using
# LSAN_OPTIONS.
export LSAN_OPTIONS="suppressions=$testdir/lsan_suppressions.txt"
/usr/bin/time taskset 0xFF $DB_BENCH --flagfile="$1"_flags.txt &> "$1"_db_bench.txt
echo done.
}

View File

@ -73,6 +73,11 @@ else
export DEPENDENCY_DIR
fi
if [ $SPDK_TEST_BLOCKDEV -eq 1 ]; then
# blockdev.sh in SPDK 19.04 is not able to run with ASAN
export SPDK_RUN_ASAN=0
fi
if [ ! -z "$HUGEMEM" ]; then
export HUGEMEM
fi

View File

@ -56,11 +56,11 @@ function tgt_check_notifications() {
# remove ID
event="${event_line%:*}"
ev_type=${event%*:}
ev_ctx=${event#:*}
ev_type=${event%:*}
ev_ctx=${event#*:}
ex_ev_type=${1%*:}
ex_ev_ctx=${1#:*}
ex_ev_type=${1%%:*}
ex_ev_ctx=${1#*:}
last_event_id=${event_line##*:}
@ -401,8 +401,21 @@ function json_config_clear() {
# Check if config is clean.
# Global params can't be cleared so need to filter them out.
local config_filter="$rootdir/test/json_config/config_filter.py"
$rootdir/scripts/rpc.py -s "${app_socket[$1]}" save_config | \
$config_filter -method delete_global_parameters | $config_filter -method check_empty
# RPC's used to cleanup configuration (e.g. to delete split and nvme bdevs)
# complete immediately and they don't wait for the unregister callback.
# It causes that configuration may not be fully cleaned at this moment and
# we should to wait a while. (See github issue #789)
count=100
while [ $count -gt 0 ] ; do
$rootdir/scripts/rpc.py -s "${app_socket[$1]}" save_config | $config_filter -method delete_global_parameters | $config_filter -method check_empty && break
count=$(( $count -1 ))
sleep 0.1
done
if [ $count -eq 0 ] ; then
return 1
fi
}
on_error_exit() {

View File

@ -1300,12 +1300,8 @@ class TestCases(object):
fail_count += self.c.snapshot_lvol_bdev(clone_bdev['name'], snapshot_name2)
snapshot_bdev2 = self.c.get_lvol_bdev_with_name(self.lvs_name + "/" + snapshot_name2)
# Try to destroy snapshots with clones and check if it fails
# Try to destroy snapshot with 2 clones and check if it fails
ret_value = self.c.destroy_lvol_bdev(snapshot_bdev['name'])
if ret_value == 0:
print("ERROR: Delete snapshot should fail but didn't")
fail_count += 1
ret_value = self.c.destroy_lvol_bdev(snapshot_bdev2['name'])
if ret_value == 0:
print("ERROR: Delete snapshot should fail but didn't")
fail_count += 1
@ -2078,6 +2074,9 @@ class TestCases(object):
self.c.construct_aio_bdev(aio_bdev0, base_name_1M, 4096)
self.c.construct_aio_bdev(aio_bdev1, base_name_32M, 4096)
# wait 1 second to allow time for lvolstore tasting
sleep(1)
# Check if configuration was properly loaded after tasting
# get all info all lvs and lvol bdevs, compare with previous info
new_bdevs = sorted(self.c.get_lvol_bdevs(), key=lambda x: x["name"])
@ -2704,12 +2703,6 @@ class TestCases(object):
fail_count += self.c.snapshot_lvol_bdev(lvol_bdev['name'], snapshot_name)
snapshot_bdev = self.c.get_lvol_bdev_with_name(self.lvs_name + "/" + snapshot_name)
# Try to destroy snapshot and check if it fails
ret_value = self.c.destroy_lvol_bdev(snapshot_bdev['name'])
if ret_value == 0:
print("ERROR: Delete snapshot should fail but didn't")
fail_count += 1
# Decouple parent lvol bdev
fail_count += self.c.decouple_parent_lvol_bdev(lvol_bdev['name'])
lvol_bdev = self.c.get_lvol_bdev_with_name(uuid_bdev0)
@ -2807,12 +2800,6 @@ class TestCases(object):
fail_count += self.run_fio_test(nbd_name, begin_fill * MEGABYTE,
fill_range * MEGABYTE, "read", pattern[i])
# Delete snapshot and check if it fails
ret_value = self.c.destroy_lvol_bdev(snapshot_bdev2['name'])
if ret_value == 0:
print("ERROR: Delete snapshot should fail but didn't")
fail_count += 1
# Decouple parent
fail_count += self.c.decouple_parent_lvol_bdev(lvol_bdev['name'])
lvol_bdev = self.c.get_lvol_bdev_with_name(uuid_bdev0)

View File

@ -36,6 +36,7 @@
#include "spdk/nvme.h"
#include "spdk/env.h"
#include "spdk/string.h"
#include "spdk/pci_ids.h"
struct ctrlr_entry {
struct spdk_nvme_ctrlr *ctrlr;
@ -81,6 +82,7 @@ static struct ctrlr_entry *g_controllers = NULL;
static struct ns_entry *g_namespaces = NULL;
static int g_num_namespaces = 0;
static struct worker_thread *g_workers = NULL;
static bool g_qemu_ssd_found = false;
static uint64_t g_tsc_rate;
@ -525,6 +527,22 @@ 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)
{
if (trid->trtype == SPDK_NVME_TRANSPORT_PCIE) {
struct spdk_pci_device *dev = spdk_nvme_ctrlr_get_pci_device(ctrlr);
/* QEMU emulated SSDs can't handle this test, so we will skip
* them. QEMU NVMe SSDs report themselves as VID == Intel. So we need
* to check this specific 0x5845 device ID to know whether it's QEMU
* or not.
*/
if (spdk_pci_device_get_vendor_id(dev) == SPDK_PCI_VID_INTEL &&
spdk_pci_device_get_device_id(dev) == 0x5845) {
g_qemu_ssd_found = true;
printf("Skipping QEMU NVMe SSD at %s\n", trid->traddr);
return;
}
}
register_ctrlr(ctrlr);
}
@ -656,7 +674,7 @@ int main(int argc, char **argv)
if (!g_controllers) {
printf("No NVMe controller found, %s exiting\n", argv[0]);
return 1;
return g_qemu_ssd_found ? 0 : 1;
}
task_pool = spdk_mempool_create("task_pool", TASK_POOL_NUM,

View File

@ -38,11 +38,9 @@ waitforlisten $nvmfpid
$rpc_py nvmf_create_transport -t RDMA -u 8192 -p 4
timing_exit start_nvmf_tgt
bdevs="$bdevs $($rpc_py construct_malloc_bdev 64 512)"
$rpc_py construct_malloc_bdev 64 512 -b Malloc1
$rpc_py nvmf_subsystem_create nqn.2016-06.io.spdk:cnode1 -a -s SPDK00000000000001
for bdev in $bdevs; do
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 $bdev
done
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 Malloc1
$rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t rdma -a $NVMF_FIRST_TARGET_IP -s 4420
PLUGIN_DIR=$rootdir/examples/nvme/fio_plugin
@ -62,24 +60,20 @@ if [ $RUN_NIGHTLY -eq 1 ]; then
$rpc_py construct_nvme_bdev -b Nvme0 -t PCIe -a $(echo $bdfs | awk '{ print $1 }') -i $NVMF_FIRST_TARGET_IP
ls_guid=$($rpc_py construct_lvol_store Nvme0n1 lvs_0)
get_lvs_free_mb $ls_guid
lb_guid=$($rpc_py construct_lvol_bdev -u $ls_guid lbd_0 $free_mb)
$rpc_py construct_lvol_bdev -l lvs_0 lbd_0 $free_mb
$rpc_py nvmf_subsystem_create nqn.2016-06.io.spdk:cnode2 -a -s SPDK00000000000001
for bdev in $lb_guid; do
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode2 $bdev
done
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode2 lvs_0/lbd_0
$rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode2 -t rdma -a $NVMF_FIRST_TARGET_IP -s 4420
LD_PRELOAD=$PLUGIN_DIR/fio_plugin /usr/src/fio/fio $PLUGIN_DIR/example_config.fio --filename="trtype=RDMA adrfam=IPv4 \
traddr=$NVMF_FIRST_TARGET_IP trsvcid=4420 ns=1"
$rpc_py delete_nvmf_subsystem nqn.2016-06.io.spdk:cnode2
# Test fio_plugin as host with nvme lvol nested backend
ls_nested_guid=$($rpc_py construct_lvol_store $lb_guid lvs_n_0)
ls_nested_guid=$($rpc_py construct_lvol_store lvs_0/lbd_0 lvs_n_0)
get_lvs_free_mb $ls_nested_guid
lb_nested_guid=$($rpc_py construct_lvol_bdev -u $ls_nested_guid lbd_nest_0 $free_mb)
$rpc_py construct_lvol_bdev -l lvs_n_0 lbd_nest_0 $free_mb
$rpc_py nvmf_subsystem_create nqn.2016-06.io.spdk:cnode3 -a -s SPDK00000000000001
for bdev in $lb_nested_guid; do
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode3 $bdev
done
$rpc_py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode3 lvs_n_0/lbd_nest_0
$rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode3 -t rdma -a $NVMF_FIRST_TARGET_IP -s 4420
LD_PRELOAD=$PLUGIN_DIR/fio_plugin /usr/src/fio/fio $PLUGIN_DIR/example_config.fio --filename="trtype=RDMA adrfam=IPv4 \
traddr=$NVMF_FIRST_TARGET_IP trsvcid=4420 ns=1"
@ -87,9 +81,9 @@ if [ $RUN_NIGHTLY -eq 1 ]; then
sync
# Delete lvol_bdev and destroy lvol_store.
$rpc_py destroy_lvol_bdev "$lb_nested_guid"
$rpc_py destroy_lvol_bdev lvs_n_0/lbd_nest_0
$rpc_py destroy_lvol_store -l lvs_n_0
$rpc_py destroy_lvol_bdev "$lb_guid"
$rpc_py destroy_lvol_bdev lvs_0/lbd_0
$rpc_py destroy_lvol_store -l lvs_0
$rpc_py delete_nvme_controller Nvme0
fi

View File

@ -1,13 +0,0 @@
#!/usr/bin/env bash
curdir=$(dirname $(readlink -f "$BASH_SOURCE"))
rootdir=$(readlink -f $curdir/../../..)
plugindir=$rootdir/examples/bdev/fio_plugin
source $rootdir/test/common/autotest_common.sh
function fio_verify(){
LD_PRELOAD=$plugindir/fio_plugin /usr/src/fio/fio $curdir/test.fio --aux-path=/tmp/ --ioengine=spdk_bdev $@
}
fio_verify --filename=MalCache1:MalCache2 --spdk_conf=$curdir/mallocs.conf

38
test/ocf/integrity/fio-modes.sh Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env bash
curdir=$(dirname $(readlink -f "$BASH_SOURCE"))
rootdir=$(readlink -f $curdir/../../..)
plugindir=$rootdir/examples/bdev/fio_plugin
source $rootdir/test/common/autotest_common.sh
function fio_verify(){
LD_PRELOAD=$plugindir/fio_plugin /usr/src/fio/fio $curdir/test.fio --aux-path=/tmp/ --ioengine=spdk_bdev $@
}
function cleanup(){
rm -f $curdir/modes.conf
}
trap "cleanup; exit 1" SIGINT SIGTERM EXIT
nvme_cfg=$($rootdir/scripts/gen_nvme.sh)
config="
$nvme_cfg
[Split]
Split Nvme0n1 8 101
[OCF]
OCF PT_Nvme pt Nvme0n1p0 Nvme0n1p1
OCF WT_Nvme wt Nvme0n1p2 Nvme0n1p3
OCF WB_Nvme0 wb Nvme0n1p4 Nvme0n1p5
OCF WB_Nvme1 wb Nvme0n1p6 Nvme0n1p7
"
echo "$config" > $curdir/modes.conf
fio_verify --filename=PT_Nvme:WT_Nvme:WB_Nvme0:WB_Nvme1 --spdk_conf=$curdir/modes.conf
trap - SIGINT SIGTERM EXIT
cleanup

View File

@ -2,7 +2,7 @@
thread=1
group_reporting=1
direct=1
norandommap=1
serialize_overlap=1
time_based=1
do_verify=1
verify=md5

View File

@ -7,16 +7,17 @@ source $rootdir/test/common/autotest_common.sh
function suite()
{
timing_enter "$@"
timing_enter $(basename $@)
run_test suite "$@"
timing_exit "$@"
timing_exit $(basename $@)
}
timing_enter ocf
suite "$testdir/integrity/fio-mallocs.sh"
suite "$testdir/integrity/fio-modes.sh"
suite "$testdir/integrity/bdevperf-iotypes.sh"
suite "$testdir/management/create-destruct.sh"
suite "$testdir/management/multicore.sh"
timing_exit ocf
report_test_completion "ocf"

View File

@ -225,11 +225,8 @@ bdev_ut_get_io_channel(void *ctx)
return spdk_get_io_channel(&g_bdev_ut_io_device);
}
static bool
stub_io_type_supported(void *_bdev, enum spdk_bdev_io_type io_type)
{
return true;
}
DEFINE_STUB(stub_io_type_supported, static bool, (void *_bdev, enum spdk_bdev_io_type io_type),
true);
static struct spdk_bdev_fn_table fn_table = {
.destruct = stub_destruct,
@ -755,6 +752,45 @@ io_wait_cb(void *arg)
entry->submitted = true;
}
static void
bdev_io_types_test(void)
{
struct spdk_bdev *bdev;
struct spdk_bdev_desc *desc = NULL;
struct spdk_io_channel *io_ch;
struct spdk_bdev_opts bdev_opts = {
.bdev_io_pool_size = 4,
.bdev_io_cache_size = 2,
};
int rc;
rc = spdk_bdev_set_opts(&bdev_opts);
CU_ASSERT(rc == 0);
spdk_bdev_initialize(bdev_init_cb, NULL);
poll_threads();
bdev = allocate_bdev("bdev0");
rc = spdk_bdev_open(bdev, true, NULL, NULL, &desc);
CU_ASSERT(rc == 0);
poll_threads();
SPDK_CU_ASSERT_FATAL(desc != NULL);
io_ch = spdk_bdev_get_io_channel(desc);
CU_ASSERT(io_ch != NULL);
/* WRITE and WRITE ZEROES are not supported */
MOCK_SET(stub_io_type_supported, false);
rc = spdk_bdev_write_zeroes_blocks(desc, io_ch, 0, 128, io_done, NULL);
CU_ASSERT(rc == -ENOTSUP);
MOCK_SET(stub_io_type_supported, true);
spdk_put_io_channel(io_ch);
spdk_bdev_close(desc);
free_bdev(bdev);
spdk_bdev_finish(bdev_fini_cb, NULL);
poll_threads();
}
static void
bdev_io_wait_test(void)
{
@ -1567,6 +1603,7 @@ main(int argc, char **argv)
CU_add_test(suite, "open_write", open_write_test) == NULL ||
CU_add_test(suite, "alias_add_del", alias_add_del_test) == NULL ||
CU_add_test(suite, "get_device_stat", get_device_stat_test) == NULL ||
CU_add_test(suite, "bdev_io_types", bdev_io_types_test) == NULL ||
CU_add_test(suite, "bdev_io_wait", bdev_io_wait_test) == NULL ||
CU_add_test(suite, "bdev_io_spans_boundary", bdev_io_spans_boundary_test) == NULL ||
CU_add_test(suite, "bdev_io_split", bdev_io_split) == NULL ||

View File

@ -61,7 +61,6 @@ bool lvol_already_opened = false;
bool g_examine_done = false;
bool g_bdev_alias_already_exists = false;
bool g_lvs_with_name_already_exists = false;
bool g_lvol_deletable = true;
int
spdk_bdev_alias_add(struct spdk_bdev *bdev, const char *alias)
@ -446,7 +445,7 @@ spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_ar
bool
spdk_lvol_deletable(struct spdk_lvol *lvol)
{
return g_lvol_deletable;
return true;
}
void
@ -1034,13 +1033,6 @@ ut_lvol_destroy(void)
CU_ASSERT(g_lvolerrno == 0);
lvol2 = g_lvol;
/* Unsuccessful lvols destroy */
g_lvol_deletable = false;
vbdev_lvol_destroy(lvol, lvol_store_op_complete, NULL);
CU_ASSERT(g_lvol != NULL);
CU_ASSERT(g_lvserrno == -EPERM);
g_lvol_deletable = true;
/* Successful lvols destroy */
vbdev_lvol_destroy(lvol, lvol_store_op_complete, NULL);
CU_ASSERT(g_lvol == NULL);

View File

@ -45,6 +45,8 @@
#include "blob/zeroes.c"
#include "blob/blob_bs_dev.c"
extern bool g_delete_snapshot_enabled;
struct spdk_blob_store *g_bs;
spdk_blob_id g_blobid;
struct spdk_blob *g_blob;
@ -2734,6 +2736,144 @@ bs_load(void)
}
static void
bs_load_pending_removal(void)
{
struct spdk_blob_store *bs;
struct spdk_bs_dev *dev;
struct spdk_blob_opts opts;
struct spdk_blob *blob, *snapshot;
spdk_blob_id blobid, snapshotid;
const void *value;
size_t value_len;
int rc;
dev = init_dev();
spdk_bs_init(dev, NULL, bs_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
bs = g_bs;
/* Create blob */
spdk_blob_opts_init(&opts);
opts.num_clusters = 10;
spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
blobid = g_blobid;
spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
blob = g_blob;
/* Create snapshot */
spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
snapshotid = g_blobid;
spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
snapshot = g_blob;
/* Set SNAPSHOT_PENDING_REMOVAL xattr */
snapshot->md_ro = false;
rc = _spdk_blob_set_xattr(snapshot, SNAPSHOT_PENDING_REMOVAL, &blobid, sizeof(spdk_blob_id), true);
CU_ASSERT(rc == 0);
snapshot->md_ro = true;
spdk_blob_close(snapshot, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_blob_close(blob, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
/* Reload blobstore */
spdk_bs_unload(g_bs, bs_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
g_bs = NULL;
dev = init_dev();
spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
bs = g_bs;
/* Snapshot should not be removed as blob is still pointing to it */
spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
snapshot = g_blob;
/* SNAPSHOT_PENDING_REMOVAL xattr should be removed during load */
rc = spdk_blob_get_xattr_value(snapshot, SNAPSHOT_PENDING_REMOVAL, &value, &value_len);
CU_ASSERT(rc != 0);
/* Set SNAPSHOT_PENDING_REMOVAL xattr again */
snapshot->md_ro = false;
rc = _spdk_blob_set_xattr(snapshot, SNAPSHOT_PENDING_REMOVAL, &blobid, sizeof(spdk_blob_id), true);
CU_ASSERT(rc == 0);
snapshot->md_ro = true;
spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
blob = g_blob;
/* Remove parent_id from blob by removing BLOB_SNAPSHOT xattr */
_spdk_blob_remove_xattr(blob, BLOB_SNAPSHOT, true);
spdk_blob_sync_md(blob, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_blob_close(snapshot, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_blob_close(blob, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
/* Reload blobstore */
spdk_bs_unload(g_bs, bs_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
g_bs = NULL;
dev = init_dev();
spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
bs = g_bs;
/* Snapshot should be removed as blob is not pointing to it anymore */
spdk_bs_open_blob(bs, snapshotid, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
spdk_bs_unload(g_bs, bs_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
g_bs = NULL;
}
static void
bs_load_custom_cluster_size(void)
{
@ -5294,12 +5434,16 @@ _blob_inflate_rw(bool decouple_parent)
poll_threads();
CU_ASSERT(g_bserrno == 0);
/* Try to delete base snapshot (for decouple_parent should fail while
* dependency still exists) */
/* Try to delete base snapshot */
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(decouple_parent || g_bserrno == 0);
CU_ASSERT(!decouple_parent || g_bserrno != 0);
if (g_delete_snapshot_enabled) {
CU_ASSERT(g_bserrno == 0);
} else {
CU_ASSERT(decouple_parent || g_bserrno == 0);
CU_ASSERT(!decouple_parent || g_bserrno != 0);
}
/* Reopen blob after snapshot deletion */
spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
@ -5578,15 +5722,11 @@ blob_relations(void)
poll_threads();
CU_ASSERT(g_bserrno == 0);
/* Try to delete snapshot with created clones */
/* Try to delete snapshot with more than 1 clone */
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
spdk_bs_unload(bs, bs_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
@ -5658,12 +5798,432 @@ blob_relations(void)
CU_ASSERT(rc == 0);
CU_ASSERT(count == 0);
/* Try to delete all blobs in the worse possible order */
/* Try to delete blob that user should not be able to remove */
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
/* Remove all blobs */
spdk_bs_delete_blob(bs, cloneid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, cloneid2, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_unload(bs, bs_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
g_bs = NULL;
}
/**
* Snapshot-clones relation test 2
*
* snapshot1
* |
* snapshot2
* |
* +-----+-----+
* | |
* blob(ro) snapshot3
* | |
* | snapshot4
* | | |
* clone2 clone clone3
*/
static void
blob_relations2(void)
{
struct spdk_blob_store *bs;
struct spdk_bs_dev *dev;
struct spdk_bs_opts bs_opts;
struct spdk_blob_opts opts;
struct spdk_blob *blob, *snapshot1, *snapshot2, *snapshot3, *snapshot4, *clone, *clone2;
spdk_blob_id blobid, snapshotid1, snapshotid2, snapshotid3, snapshotid4, cloneid, cloneid2,
cloneid3;
int rc;
size_t count;
spdk_blob_id ids[10] = {};
if (!g_delete_snapshot_enabled) {
return;
}
dev = init_dev();
spdk_bs_opts_init(&bs_opts);
snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE");
spdk_bs_init(dev, &bs_opts, bs_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
bs = g_bs;
/* 1. Create blob with 10 clusters */
spdk_blob_opts_init(&opts);
opts.num_clusters = 10;
spdk_bs_create_blob_ext(bs, &opts, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
blobid = g_blobid;
spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
blob = g_blob;
/* 2. Create snapshot1 */
spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
snapshotid1 = g_blobid;
spdk_bs_open_blob(bs, snapshotid1, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
snapshot1 = g_blob;
CU_ASSERT(snapshot1->parent_id == SPDK_BLOBID_INVALID);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid1) == SPDK_BLOBID_INVALID);
CU_ASSERT(blob->parent_id == snapshotid1);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid1);
/* Check if blob is the clone of snapshot1 */
CU_ASSERT(blob->parent_id == snapshotid1);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid1);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid1, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == blobid);
/* 3. Create another snapshot */
spdk_bs_create_snapshot(bs, blobid, NULL, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
snapshotid2 = g_blobid;
spdk_bs_open_blob(bs, snapshotid2, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
snapshot2 = g_blob;
CU_ASSERT(spdk_blob_is_clone(snapshot2));
CU_ASSERT(snapshot2->parent_id == snapshotid1);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == snapshotid1);
/* Check if snapshot2 is the clone of snapshot1 and blob
* is a child of snapshot2 */
CU_ASSERT(blob->parent_id == snapshotid2);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid2);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == blobid);
/* 4. Create clone from snapshot */
spdk_bs_create_clone(bs, snapshotid2, NULL, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
cloneid = g_blobid;
spdk_bs_open_blob(bs, cloneid, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
clone = g_blob;
CU_ASSERT(clone->parent_id == snapshotid2);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid2);
/* Check if clone is on the snapshot's list */
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 2);
CU_ASSERT(ids[0] == blobid || ids[1] == blobid);
CU_ASSERT(ids[0] == cloneid || ids[1] == cloneid);
/* 5. Create snapshot of the clone */
spdk_bs_create_snapshot(bs, cloneid, NULL, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
snapshotid3 = g_blobid;
spdk_bs_open_blob(bs, snapshotid3, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
snapshot3 = g_blob;
CU_ASSERT(snapshot3->parent_id == snapshotid2);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid3) == snapshotid2);
/* Check if clone is converted to the clone of snapshot3 and snapshot3
* is a child of snapshot2 */
CU_ASSERT(clone->parent_id == snapshotid3);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid3);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid3, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == cloneid);
/* 6. Create another snapshot of the clone */
spdk_bs_create_snapshot(bs, cloneid, NULL, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
snapshotid4 = g_blobid;
spdk_bs_open_blob(bs, snapshotid4, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
snapshot4 = g_blob;
CU_ASSERT(snapshot4->parent_id == snapshotid3);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid4) == snapshotid3);
/* Check if clone is converted to the clone of snapshot4 and snapshot4
* is a child of snapshot3 */
CU_ASSERT(clone->parent_id == snapshotid4);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid4);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid4, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == cloneid);
/* 7. Remove snapshot 4 */
spdk_blob_close(snapshot4, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, snapshotid4, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
/* Check if relations are back to state from before creating snapshot 4 */
CU_ASSERT(clone->parent_id == snapshotid3);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid3);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid3, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == cloneid);
/* 8. Create second clone of snapshot 3 and try to remove snapshot 3 */
spdk_bs_create_clone(bs, snapshotid3, NULL, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
cloneid3 = g_blobid;
spdk_bs_delete_blob(bs, snapshotid3, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
/* 9. Open snapshot 3 again and try to remove it while clone 3 is closed */
spdk_bs_open_blob(bs, snapshotid3, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
snapshot3 = g_blob;
spdk_bs_delete_blob(bs, snapshotid3, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
spdk_blob_close(snapshot3, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, cloneid3, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
/* 10. Remove snapshot 1 */
spdk_blob_close(snapshot1, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, snapshotid1, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
/* Check if relations are back to state from before creating snapshot 4 (before step 6) */
CU_ASSERT(snapshot2->parent_id == SPDK_BLOBID_INVALID);
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == SPDK_BLOBID_INVALID);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 2);
CU_ASSERT(ids[0] == blobid || ids[1] == blobid);
CU_ASSERT(ids[0] == snapshotid3 || ids[1] == snapshotid3);
/* 11. Try to create clone from read only blob */
/* Mark blob as read only */
spdk_blob_set_read_only(blob);
spdk_blob_sync_md(blob, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
/* Create clone from read only blob */
spdk_bs_create_clone(bs, blobid, NULL, blob_op_with_id_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
CU_ASSERT(g_blobid != SPDK_BLOBID_INVALID);
cloneid2 = g_blobid;
spdk_bs_open_blob(bs, cloneid2, blob_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_blob != NULL);
clone2 = g_blob;
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, blobid, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == cloneid2);
/* Close blobs */
spdk_blob_close(clone2, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_blob_close(blob, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_blob_close(clone, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_blob_close(snapshot2, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_blob_close(snapshot3, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_unload(bs, bs_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
g_bs = NULL;
/* Load an existing blob store */
dev = init_dev();
snprintf(bs_opts.bstype.bstype, sizeof(bs_opts.bstype.bstype), "TESTTYPE");
spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
SPDK_CU_ASSERT_FATAL(g_bs != NULL);
bs = g_bs;
/* Verify structure of loaded blob store */
/* snapshot2 */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid2) == SPDK_BLOBID_INVALID);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid2, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 2);
CU_ASSERT(ids[0] == blobid || ids[1] == blobid);
CU_ASSERT(ids[0] == snapshotid3 || ids[1] == snapshotid3);
/* blob */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, blobid) == snapshotid2);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, blobid, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == cloneid2);
/* clone */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid) == snapshotid3);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, cloneid, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 0);
/* snapshot3 */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, snapshotid3) == snapshotid2);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, snapshotid3, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 1);
CU_ASSERT(ids[0] == cloneid);
/* clone2 */
CU_ASSERT(spdk_blob_get_parent_snapshot(bs, cloneid2) == blobid);
count = SPDK_COUNTOF(ids);
rc = spdk_blob_get_clones(bs, cloneid2, ids, &count);
CU_ASSERT(rc == 0);
CU_ASSERT(count == 0);
/* Try to delete all blobs in the worse possible order */
spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
spdk_bs_delete_blob(bs, snapshotid3, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, snapshotid2, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
@ -5676,26 +6236,14 @@ blob_relations(void)
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno != 0);
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, cloneid2, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, blobid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_delete_blob(bs, snapshotid, blob_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
spdk_bs_unload(bs, bs_op_complete, NULL);
poll_threads();
CU_ASSERT(g_bserrno == 0);
@ -6638,6 +7186,7 @@ int main(int argc, char **argv)
CU_add_test(suite, "blob_iter", blob_iter) == NULL ||
CU_add_test(suite, "blob_xattr", blob_xattr) == NULL ||
CU_add_test(suite, "bs_load", bs_load) == NULL ||
CU_add_test(suite, "bs_load_pending_removal", bs_load_pending_removal) == NULL ||
CU_add_test(suite, "bs_load_custom_cluster_size", bs_load_custom_cluster_size) == NULL ||
CU_add_test(suite, "bs_unload", bs_unload) == NULL ||
CU_add_test(suite, "bs_cluster_sz", bs_cluster_sz) == NULL ||
@ -6661,6 +7210,7 @@ int main(int argc, char **argv)
CU_add_test(suite, "blob_snapshot_rw", blob_snapshot_rw) == NULL ||
CU_add_test(suite, "blob_snapshot_rw_iov", blob_snapshot_rw_iov) == NULL ||
CU_add_test(suite, "blob_relations", blob_relations) == NULL ||
CU_add_test(suite, "blob_relations2", blob_relations2) == NULL ||
CU_add_test(suite, "blob_inflate_rw", blob_inflate_rw) == NULL ||
CU_add_test(suite, "blob_snapshot_freeze_io", blob_snapshot_freeze_io) == NULL ||
CU_add_test(suite, "blob_operation_split_rw", blob_operation_split_rw) == NULL ||

View File

@ -132,6 +132,24 @@ _fs_init(void *arg)
CU_ASSERT(g_fserrno == 0);
}
static void
_fs_load(void *arg)
{
struct spdk_thread *thread;
struct spdk_bs_dev *dev;
g_fs = NULL;
g_fserrno = -1;
dev = init_dev();
spdk_fs_load(dev, send_request, fs_op_with_handle_complete, NULL);
thread = spdk_get_thread();
while (spdk_thread_poll(thread, 0, 0) > 0) {}
SPDK_CU_ASSERT_FATAL(g_fs != NULL);
SPDK_CU_ASSERT_FATAL(g_fs->bdev == dev);
CU_ASSERT(g_fserrno == 0);
}
static void
_fs_unload(void *arg)
{
@ -145,6 +163,11 @@ _fs_unload(void *arg)
g_fs = NULL;
}
static void
_nop(void *arg)
{
}
static void
cache_write(void)
{
@ -184,6 +207,139 @@ cache_write(void)
ut_send_request(_fs_unload, NULL);
}
static void
file_length(void)
{
int rc;
char *buf;
uint64_t buf_length;
struct spdk_fs_thread_ctx *channel;
struct spdk_file_stat stat = {0};
ut_send_request(_fs_init, NULL);
channel = spdk_fs_alloc_thread_ctx(g_fs);
g_file = NULL;
rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
CU_ASSERT(rc == 0);
SPDK_CU_ASSERT_FATAL(g_file != NULL);
/* Write one CACHE_BUFFER. Filling at least one cache buffer triggers
* a flush to disk.
*/
buf_length = CACHE_BUFFER_SIZE;
buf = calloc(1, buf_length);
spdk_file_write(g_file, channel, buf, 0, buf_length);
free(buf);
/* Spin until all of the data has been flushed to the SSD. There's been no
* sync operation yet, so the xattr on the file is still 0.
*/
while (g_file->length_flushed != buf_length) {}
/* Close the file. This causes an implicit sync which should write the
* length_flushed value as the "length" xattr on the file.
*/
spdk_file_close(g_file, channel);
rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
CU_ASSERT(rc == 0);
CU_ASSERT(buf_length == stat.size);
spdk_fs_free_thread_ctx(channel);
/* Unload and reload the filesystem. The file length will be
* read during load from the length xattr. We want to make sure
* it matches what was written when the file was originally
* written and closed.
*/
ut_send_request(_fs_unload, NULL);
ut_send_request(_fs_load, NULL);
channel = spdk_fs_alloc_thread_ctx(g_fs);
rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
CU_ASSERT(rc == 0);
CU_ASSERT(buf_length == stat.size);
g_file = NULL;
rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &g_file);
CU_ASSERT(rc == 0);
SPDK_CU_ASSERT_FATAL(g_file != NULL);
spdk_file_close(g_file, channel);
rc = spdk_fs_delete_file(g_fs, channel, "testfile");
CU_ASSERT(rc == 0);
spdk_fs_free_thread_ctx(channel);
ut_send_request(_fs_unload, NULL);
}
static void
partial_buffer(void)
{
int rc;
char *buf;
uint64_t buf_length;
struct spdk_fs_thread_ctx *channel;
struct spdk_file_stat stat = {0};
ut_send_request(_fs_init, NULL);
channel = spdk_fs_alloc_thread_ctx(g_fs);
g_file = NULL;
rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
CU_ASSERT(rc == 0);
SPDK_CU_ASSERT_FATAL(g_file != NULL);
/* Write one CACHE_BUFFER plus one byte. Filling at least one cache buffer triggers
* a flush to disk. We want to make sure the extra byte is not implicitly flushed.
* It should only get flushed once we sync or close the file.
*/
buf_length = CACHE_BUFFER_SIZE + 1;
buf = calloc(1, buf_length);
spdk_file_write(g_file, channel, buf, 0, buf_length);
free(buf);
/* Send some nop messages to the dispatch thread. This will ensure any of the
* pending write operations are completed. A well-functioning blobfs should only
* issue one write for the filled CACHE_BUFFER - a buggy one might try to write
* the extra byte. So do a bunch of _nops to make sure all of them (even the buggy
* ones) get a chance to run. Note that we can't just send a message to the
* dispatch thread to call spdk_thread_poll() because the messages are themselves
* run in the context of spdk_thread_poll().
*/
ut_send_request(_nop, NULL);
ut_send_request(_nop, NULL);
ut_send_request(_nop, NULL);
ut_send_request(_nop, NULL);
ut_send_request(_nop, NULL);
ut_send_request(_nop, NULL);
CU_ASSERT(g_file->length_flushed == CACHE_BUFFER_SIZE);
/* Close the file. This causes an implicit sync which should write the
* length_flushed value as the "length" xattr on the file.
*/
spdk_file_close(g_file, channel);
rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
CU_ASSERT(rc == 0);
CU_ASSERT(buf_length == stat.size);
rc = spdk_fs_delete_file(g_fs, channel, "testfile");
CU_ASSERT(rc == 0);
spdk_fs_free_thread_ctx(channel);
ut_send_request(_fs_unload, NULL);
}
static void
cache_write_null_buffer(void)
{
@ -369,6 +525,8 @@ int main(int argc, char **argv)
if (
CU_add_test(suite, "write", cache_write) == NULL ||
CU_add_test(suite, "file length", file_length) == NULL ||
CU_add_test(suite, "partial buffer", partial_buffer) == NULL ||
CU_add_test(suite, "write_null_buffer", cache_write_null_buffer) == NULL ||
CU_add_test(suite, "create_sync", fs_create_sync) == NULL ||
CU_add_test(suite, "append_no_cache", cache_append_no_cache) == NULL ||

View File

@ -74,7 +74,7 @@ log_test(void)
CU_ASSERT(spdk_log_get_flag("log") == false);
#endif
spdk_log_open();
spdk_log_open(NULL);
spdk_log_set_flag("log");
SPDK_WARNLOG("log warning unit test\n");
SPDK_DEBUGLOG(SPDK_LOG_LOG, "log test\n");

View File

@ -9,10 +9,6 @@ PLUGIN_DIR=$ROOT_DIR/examples/bdev/fio_plugin
FIO_PATH="/usr/src/fio"
virtio_bdevs=""
virtio_with_unmap=""
os_image="/home/sys_sgsw/vhost_vm_image.qcow2"
#different linux distributions have different versions of targetcli that have different names for ramdisk option
targetcli_rd_name=""
kernel_vhost_disk="naa.5012345678901234"
function usage()
{
@ -20,7 +16,6 @@ function usage()
echo "Script for running vhost initiator tests."
echo "Usage: $(basename $1) [-h|--help] [--fiobin=PATH]"
echo "-h, --help Print help and exit"
echo " --vm_image=PATH Path to VM image used in these tests [default=$os_image]"
echo " --fiopath=PATH Path to fio directory on host [default=$FIO_PATH]"
}
@ -30,7 +25,6 @@ while getopts 'h-:' optchar; do
case "$OPTARG" in
help) usage $0 && exit 0 ;;
fiopath=*) FIO_PATH="${OPTARG#*=}" ;;
vm_image=*) os_image="${OPTARG#*=}" ;;
*) usage $0 echo "Invalid argument '$OPTARG'" && exit 1 ;;
esac
;;
@ -53,27 +47,8 @@ if [[ $EUID -ne 0 ]]; then
exit 1
fi
if targetcli ls backstores | grep ramdisk ; then
targetcli_rd_name="ramdisk"
elif targetcli ls backstores | grep rd_mcp ; then
targetcli_rd_name="rd_mcp"
else
error "targetcli: cannot create a ramdisk.\
Neither backstores/ramdisk nor backstores/rd_mcp is available"
fi
function remove_kernel_vhost()
{
if targetcli "/vhost/$kernel_vhost_disk ls"; then
targetcli "/vhost delete $kernel_vhost_disk"
fi
if targetcli "/backstores/$targetcli_rd_name/ramdisk ls"; then
targetcli "/backstores/$targetcli_rd_name delete ramdisk"
fi
}
trap 'rm -f *.state $ROOT_DIR/spdk.tar.gz $ROOT_DIR/fio.tar.gz $(get_vhost_dir)/Virtio0;\
remove_kernel_vhost; error_exit "${FUNCNAME}""${LINENO}"' ERR SIGTERM SIGABRT
error_exit "${FUNCNAME}""${LINENO}"' ERR SIGTERM SIGABRT
function run_spdk_fio() {
LD_PRELOAD=$PLUGIN_DIR/fio_plugin $FIO_PATH/fio --ioengine=spdk_bdev\
"$@" --spdk_mem=1024 --spdk_single_seg=1
@ -131,72 +106,6 @@ run_spdk_fio $INITIATOR_DIR/bdev.fio --filename=$virtio_with_unmap --spdk_conf=$
--spdk_conf=$INITIATOR_DIR/bdev.conf
timing_exit run_spdk_fio_unmap
timing_enter create_kernel_vhost
targetcli "/backstores/$targetcli_rd_name create name=ramdisk size=1GB"
targetcli "/vhost create $kernel_vhost_disk"
targetcli "/vhost/$kernel_vhost_disk/tpg1/luns create /backstores/$targetcli_rd_name/ramdisk"
timing_exit create_kernel_vhost
timing_enter setup_vm
vm_no="0"
vm_setup --disk-type=spdk_vhost_scsi --force=$vm_no --os=$os_image \
--disks="Nvme0n1_scsi0:Malloc0:Malloc1:$kernel_vhost_disk,kernel_vhost:Virtio0,virtio:\
Nvme0n1_blk0,spdk_vhost_blk:Nvme0n1_blk1,spdk_vhost_blk" \
--queue_num=8 --memory=6144
vm_run $vm_no
timing_enter vm_wait_for_boot
vm_wait_for_boot 300 $vm_no
timing_exit vm_wait_for_boot
timing_enter vm_scp_spdk
touch $ROOT_DIR/spdk.tar.gz
tar --exclude="spdk.tar.gz" --exclude="*.o" --exclude="*.d" --exclude=".git" -C $ROOT_DIR -zcf $ROOT_DIR/spdk.tar.gz .
vm_scp $vm_no $ROOT_DIR/spdk.tar.gz "127.0.0.1:/root"
vm_ssh $vm_no "mkdir -p /root/spdk; tar -zxf /root/spdk.tar.gz -C /root/spdk --strip-components=1"
touch $ROOT_DIR/fio.tar.gz
tar --exclude="fio.tar.gz" --exclude="*.o" --exclude="*.d" --exclude=".git" -C $FIO_PATH -zcf $ROOT_DIR/fio.tar.gz .
vm_scp $vm_no $ROOT_DIR/fio.tar.gz "127.0.0.1:/root"
vm_ssh $vm_no "rm -rf /root/fio_src; mkdir -p /root/fio_src; tar -zxf /root/fio.tar.gz -C /root/fio_src --strip-components=1"
timing_exit vm_scp_spdk
timing_enter vm_build_spdk
nproc=$(vm_ssh $vm_no "nproc")
vm_ssh $vm_no " cd /root/fio_src ; make clean ; make -j${nproc} ; make install"
vm_ssh $vm_no " cd spdk ; ./configure --with-fio=/root/fio_src ; make clean ; make -j${nproc}"
timing_exit vm_build_spdk
vm_ssh $vm_no "/root/spdk/scripts/setup.sh"
vbdevs=$(vm_ssh $vm_no ". /root/spdk/test/common/autotest_common.sh && discover_bdevs /root/spdk \
/root/spdk/test/vhost/initiator/bdev_pci.conf")
virtio_bdevs=$(jq -r '[.[].name] | join(":")' <<< $vbdevs)
virtio_with_unmap=$(jq -r '[.[] | select(.supported_io_types.unmap==true).name]
| join(":")' <<< $vbdevs)
timing_exit setup_vm
timing_enter run_spdk_fio_pci
vm_ssh $vm_no "LD_PRELOAD=/root/spdk/examples/bdev/fio_plugin/fio_plugin /root/fio_src/fio --ioengine=spdk_bdev \
/root/spdk/test/vhost/initiator/bdev.fio --filename=$virtio_bdevs --section=job_randwrite \
--section=job_randrw --section=job_write --section=job_rw \
--spdk_conf=/root/spdk/test/vhost/initiator/bdev_pci.conf --spdk_mem=1024 --spdk_single_seg=1"
timing_exit run_spdk_fio_pci
timing_enter run_spdk_fio_pci_unmap
vm_ssh $vm_no "LD_PRELOAD=/root/spdk/examples/bdev/fio_plugin/fio_plugin /root/fio_src/fio --ioengine=spdk_bdev \
/root/spdk/test/vhost/initiator/bdev.fio --filename=$virtio_with_unmap \
--spdk_conf=/root/spdk/test/vhost/initiator/bdev_pci.conf --spdk_mem=1024 --spdk_single_seg=1"
timing_exit run_spdk_fio_pci_unmap
timing_enter vm_shutdown_all
vm_shutdown_all
timing_exit vm_shutdown_all
rm -f *.state $ROOT_DIR/spdk.tar.gz $ROOT_DIR/fio.tar.gz $(get_vhost_dir)/Virtio0
timing_enter remove_kernel_vhost
remove_kernel_vhost
timing_exit remove_kernel_vhost
$RPC_PY delete_nvme_controller Nvme0
timing_enter spdk_vhost_kill