Commit cfe8449e authored by Jim Harris's avatar Jim Harris Committed by Tomasz Zawadzki
Browse files

scsi: round task->iov.iov_base allocation up to nearest 4 bytes



Some SCSI commands such as INQUIRY may generate an odd number
of bytes in its response, not evenly divisible by 4.

But iSCSI must align all transfer-in PDUs to 4-byte multiple.
After enabling DPDK ASAN, we discover that the SCSI task
response buffer was allocating exactly the size of the INQUIRY
reponse, but iSCSI rounds this up, and ends up doing a sendmsg()
off the end of the buffer for those trailing bytes.

We could try to fix this in iSCSI layer, but it makes the code
more complex - it would need to allocate some separate buffer for
those extra bytes, or allocate a new buffer and copy the bytes
over.

So instead fix this down in the SCSI layer when the buffer is
allocated, still report the iov_len as the smaller amount, but
allocate an actual buffer that is rounded up to the nearest 4.

Fixes issue #3203.

Signed-off-by: default avatarJim Harris <jim.harris@samsung.com>
Change-Id: I702fe1b543c95388fa1dfa8c7cafb2538917479f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/20853


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
parent 6f4e0c95
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -69,9 +69,17 @@ spdk_scsi_task_construct(struct spdk_scsi_task *task,
static void *
scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
{
	uint32_t zmalloc_len;

	assert(task->alloc_len == 0);

	task->iov.iov_base = spdk_dma_zmalloc(alloc_len, 0, NULL);
	/* Some ULPs (such as iSCSI) need to round len up to nearest
	 * 4 bytes. We can help those ULPs by allocating memory here
	 * up to next 4 byte boundary, so they don't have to worry
	 * about handling out-of-bounds errors.
	 */
	zmalloc_len = 4 * spdk_divide_round_up(alloc_len, 4);
	task->iov.iov_base = spdk_dma_zmalloc(zmalloc_len, 0, NULL);
	task->iov.iov_len = alloc_len;
	task->alloc_len = alloc_len;