From 0095e2b9940e72395bcbc56f8c41635a9861e148 Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Tue, 8 Nov 2016 23:03:37 -0700 Subject: [PATCH] bdev/nvme: account for 2MB straddle in queued_next_sge() This function needs to check for SGEs that straddle a 2MB page boundary, and ensure it does not return a length that will cross that boundary. This cannot happen in practice currently with SPDK since all buffers are allocated using rte_malloc(), but an upcoming vhost-scsi target may produce SGEs from a guest VM's physical memory that span a 2MB boundary. Signed-off-by: Jim Harris Change-Id: I8b83c7c39c4cf33815abb22ff2ebc90941b21e28 --- lib/bdev/nvme/blockdev_nvme.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/bdev/nvme/blockdev_nvme.c b/lib/bdev/nvme/blockdev_nvme.c index 61ee35ab8..aa7c08a5f 100644 --- a/lib/bdev/nvme/blockdev_nvme.c +++ b/lib/bdev/nvme/blockdev_nvme.c @@ -639,6 +639,10 @@ queued_reset_sgl(void *ref, uint32_t sgl_offset) } } +#define min(a, b) (((a)<(b))?(a):(b)) + +#define _2MB_OFFSET(ptr) (((uintptr_t)ptr) & (0x200000 - 1)) + static int queued_next_sge(void *ref, void **address, uint32_t *length) { @@ -658,6 +662,8 @@ queued_next_sge(void *ref, void **address, uint32_t *length) *length -= bio->iov_offset; } + *length = min(*length, 0x200000 - _2MB_OFFSET(*address)); + bio->iov_offset += *length; if (bio->iov_offset == iov->iov_len) { bio->iovpos++;