Commit 1966f1ee authored by Changpeng Liu's avatar Changpeng Liu Committed by Ben Walker
Browse files

blobfs: add writev/readv asynchronous APIs support



Change-Id: Id1172f546852fcf25c6d13cb63f9d875b02e768c
Signed-off-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453493


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent c74ea9fa
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -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
+86 −12
Original line number Diff line number Diff line
@@ -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,8 +1790,19 @@ __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,
_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;
@@ -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)
{