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: Changpeng Liu <changpeng.liu@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453611 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
75a6265de9
commit
c55c85f807
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user