bdev: retry IOs on ENOMEM when pushing bounce data/md
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Change-Id: Ia7634b570eb7d04c22003337a46630d152171157 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/17764 Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Community-CI: Mellanox Build Bot Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
fafb7d4741
commit
f8a33650d2
@ -371,6 +371,8 @@ enum bdev_io_retry_state {
|
|||||||
BDEV_IO_RETRY_STATE_PULL,
|
BDEV_IO_RETRY_STATE_PULL,
|
||||||
BDEV_IO_RETRY_STATE_PULL_MD,
|
BDEV_IO_RETRY_STATE_PULL_MD,
|
||||||
BDEV_IO_RETRY_STATE_SUBMIT,
|
BDEV_IO_RETRY_STATE_SUBMIT,
|
||||||
|
BDEV_IO_RETRY_STATE_PUSH,
|
||||||
|
BDEV_IO_RETRY_STATE_PUSH_MD,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define __bdev_to_io_dev(bdev) (((char *)bdev) + 1)
|
#define __bdev_to_io_dev(bdev) (((char *)bdev) + 1)
|
||||||
@ -380,6 +382,8 @@ enum bdev_io_retry_state {
|
|||||||
|
|
||||||
static inline void bdev_io_complete(void *ctx);
|
static inline void bdev_io_complete(void *ctx);
|
||||||
static inline void bdev_io_complete_unsubmitted(struct spdk_bdev_io *bdev_io);
|
static inline void bdev_io_complete_unsubmitted(struct spdk_bdev_io *bdev_io);
|
||||||
|
static void bdev_io_push_bounce_md_buf(struct spdk_bdev_io *bdev_io);
|
||||||
|
static void bdev_io_push_bounce_data(struct spdk_bdev_io *bdev_io);
|
||||||
|
|
||||||
static void bdev_write_zero_buffer_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg);
|
static void bdev_write_zero_buffer_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg);
|
||||||
static int bdev_write_zero_buffer(struct spdk_bdev_io *bdev_io);
|
static int bdev_write_zero_buffer(struct spdk_bdev_io *bdev_io);
|
||||||
@ -1482,6 +1486,12 @@ bdev_ch_retry_io(struct spdk_bdev_channel *bdev_ch)
|
|||||||
case BDEV_IO_RETRY_STATE_PULL_MD:
|
case BDEV_IO_RETRY_STATE_PULL_MD:
|
||||||
bdev_io_pull_md_buf(bdev_io);
|
bdev_io_pull_md_buf(bdev_io);
|
||||||
break;
|
break;
|
||||||
|
case BDEV_IO_RETRY_STATE_PUSH:
|
||||||
|
bdev_io_push_bounce_data(bdev_io);
|
||||||
|
break;
|
||||||
|
case BDEV_IO_RETRY_STATE_PUSH_MD:
|
||||||
|
bdev_io_push_bounce_md_buf(bdev_io);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0 && "invalid retry state");
|
assert(0 && "invalid retry state");
|
||||||
break;
|
break;
|
||||||
@ -1557,6 +1567,11 @@ _bdev_io_push_bounce_md_buf_done(void *ctx, int rc)
|
|||||||
|
|
||||||
TAILQ_REMOVE(&ch->io_memory_domain, bdev_io, internal.link);
|
TAILQ_REMOVE(&ch->io_memory_domain, bdev_io, internal.link);
|
||||||
bdev_io_decrement_outstanding(ch, ch->shared_resource);
|
bdev_io_decrement_outstanding(ch, ch->shared_resource);
|
||||||
|
|
||||||
|
if (spdk_unlikely(!TAILQ_EMPTY(&ch->shared_resource->nomem_io))) {
|
||||||
|
bdev_ch_retry_io(ch);
|
||||||
|
}
|
||||||
|
|
||||||
bdev_io->internal.data_transfer_cpl(bdev_io, rc);
|
bdev_io->internal.data_transfer_cpl(bdev_io, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1589,8 +1604,11 @@ bdev_io_push_bounce_md_buf(struct spdk_bdev_io *bdev_io)
|
|||||||
}
|
}
|
||||||
TAILQ_REMOVE(&ch->io_memory_domain, bdev_io, internal.link);
|
TAILQ_REMOVE(&ch->io_memory_domain, bdev_io, internal.link);
|
||||||
bdev_io_decrement_outstanding(ch, ch->shared_resource);
|
bdev_io_decrement_outstanding(ch, ch->shared_resource);
|
||||||
|
if (rc != -ENOMEM) {
|
||||||
SPDK_ERRLOG("Failed to push md to memory domain %s\n",
|
SPDK_ERRLOG("Failed to push md to memory domain %s\n",
|
||||||
spdk_memory_domain_get_dma_device_id(bdev_io->internal.memory_domain));
|
spdk_memory_domain_get_dma_device_id(
|
||||||
|
bdev_io->internal.memory_domain));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy(bdev_io->internal.orig_md_iov.iov_base, bdev_io->u.bdev.md_buf,
|
memcpy(bdev_io->internal.orig_md_iov.iov_base, bdev_io->u.bdev.md_buf,
|
||||||
bdev_io->internal.orig_md_iov.iov_len);
|
bdev_io->internal.orig_md_iov.iov_len);
|
||||||
@ -1598,9 +1616,13 @@ bdev_io_push_bounce_md_buf(struct spdk_bdev_io *bdev_io)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spdk_unlikely(rc == -ENOMEM)) {
|
||||||
|
bdev_queue_nomem_io_head(ch->shared_resource, bdev_io, BDEV_IO_RETRY_STATE_PUSH_MD);
|
||||||
|
} else {
|
||||||
assert(bdev_io->internal.data_transfer_cpl);
|
assert(bdev_io->internal.data_transfer_cpl);
|
||||||
bdev_io->internal.data_transfer_cpl(bdev_io, rc);
|
bdev_io->internal.data_transfer_cpl(bdev_io, rc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
bdev_io_push_bounce_data_buffer_done(void *ctx, int rc)
|
bdev_io_push_bounce_data_buffer_done(void *ctx, int rc)
|
||||||
@ -1632,6 +1654,10 @@ _bdev_io_push_bounce_data_buffer_done(void *ctx, int status)
|
|||||||
TAILQ_REMOVE(&ch->io_memory_domain, bdev_io, internal.link);
|
TAILQ_REMOVE(&ch->io_memory_domain, bdev_io, internal.link);
|
||||||
bdev_io_decrement_outstanding(ch, ch->shared_resource);
|
bdev_io_decrement_outstanding(ch, ch->shared_resource);
|
||||||
|
|
||||||
|
if (spdk_unlikely(!TAILQ_EMPTY(&ch->shared_resource->nomem_io))) {
|
||||||
|
bdev_ch_retry_io(ch);
|
||||||
|
}
|
||||||
|
|
||||||
bdev_io_push_bounce_data_buffer_done(ctx, status);
|
bdev_io_push_bounce_data_buffer_done(ctx, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1662,8 +1688,11 @@ bdev_io_push_bounce_data(struct spdk_bdev_io *bdev_io)
|
|||||||
|
|
||||||
TAILQ_REMOVE(&ch->io_memory_domain, bdev_io, internal.link);
|
TAILQ_REMOVE(&ch->io_memory_domain, bdev_io, internal.link);
|
||||||
bdev_io_decrement_outstanding(ch, ch->shared_resource);
|
bdev_io_decrement_outstanding(ch, ch->shared_resource);
|
||||||
|
if (rc != -ENOMEM) {
|
||||||
SPDK_ERRLOG("Failed to push data to memory domain %s\n",
|
SPDK_ERRLOG("Failed to push data to memory domain %s\n",
|
||||||
spdk_memory_domain_get_dma_device_id(bdev_io->internal.memory_domain));
|
spdk_memory_domain_get_dma_device_id(
|
||||||
|
bdev_io->internal.memory_domain));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
spdk_copy_buf_to_iovs(bdev_io->internal.orig_iovs,
|
spdk_copy_buf_to_iovs(bdev_io->internal.orig_iovs,
|
||||||
bdev_io->internal.orig_iovcnt,
|
bdev_io->internal.orig_iovcnt,
|
||||||
@ -1672,8 +1701,12 @@ bdev_io_push_bounce_data(struct spdk_bdev_io *bdev_io)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spdk_unlikely(rc == -ENOMEM)) {
|
||||||
|
bdev_queue_nomem_io_head(ch->shared_resource, bdev_io, BDEV_IO_RETRY_STATE_PUSH);
|
||||||
|
} else {
|
||||||
bdev_io_push_bounce_data_buffer_done(bdev_io, rc);
|
bdev_io_push_bounce_data_buffer_done(bdev_io, rc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_bdev_io_push_bounce_data_buffer(struct spdk_bdev_io *bdev_io, bdev_copy_bounce_buffer_cpl cpl_cb)
|
_bdev_io_push_bounce_data_buffer(struct spdk_bdev_io *bdev_io, bdev_copy_bounce_buffer_cpl cpl_cb)
|
||||||
|
@ -5895,6 +5895,37 @@ bdev_io_ext_bounce_buffer(void)
|
|||||||
stub_complete_io(1);
|
stub_complete_io(1);
|
||||||
CU_ASSERT(g_io_done == true);
|
CU_ASSERT(g_io_done == true);
|
||||||
|
|
||||||
|
/* Verify the request is queued after receiving ENOMEM from push */
|
||||||
|
g_io_done = false;
|
||||||
|
expected_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_READ, 32, 14, 1);
|
||||||
|
ut_expected_io_set_iov(expected_io, 0, iov.iov_base, iov.iov_len);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, expected_io, link);
|
||||||
|
|
||||||
|
MOCK_SET(spdk_memory_domain_push_data, -ENOMEM);
|
||||||
|
rc = spdk_bdev_readv_blocks_ext(desc, io_ch, &iov, 1, 32, 14, io_done, NULL, &ext_io_opts);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT(g_io_done == false);
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1);
|
||||||
|
|
||||||
|
aux_io = ut_alloc_expected_io(SPDK_BDEV_IO_TYPE_WRITE, 32, 14, 1);
|
||||||
|
ut_expected_io_set_iov(aux_io, 0, iov.iov_base, iov.iov_len);
|
||||||
|
TAILQ_INSERT_TAIL(&g_bdev_ut_channel->expected_io, aux_io, link);
|
||||||
|
rc = spdk_bdev_writev_blocks(desc, io_ch, &iov, 1, 32, 14, io_done, NULL);
|
||||||
|
CU_ASSERT(rc == 0);
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 2);
|
||||||
|
|
||||||
|
stub_complete_io(1);
|
||||||
|
/* The IO isn't done yet, it's still waiting on push */
|
||||||
|
CU_ASSERT(g_io_done == false);
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 1);
|
||||||
|
MOCK_CLEAR(spdk_memory_domain_push_data);
|
||||||
|
g_memory_domain_push_data_called = false;
|
||||||
|
/* Completing the second IO should also trigger push on the first one */
|
||||||
|
stub_complete_io(1);
|
||||||
|
CU_ASSERT(g_io_done == true);
|
||||||
|
CU_ASSERT(g_memory_domain_push_data_called == true);
|
||||||
|
CU_ASSERT(g_bdev_ut_channel->outstanding_io_count == 0);
|
||||||
|
|
||||||
spdk_put_io_channel(io_ch);
|
spdk_put_io_channel(io_ch);
|
||||||
spdk_bdev_close(desc);
|
spdk_bdev_close(desc);
|
||||||
free_bdev(bdev);
|
free_bdev(bdev);
|
||||||
|
Loading…
Reference in New Issue
Block a user