blobfs: add writev/readv asynchronous APIs support

Change-Id: Id1172f546852fcf25c6d13cb63f9d875b02e768c
Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453493
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Changpeng Liu 2019-05-05 22:19:14 -04:00 committed by Ben Walker
parent c74ea9fa8e
commit 1966f1eef3
2 changed files with 122 additions and 12 deletions

View File

@ -406,6 +406,42 @@ int spdk_file_sync(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx);
*/
int spdk_file_get_id(struct spdk_file *file, void *id, size_t size);
/**
* Read data to user buffer from the given file.
*
* \param file File to read.
* \param channel I/O channel for asynchronous operations.
* \param iovs A scatter gather list of buffers to be read into.
* \param iovcnt The number of elements in iov.
* \param offset The beginning position to read.
* \param length The size in bytes of data to read.
* \param cb_fn Called when the request is complete.
* \param cb_arg Argument passed to cb_fn.
*
* \return None.
*/
void spdk_file_readv_async(struct spdk_file *file, struct spdk_io_channel *channel,
struct iovec *iovs, uint32_t iovcnt, uint64_t offset, uint64_t length,
spdk_file_op_complete cb_fn, void *cb_arg);
/**
* Write data to the given file.
*
* \param file File to write.
* \param channel I/O channel for asynchronous operations.
* \param iovs A scatter gather list of buffers to be written from.
* \param iovcnt The number of elements in iov.
* \param offset The beginning position to write.
* \param length The size in bytes of data to write.
* \param cb_fn Called when the request is complete.
* \param cb_arg Argument passed to cb_fn.
*
* \return None.
*/
void spdk_file_writev_async(struct spdk_file *file, struct spdk_io_channel *channel,
struct iovec *iovs, uint32_t iovcnt, uint64_t offset, uint64_t length,
spdk_file_op_complete cb_fn, void *cb_arg);
#ifdef __cplusplus
}
#endif

View File

