bdev: split requests first if the request has data buffer

There is one existing example usage case to describe the issue:
Users(e.g. Vhost-blk target with Windows Guest) call spdk_bdev_readv_blocks()
to submit a 128KiB length data READ request, and the data buffer
provides by vhost isn't aligned, but the backend block device
requires aligned data buffer, so existing function call trace:
spdk_bdev_readv_blocks()-->
    spdk_bdev_io_submit()-->
    spdk_bdev_io_get_buf()
spdk_bdev_io_get_buf() will allocate buffer from large data
buffer pool for 128KiB length, of course, it will return error
with existing logic.

So here, no matter what the data length is, we can go through
the split process first for both READ and WRITE.

However, there is one scenario that for iSCSI READ request,
the iSCSI layer will not allocate data buffer for the request,
so for this case if the IO boundary is required we should keep
the logic as before.

Change-Id: I67661f5fa4c3c7c561b45c86146759aa3477adbf
Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453133
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
This commit is contained in:
Changpeng Liu 2019-06-18 23:51:43 -04:00
parent 77290bfe6b
commit 5d718951a6

View File

@ -1739,6 +1739,10 @@ _spdk_bdev_io_split_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_ar
_spdk_bdev_io_split(parent_io);
}
static void
_spdk_bdev_io_split_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
bool success);
static void
spdk_bdev_io_split(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
{
@ -1749,7 +1753,13 @@ spdk_bdev_io_split(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
bdev_io->u.bdev.split_outstanding = 0;
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
_spdk_bdev_io_split(bdev_io);
if (_is_buf_allocated(bdev_io->u.bdev.iovs)) {
_spdk_bdev_io_split(bdev_io);
} else {
assert(bdev_io->type == SPDK_BDEV_IO_TYPE_READ);
spdk_bdev_io_get_buf(bdev_io, _spdk_bdev_io_split_get_buf_cb,
bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
}
}
static void
@ -1812,12 +1822,7 @@ spdk_bdev_io_submit(struct spdk_bdev_io *bdev_io)
assert(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_PENDING);
if (bdev->split_on_optimal_io_boundary && _spdk_bdev_io_should_split(bdev_io)) {
if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
spdk_bdev_io_get_buf(bdev_io, _spdk_bdev_io_split_get_buf_cb,
bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
} else {
spdk_bdev_io_split(NULL, bdev_io);
}
spdk_bdev_io_split(NULL, bdev_io);
return;
}