From ed8df49d2f05502627be511a38e4396fa0a8f427 Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Mon, 25 Jun 2018 11:41:17 -0700 Subject: [PATCH] bdev: Make spdk_bdev_io_set_buf public Also make it correctly account for alignment and automatically use the internal iov element if necessary. Change-Id: I0b33ef9444f0693c2d6b0cdaf221c4a5b0ad2cc3 Signed-off-by: Ben Walker Reviewed-on: https://review.gerrithub.io/416870 Tested-by: SPDK Automated Test System Reviewed-by: Daniel Verkamp Reviewed-by: Shuhei Matsumoto --- include/spdk/bdev_module.h | 14 ++++++++++ lib/bdev/bdev.c | 55 +++++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/include/spdk/bdev_module.h b/include/spdk/bdev_module.h index 9be50ebc08..bb66465a7c 100644 --- a/include/spdk/bdev_module.h +++ b/include/spdk/bdev_module.h @@ -584,6 +584,20 @@ const struct spdk_bdev_aliases_list *spdk_bdev_get_aliases(const struct spdk_bde */ void spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, uint64_t len); +/** + * Set the given buffer as the data buffer described by this bdev_io. + * + * The portion of the buffer used may be adjusted for memory alignement + * purposes. + * + * \param bdev_io I/O to set the buffer on. + * \param buf The buffer to set as the active data buffer. + * \param len The length of the buffer. + * + * \return The usable size of the buffer, after adjustments of alignment. + */ +size_t spdk_bdev_io_set_buf(struct spdk_bdev_io *bdev_io, void *buf, size_t len); + /** * Complete a bdev_io * diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 23e17c76be..a6644dddc8 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -377,14 +377,12 @@ spdk_bdev_get_by_name(const char *bdev_name) return NULL; } -static void -spdk_bdev_io_set_buf(struct spdk_bdev_io *bdev_io, void *buf) +size_t +spdk_bdev_io_set_buf(struct spdk_bdev_io *bdev_io, void *buf, size_t len) { struct iovec **iovs; int *iovcnt; - - assert(bdev_io->internal.get_buf_cb != NULL); - assert(buf != NULL); + void *aligned_buf; iovs = &bdev_io->u.bdev.iovs; iovcnt = &bdev_io->u.bdev.iovcnt; @@ -394,13 +392,18 @@ spdk_bdev_io_set_buf(struct spdk_bdev_io *bdev_io, void *buf) *iovcnt = 1; } - (*iovs)[0].iov_base = (void *)((unsigned long)((char *)buf + 512) & ~511UL); - (*iovs)[0].iov_len = bdev_io->internal.buf_len; + if (buf != NULL) { + aligned_buf = (void *)(((uintptr_t)buf + 512) & ~511UL); + len = len - ((uintptr_t)aligned_buf - (uintptr_t)buf); + } else { + aligned_buf = NULL; + assert(len == 0); + } - bdev_io->internal.buf = buf; - bdev_io->u.bdev.iovs[0].iov_base = (void *)((unsigned long)((char *)buf + 512) & ~511UL); - bdev_io->u.bdev.iovs[0].iov_len = bdev_io->internal.buf_len; - bdev_io->internal.get_buf_cb(bdev_io->internal.ch->channel, bdev_io); + (*iovs)[0].iov_base = aligned_buf; + (*iovs)[0].iov_len = len; + + return len; } static void @@ -411,6 +414,7 @@ spdk_bdev_io_put_buf(struct spdk_bdev_io *bdev_io) void *buf; bdev_io_stailq_t *stailq; struct spdk_bdev_mgmt_channel *ch; + size_t len; assert(bdev_io->u.bdev.iovcnt == 1); @@ -420,9 +424,11 @@ spdk_bdev_io_put_buf(struct spdk_bdev_io *bdev_io) if (bdev_io->internal.buf_len <= SPDK_BDEV_SMALL_BUF_MAX_SIZE) { pool = g_bdev_mgr.buf_small_pool; stailq = &ch->need_buf_small; + len = SPDK_BDEV_SMALL_BUF_MAX_SIZE + 512; } else { pool = g_bdev_mgr.buf_large_pool; stailq = &ch->need_buf_large; + len = SPDK_BDEV_LARGE_BUF_MAX_SIZE + 512; } if (STAILQ_EMPTY(stailq)) { @@ -430,7 +436,15 @@ spdk_bdev_io_put_buf(struct spdk_bdev_io *bdev_io) } else { tmp = STAILQ_FIRST(stailq); STAILQ_REMOVE_HEAD(stailq, internal.buf_link); - spdk_bdev_io_set_buf(tmp, buf); + len = spdk_bdev_io_set_buf(tmp, buf, len); + if (len < tmp->internal.buf_len) { + SPDK_ERRLOG("Unable to use buffer due to alignment\n"); + spdk_mempool_put(pool, buf); + spdk_bdev_io_set_buf(tmp, NULL, 0); + return; + } + tmp->internal.buf = buf; + tmp->internal.get_buf_cb(tmp->internal.ch->channel, tmp); } } @@ -441,6 +455,7 @@ spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, u bdev_io_stailq_t *stailq; void *buf = NULL; struct spdk_bdev_mgmt_channel *mgmt_ch; + size_t buf_len; assert(cb != NULL); assert(bdev_io->u.bdev.iovs != NULL); @@ -459,9 +474,11 @@ spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, u if (len <= SPDK_BDEV_SMALL_BUF_MAX_SIZE) { pool = g_bdev_mgr.buf_small_pool; stailq = &mgmt_ch->need_buf_small; + buf_len = SPDK_BDEV_SMALL_BUF_MAX_SIZE + 512; } else { pool = g_bdev_mgr.buf_large_pool; stailq = &mgmt_ch->need_buf_large; + buf_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE + 512; } buf = spdk_mempool_get(pool); @@ -469,7 +486,19 @@ spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, u if (!buf) { STAILQ_INSERT_TAIL(stailq, bdev_io, internal.buf_link); } else { - spdk_bdev_io_set_buf(bdev_io, buf); + size_t aligned_len; + + aligned_len = spdk_bdev_io_set_buf(bdev_io, buf, buf_len); + if (aligned_len < len) { + SPDK_ERRLOG("Unable to use buffer after alignment calculations.\n"); + spdk_mempool_put(pool, buf); + spdk_bdev_io_set_buf(bdev_io, NULL, 0); + STAILQ_INSERT_TAIL(stailq, bdev_io, internal.buf_link); + return; + } + + bdev_io->internal.buf = buf; + bdev_io->internal.get_buf_cb(bdev_io->internal.ch->channel, bdev_io); } }