bdev: Lock LBA range for fused command execution
Signed-off-by: Maciej Szwed <maciej.szwed@intel.com> Change-Id: I577f961484b2ebf350f4f795eda1a018c5f0fd7a Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/481710 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
8a3042b714
commit
a83644fe2b
@ -359,6 +359,16 @@ bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *
|
|||||||
uint64_t offset_blocks, uint64_t num_blocks,
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
static int
|
||||||
|
bdev_lock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
||||||
|
uint64_t offset, uint64_t length,
|
||||||
|
lock_range_cb cb_fn, void *cb_arg);
|
||||||
|
|
||||||
|
static int
|
||||||
|
bdev_unlock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
||||||
|
uint64_t offset, uint64_t length,
|
||||||
|
lock_range_cb cb_fn, void *cb_arg);
|
||||||
|
|
||||||
void
|
void
|
||||||
spdk_bdev_get_opts(struct spdk_bdev_opts *opts)
|
spdk_bdev_get_opts(struct spdk_bdev_opts *opts)
|
||||||
{
|
{
|
||||||
@ -3630,20 +3640,42 @@ spdk_bdev_compare_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_cha
|
|||||||
cb, cb_arg);
|
cb, cb_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bdev_comparev_and_writev_blocks_unlocked(void *ctx, int unlock_status)
|
||||||
|
{
|
||||||
|
struct spdk_bdev_io *bdev_io = ctx;
|
||||||
|
|
||||||
|
if (unlock_status) {
|
||||||
|
SPDK_ERRLOG("LBA range unlock failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bdev_io->internal.cb(bdev_io, bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS ? true :
|
||||||
|
false, bdev_io->internal.caller_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bdev_comparev_and_writev_blocks_unlock(struct spdk_bdev_io *bdev_io, int status)
|
||||||
|
{
|
||||||
|
bdev_io->internal.status = status;
|
||||||
|
|
||||||
|
bdev_unlock_lba_range(bdev_io->internal.desc, spdk_io_channel_from_ctx(bdev_io->internal.ch),
|
||||||
|
bdev_io->u.bdev.offset_blocks, bdev_io->u.bdev.num_blocks,
|
||||||
|
bdev_comparev_and_writev_blocks_unlocked, bdev_io);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bdev_compare_and_write_do_write_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
bdev_compare_and_write_do_write_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
|
||||||
{
|
{
|
||||||
struct spdk_bdev_io *parent_io = cb_arg;
|
struct spdk_bdev_io *parent_io = cb_arg;
|
||||||
|
|
||||||
spdk_bdev_free_io(bdev_io);
|
if (!success) {
|
||||||
|
SPDK_ERRLOG("Compare and write operation failed\n");
|
||||||
if (success) {
|
|
||||||
parent_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
|
||||||
} else {
|
|
||||||
parent_io->internal.status = SPDK_BDEV_IO_STATUS_FAILED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_io->internal.cb(parent_io, false, parent_io->internal.caller_ctx);
|
spdk_bdev_free_io(bdev_io);
|
||||||
|
|
||||||
|
bdev_comparev_and_writev_blocks_unlock(parent_io,
|
||||||
|
success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3662,8 +3694,7 @@ bdev_compare_and_write_do_write(void *_bdev_io)
|
|||||||
if (rc == -ENOMEM) {
|
if (rc == -ENOMEM) {
|
||||||
bdev_queue_io_wait_with_cb(bdev_io, bdev_compare_and_write_do_write);
|
bdev_queue_io_wait_with_cb(bdev_io, bdev_compare_and_write_do_write);
|
||||||
} else if (rc != 0) {
|
} else if (rc != 0) {
|
||||||
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FAILED;
|
bdev_comparev_and_writev_blocks_unlock(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
||||||
bdev_io->internal.cb(bdev_io, false, bdev_io->internal.caller_ctx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3675,8 +3706,7 @@ bdev_compare_and_write_do_compare_done(struct spdk_bdev_io *bdev_io, bool succes
|
|||||||
spdk_bdev_free_io(bdev_io);
|
spdk_bdev_free_io(bdev_io);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
parent_io->internal.status = SPDK_BDEV_IO_STATUS_MISCOMPARE;
|
bdev_comparev_and_writev_blocks_unlock(parent_io, SPDK_BDEV_IO_STATUS_MISCOMPARE);
|
||||||
parent_io->internal.cb(parent_io, false, parent_io->internal.caller_ctx);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3697,9 +3727,21 @@ bdev_compare_and_write_do_compare(void *_bdev_io)
|
|||||||
if (rc == -ENOMEM) {
|
if (rc == -ENOMEM) {
|
||||||
bdev_queue_io_wait_with_cb(bdev_io, bdev_compare_and_write_do_compare);
|
bdev_queue_io_wait_with_cb(bdev_io, bdev_compare_and_write_do_compare);
|
||||||
} else if (rc != 0) {
|
} else if (rc != 0) {
|
||||||
|
bdev_comparev_and_writev_blocks_unlock(bdev_io, SPDK_BDEV_IO_STATUS_FIRST_FUSED_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bdev_comparev_and_writev_blocks_locked(void *ctx, int status)
|
||||||
|
{
|
||||||
|
struct spdk_bdev_io *bdev_io = ctx;
|
||||||
|
|
||||||
|
if (status) {
|
||||||
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FIRST_FUSED_FAILED;
|
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FIRST_FUSED_FAILED;
|
||||||
bdev_io->internal.cb(bdev_io, false, bdev_io->internal.caller_ctx);
|
bdev_io->internal.cb(bdev_io, false, bdev_io->internal.caller_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bdev_compare_and_write_do_compare(bdev_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -3747,8 +3789,8 @@ spdk_bdev_comparev_and_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdev_compare_and_write_do_compare(bdev_io);
|
return bdev_lock_lba_range(desc, ch, offset_blocks, num_blocks,
|
||||||
return 0;
|
bdev_comparev_and_writev_blocks_locked, bdev_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -6123,12 +6165,7 @@ bdev_lba_range_overlaps_tailq(struct lba_range *range, lba_range_tailq_t *tailq)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
bdev_lock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
|
||||||
uint64_t offset, uint64_t length,
|
|
||||||
lock_range_cb cb_fn, void *cb_arg);
|
|
||||||
|
|
||||||
int
|
|
||||||
bdev_lock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
bdev_lock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
||||||
uint64_t offset, uint64_t length,
|
uint64_t offset, uint64_t length,
|
||||||
lock_range_cb cb_fn, void *cb_arg)
|
lock_range_cb cb_fn, void *cb_arg)
|
||||||
@ -6244,12 +6281,7 @@ bdev_unlock_lba_range_get_channel(struct spdk_io_channel_iter *i)
|
|||||||
spdk_for_each_channel_continue(i, 0);
|
spdk_for_each_channel_continue(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
bdev_unlock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
|
||||||
uint64_t offset, uint64_t length,
|
|
||||||
lock_range_cb cb_fn, void *cb_arg);
|
|
||||||
|
|
||||||
int
|
|
||||||
bdev_unlock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
bdev_unlock_lba_range(struct spdk_bdev_desc *desc, struct spdk_io_channel *_ch,
|
||||||
uint64_t offset, uint64_t length,
|
uint64_t offset, uint64_t length,
|
||||||
lock_range_cb cb_fn, void *cb_arg)
|
lock_range_cb cb_fn, void *cb_arg)
|
||||||
|
@ -2346,11 +2346,15 @@ bdev_compare_and_write(void)
|
|||||||
g_compare_write_buf_len = sizeof(write_buf);
|
g_compare_write_buf_len = sizeof(write_buf);
|
||||||
rc = spdk_bdev_comparev_and_writev_blocks(desc, ioch, &compare_iov, 1, &write_iov, 1,
|
rc = spdk_bdev_comparev_and_writev_blocks(desc, ioch, &compare_iov, 1, &write_iov, 1,
|
||||||
offset, num_blocks, io_done, NULL);
|
offset, num_blocks, io_done, NULL);
|
||||||
|
/* Trigger range locking */
|
||||||
|
poll_threads();
|
||||||
CU_ASSERT_EQUAL(rc, 0);
|
CU_ASSERT_EQUAL(rc, 0);
|
||||||
num_completed = stub_complete_io(1);
|
num_completed = stub_complete_io(1);
|
||||||
CU_ASSERT_EQUAL(num_completed, 1);
|
CU_ASSERT_EQUAL(num_completed, 1);
|
||||||
CU_ASSERT(g_io_done == false);
|
CU_ASSERT(g_io_done == false);
|
||||||
num_completed = stub_complete_io(1);
|
num_completed = stub_complete_io(1);
|
||||||
|
/* Trigger range unlocking */
|
||||||
|
poll_threads();
|
||||||
CU_ASSERT_EQUAL(num_completed, 1);
|
CU_ASSERT_EQUAL(num_completed, 1);
|
||||||
CU_ASSERT(g_io_done == true);
|
CU_ASSERT(g_io_done == true);
|
||||||
CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
|
CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
|
||||||
@ -2367,8 +2371,12 @@ bdev_compare_and_write(void)
|
|||||||
g_compare_write_buf_len = sizeof(write_buf);
|
g_compare_write_buf_len = sizeof(write_buf);
|
||||||
rc = spdk_bdev_comparev_and_writev_blocks(desc, ioch, &compare_iov, 1, &write_iov, 1,
|
rc = spdk_bdev_comparev_and_writev_blocks(desc, ioch, &compare_iov, 1, &write_iov, 1,
|
||||||
offset, num_blocks, io_done, NULL);
|
offset, num_blocks, io_done, NULL);
|
||||||
|
/* Trigger range locking */
|
||||||
|
poll_threads();
|
||||||
CU_ASSERT_EQUAL(rc, 0);
|
CU_ASSERT_EQUAL(rc, 0);
|
||||||
num_completed = stub_complete_io(1);
|
num_completed = stub_complete_io(1);
|
||||||
|
/* Trigger range unlocking earlier because we expect error here */
|
||||||
|
poll_threads();
|
||||||
CU_ASSERT_EQUAL(num_completed, 1);
|
CU_ASSERT_EQUAL(num_completed, 1);
|
||||||
CU_ASSERT(g_io_done == true);
|
CU_ASSERT(g_io_done == true);
|
||||||
CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE);
|
CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_MISCOMPARE);
|
||||||
|
Loading…
Reference in New Issue
Block a user