@ -1710,22 +1710,50 @@ __rw_done(void *ctx, int bserrno)
free_fs_request(req);
}
static void
_copy_iovs_to_buf(void *buf, size_t buf_len, struct iovec *iovs, int iovcnt)
{
int i;
size_t len;
for (i = 0; i < iovcnt; i++) {
len = spdk_min(iovs[i].iov_len, buf_len);
memcpy(buf, iovs[i].iov_base, len);
buf += len;
assert(buf_len >= len);
buf_len -= len;
}
}
static void
_copy_buf_to_iovs(struct iovec *iovs, int iovcnt, void *buf, size_t buf_len)
{
int i;
size_t len;
for (i = 0; i < iovcnt; i++) {
len = spdk_min(iovs[i].iov_len, buf_len);
memcpy(iovs[i].iov_base, buf, len);
buf += len;
assert(buf_len >= len);
buf_len -= len;
}
}
static void
__read_done(void *ctx, int bserrno)
{
struct spdk_fs_request *req = ctx;
struct spdk_fs_cb_args *args = &req->args;
void *buf;
assert(req != NULL);
buf = (void *)((uintptr_t)args->op.rw.pin_buf + (args->op.rw.offset & (args->op.rw.blocklen - 1)));
if (args->op.rw.is_read) {
memcpy(args->iovs[0].iov_base,
args->op.rw.pin_buf + (args->op.rw.offset & (args->op.rw.blocklen - 1)),
args->iovs[0].iov_len);
_copy_buf_to_iovs(args->iovs, args->iovcnt, buf, args->op.rw.length);
__rw_done(req, 0);
} else {
memcpy(args->op.rw.pin_buf + (args->op.rw.offset & (args->op.rw.blocklen - 1)),
args->iovs[0].iov_base,
args->iovs[0].iov_len);
_copy_iovs_to_buf(buf, args->op.rw.length, args->iovs, args->iovcnt);
spdk_blob_io_write(args->file->blob, args->op.rw.channel,
args->op.rw.pin_buf,
args->op.rw.start_lba, args->op.rw.num_lba,
@ -1762,9 +1790,20 @@ __get_page_parameters(struct spdk_file *file, uint64_t offset, uint64_t length,
}
static void
__readwrite(struct spdk_file *file, struct spdk_io_channel *_channel,
void *payload, uint64_t offset, uint64_t length,
spdk_file_op_complete cb_fn, void *cb_arg, int is_read)
_fs_request_setup_iovs(struct spdk_fs_request *req, struct iovec *iovs, uint32_t iovcnt)
{
uint32_t i;
for (i = 0; i < iovcnt; i++) {
req->args.iovs[i].iov_base = iovs[i].iov_base;
req->args.iovs[i].iov_len = iovs[i].iov_len;
}
}
static void
__readvwritev(struct spdk_file *file, struct spdk_io_channel *_channel,
struct iovec *iovs, uint32_t iovcnt, uint64_t offset, uint64_t length,
spdk_file_op_complete cb_fn, void *cb_arg, int is_read)
{
struct spdk_fs_request *req;
struct spdk_fs_cb_args *args;
@ -1777,7 +1816,7 @@ __readwrite(struct spdk_file *file, struct spdk_io_channel *_channel,
return;
}
req = alloc_fs_request_with_iov(channel, 1);
req = alloc_fs_request_with_iov(channel, iovcnt);
if (req == NULL) {
cb_fn(cb_arg, -ENOMEM);
return;
@ -1790,13 +1829,13 @@ __readwrite(struct spdk_file *file, struct spdk_io_channel *_channel,
args->arg = cb_arg;
args->file = file;
args->op.rw.channel = channel->bs_channel;
args->iovs[0].iov_base = payload;
args->iovs[0].iov_len = (size_t)length;
_fs_request_setup_iovs(req, iovs, iovcnt);
args->op.rw.is_read = is_read;
args->op.rw.offset = offset;
args->op.rw.blocklen = lba_size;
pin_buf_length = num_lba * lba_size;
args->op.rw.length = pin_buf_length;
args->op.rw.pin_buf = spdk_malloc(pin_buf_length, lba_size, NULL,
SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA);
if (args->op.rw.pin_buf == NULL) {
@ -1817,6 +1856,19 @@ __readwrite(struct spdk_file *file, struct spdk_io_channel *_channel,
}
}
static void
__readwrite(struct spdk_file *file, struct spdk_io_channel *channel,
void *payload, uint64_t offset, uint64_t length,
spdk_file_op_complete cb_fn, void *cb_arg, int is_read)
{
struct iovec iov;
iov.iov_base = payload;
iov.iov_len = (size_t)length;
__readvwritev(file, channel, &iov, 1, offset, length, cb_fn, cb_arg, is_read);
}
void
spdk_file_write_async(struct spdk_file *file, struct spdk_io_channel *channel,
void *payload, uint64_t offset, uint64_t length,
@ -1825,6 +1877,17 @@ spdk_file_write_async(struct spdk_file *file, struct spdk_io_channel *channel,
__readwrite(file, channel, payload, offset, length, cb_fn, cb_arg, 0);
}
void
spdk_file_writev_async(struct spdk_file *file, struct spdk_io_channel *channel,
struct iovec *iovs, uint32_t iovcnt, uint64_t offset, uint64_t length,
spdk_file_op_complete cb_fn, void *cb_arg)
{
SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s offset=%jx length=%jx\n",
file->name, offset, length);
__readvwritev(file, channel, iovs, iovcnt, offset, length, cb_fn, cb_arg, 0);
}
void
spdk_file_read_async(struct spdk_file *file, struct spdk_io_channel *channel,
void *payload, uint64_t offset, uint64_t length,
@ -1835,6 +1898,17 @@ spdk_file_read_async(struct spdk_file *file, struct spdk_io_channel *channel,
__readwrite(file, channel, payload, offset, length, cb_fn, cb_arg, 1);
}
void
spdk_file_readv_async(struct spdk_file *file, struct spdk_io_channel *channel,
struct iovec *iovs, uint32_t iovcnt, uint64_t offset, uint64_t length,
spdk_file_op_complete cb_fn, void *cb_arg)
{
SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s offset=%jx length=%jx\n",
file->name, offset, length);
__readvwritev(file, channel, iovs, iovcnt, offset, length, cb_fn, cb_arg, 1);
}
struct spdk_io_channel *
spdk_fs_alloc_io_channel(struct spdk_filesystem *fs)
{