diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 5dbde7515..24f691cd3 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -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; diff --git a/test/unit/lib/bdev/bdev.c/bdev_ut.c b/test/unit/lib/bdev/bdev.c/bdev_ut.c index 961bb1ad0..00eee80c2 100644 --- a/test/unit/lib/bdev/bdev.c/bdev_ut.c +++ b/test/unit/lib/bdev/bdev.c/bdev_ut.c @@ -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);