Commit c55c85f8 authored by Changpeng Liu's avatar Changpeng Liu
Browse files

bdev: complete parent IO only when all the children IO are finished



When parent IO was splitted into several children requests, SPDK
may return parent completion callback with error status before
all the children requests are finished.

Change-Id: I63221a0ae1a5925a7fcd9744b4f5d8079c641252
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453611


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 75a6265d
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -1633,11 +1633,9 @@ _spdk_bdev_io_split_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_ar
	}

	/*
	 * Parent I/O finishes when all blocks are consumed or there is any failure of
	 * child I/O and no outstanding child I/O.
	 * Parent I/O finishes when all blocks are consumed.
	 */
	if (parent_io->u.bdev.split_remaining_num_blocks == 0 ||
	    parent_io->internal.status != SPDK_BDEV_IO_STATUS_SUCCESS) {
	if (parent_io->u.bdev.split_remaining_num_blocks == 0) {
		parent_io->internal.cb(parent_io, parent_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS,
				       parent_io->internal.caller_ctx);
		return;
+23 −1
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ struct bdev_ut_channel {
static bool g_io_done;
static struct spdk_bdev_io *g_bdev_io;
static enum spdk_bdev_io_status g_io_status;
static enum spdk_bdev_io_status g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS;
static uint32_t g_bdev_ut_io_device;
static struct bdev_ut_channel *g_bdev_ut_channel;

@@ -203,6 +204,7 @@ stub_complete_io(uint32_t num_to_complete)
{
	struct bdev_ut_channel *ch = g_bdev_ut_channel;
	struct spdk_bdev_io *bdev_io;
	static enum spdk_bdev_io_status io_status;
	uint32_t num_completed = 0;

	while (num_completed < num_to_complete) {
@@ -212,7 +214,9 @@ stub_complete_io(uint32_t num_to_complete)
		bdev_io = TAILQ_FIRST(&ch->outstanding_io);
		TAILQ_REMOVE(&ch->outstanding_io, bdev_io, module_link);
		ch->outstanding_io_count--;
		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
		io_status = g_io_exp_status == SPDK_BDEV_IO_STATUS_SUCCESS ? SPDK_BDEV_IO_STATUS_SUCCESS :
			    g_io_exp_status;
		spdk_bdev_io_complete(bdev_io, io_status);
		num_completed++;
	}

@@ -1143,6 +1147,24 @@ bdev_io_split(void)

	CU_ASSERT(TAILQ_EMPTY(&g_bdev_ut_channel->expected_io));

	/* Children requests return an error status */
	bdev->optimal_io_boundary = 16;
	iov[0].iov_base = (void *)0x10000;
	iov[0].iov_len = 512 * 64;
	g_io_exp_status = SPDK_BDEV_IO_STATUS_FAILED;
	g_io_done = false;
	g_io_status = SPDK_BDEV_IO_STATUS_SUCCESS;

	rc = spdk_bdev_readv_blocks(desc, io_ch, iov, 1, 1, 64, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 5);
	stub_complete_io(4);
	CU_ASSERT(g_io_done == false);
	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
	stub_complete_io(1);
	CU_ASSERT(g_io_done == true);
	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED);

	spdk_put_io_channel(io_ch);
	spdk_bdev_close(desc);
	free_bdev(bdev);