Commit 089d178a authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

lib/bdev: Terminate parent I/O with failure immediately if one of child I/O failed



Previously, bdev_io_split_done() had continued splitting process
even if the status became failed. To abort split I/O, this patch
changes bdev_io_split_done() to terminate with failure before
continuing splitting process if the status became failed. Add
necessary unit test together.

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Ifd1ea49c22523e8c06fb45ebdcb2c84a57afd2ef
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2234


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Community-CI: Broadcom CI
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarMichael Haeuptle <michaelhaeuptle@gmail.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent fc3e4061
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1952,6 +1952,9 @@ bdev_io_split_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)

	if (!success) {
		parent_io->internal.status = SPDK_BDEV_IO_STATUS_FAILED;
		/* If any child I/O failed, stop further splitting process. */
		parent_io->u.bdev.split_current_offset_blocks += parent_io->u.bdev.split_remaining_num_blocks;
		parent_io->u.bdev.split_remaining_num_blocks = 0;
	}
	parent_io->u.bdev.split_outstanding--;
	if (parent_io->u.bdev.split_outstanding != 0) {
+36 −0
Original line number Diff line number Diff line
@@ -1546,6 +1546,42 @@ bdev_io_split_test(void)
	CU_ASSERT(g_io_done == true);
	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED);

	/* Test if a multi vector command terminated with failure before continueing
	 * splitting process when one of child I/O failed.
	 * The multi vector command is as same as the above that needs to be split by strip
	 * and then needs to be split further due to the capacity of child iovs.
	 */
	for (i = 0; i < BDEV_IO_NUM_CHILD_IOV - 1; i++) {
		iov[i].iov_base = (void *)((i + 1) * 0x10000);
		iov[i].iov_len = 512;
	}
	iov[BDEV_IO_NUM_CHILD_IOV - 1].iov_base = (void *)(BDEV_IO_NUM_CHILD_IOV * 0x10000);
	iov[BDEV_IO_NUM_CHILD_IOV - 1].iov_len = 256;

	iov[BDEV_IO_NUM_CHILD_IOV].iov_base = (void *)((BDEV_IO_NUM_CHILD_IOV + 1) * 0x10000);
	iov[BDEV_IO_NUM_CHILD_IOV].iov_len = 256;

	iov[BDEV_IO_NUM_CHILD_IOV + 1].iov_base = (void *)((BDEV_IO_NUM_CHILD_IOV + 2) * 0x10000);
	iov[BDEV_IO_NUM_CHILD_IOV + 1].iov_len = 512;

	bdev->optimal_io_boundary = BDEV_IO_NUM_CHILD_IOV;

	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, BDEV_IO_NUM_CHILD_IOV * 2, 0,
				    BDEV_IO_NUM_CHILD_IOV + 1, io_done, NULL);
	CU_ASSERT(rc == 0);
	CU_ASSERT(g_io_done == false);

	CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1);
	stub_complete_io(1);
	CU_ASSERT(g_io_done == true);
	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED);

	g_io_exp_status = SPDK_BDEV_IO_STATUS_SUCCESS;

	/* for this test we will create the following conditions to hit the code path where
	 * we are trying to send and IO following a split that has no iovs because we had to
	 * trim them for alignment reasons.