Commit a2d0fa53 authored by Piotr Pelplinski's avatar Piotr Pelplinski
Browse files

spdk: add support for readv and writev in scsi layer



This patch adds support for spdk_bdev_readv in scsi layer.
It also fixes write so that it uses multiple iov's instead of one.
Currently we should use only task->iov (for single vector operation)
or task->iovs (for multiple vector operations).

Signed-off-by: default avatarPiotr Pelplinski <piotr.pelplinski@intel.com>
Change-Id: Ia3b2f6d18fd212b11d7b63b11dc46ec5bbc74788
parent 563b2caf
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -63,6 +63,10 @@

#define SPDK_SCSI_LUN_MAX_NAME_LENGTH		16

/* This flag indicated that data buffers are allocated
 * internally and hence need to be freed by the SCSI layer.*/
#define SPDK_SCSI_TASK_ALLOC_BUFFER  1

enum spdk_scsi_data_dir {
	SPDK_SCSI_DIR_NONE = 0,
	SPDK_SCSI_DIR_TO_DEV = 1,
@@ -133,11 +137,11 @@ struct spdk_scsi_task {
	struct iovec iov;
	struct iovec *iovs;
	uint16_t iovcnt;
	uint8_t iov_flags;

	uint8_t sense_data[32];
	size_t sense_data_len;

	uint8_t *rbuf; /* read buffer */
	void *blockdev_io;

	TAILQ_ENTRY(spdk_scsi_task) scsi_link;
+3 −3
Original line number Diff line number Diff line
@@ -2602,7 +2602,7 @@ spdk_iscsi_send_datain(struct spdk_iscsi_conn *conn,
	/* DATA PDU */
	rsp_pdu = spdk_get_pdu();
	rsph = (struct iscsi_bhs_data_in *)&rsp_pdu->bhs;
	rsp_pdu->data = task->scsi.rbuf + offset;
	rsp_pdu->data = task->scsi.iov.iov_base + offset;
	rsp_pdu->data_from_mempool = true;

	task_tag = task->scsi.id;
@@ -2844,7 +2844,7 @@ int spdk_iscsi_conn_handle_queued_tasks(struct spdk_iscsi_conn *conn)
			assert(subtask != NULL);
			subtask->scsi.offset = task->current_datain_offset;
			subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_RBUF_MAX_SIZE, remaining_size);
			subtask->scsi.rbuf = NULL;
			subtask->scsi.iov.iov_base = NULL;
			spdk_iscsi_queue_task(conn, subtask);
			task->current_datain_offset += subtask->scsi.length;
			conn->data_in_cnt++;
@@ -2866,7 +2866,7 @@ static int spdk_iscsi_op_scsi_read(struct spdk_iscsi_conn *conn,
	task->scsi.parent = NULL;
	task->scsi.offset = 0;
	task->scsi.length = DMIN32(SPDK_BDEV_LARGE_RBUF_MAX_SIZE, task->scsi.transfer_len);
	task->scsi.rbuf = NULL;
	task->scsi.iov.iov_base = NULL;

	remaining_size = task->scsi.transfer_len - task->scsi.length;
	task->current_datain_offset = 0;
+7 −8
Original line number Diff line number Diff line
@@ -1300,9 +1300,8 @@ spdk_bdev_scsi_task_complete(spdk_event_t event)
			spdk_scsi_lun_clear_all(task->lun);
		}
	}

	if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
		task->rbuf = bdev_io->u.read.iovs[0].iov_base;
		task->iov.iov_base = bdev_io->u.read.iovs[0].iov_base;
	}

	spdk_scsi_lun_complete_task(task->lun, task);
@@ -1334,11 +1333,11 @@ spdk_bdev_scsi_read(struct spdk_bdev *bdev,
		SPDK_ERRLOG("end of media\n");
		return -1;
	}

	task->blockdev_io = spdk_bdev_read(bdev, task->ch, task->rbuf, offset, nbytes,
	task->blockdev_io = spdk_bdev_readv(bdev, task->ch, task->iovs,
					    task->iovcnt, offset, nbytes,
					    spdk_bdev_scsi_task_complete, task);
	if (!task->blockdev_io) {
		SPDK_ERRLOG("spdk_bdev_read() failed\n");
		SPDK_ERRLOG("spdk_bdev_readv() failed\n");
		return -1;
	}

@@ -1385,8 +1384,8 @@ spdk_bdev_scsi_write(struct spdk_bdev *bdev,
	}

	offset += task->offset;
	task->blockdev_io = spdk_bdev_writev(bdev, task->ch, &task->iov,
					     1, offset, task->length,
	task->blockdev_io = spdk_bdev_writev(bdev, task->ch, task->iovs,
					     task->iovcnt, offset, task->length,
					     spdk_bdev_scsi_task_complete,
					     task);

+9 −10
Original line number Diff line number Diff line
@@ -59,12 +59,10 @@ spdk_scsi_task_put(struct spdk_scsi_task *task)
				bdev_io->status = SPDK_BDEV_IO_STATUS_FAILED;
			}
			spdk_bdev_free_io(bdev_io);
		} else {
			spdk_free(task->rbuf);
		} else if (task->iov_flags & SPDK_SCSI_TASK_ALLOC_BUFFER) {
			spdk_free(task->iov.iov_base);
		}

		task->rbuf = NULL;

		assert(task->owner_task_ctr != NULL);
		if (*(task->owner_task_ctr) > 0) {
			*(task->owner_task_ctr) -= 1;
@@ -122,13 +120,14 @@ spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
	if (alloc_len < 4096) {
		alloc_len = 4096;
	}

	task->alloc_len = alloc_len;
	if (task->rbuf == NULL) {
		task->rbuf = spdk_zmalloc(alloc_len, 0, NULL);
	/* This is workaround for buffers shorter than 4kb */
	if (task->iov.iov_base == NULL) {
		task->iov.iov_base = spdk_zmalloc(alloc_len, 0, NULL);
		task->iov_flags |= SPDK_SCSI_TASK_ALLOC_BUFFER;
	}
	*data = task->rbuf;
	memset(task->rbuf, 0, task->alloc_len);
	task->alloc_len = alloc_len;
	*data = task->iov.iov_base;
	memset(task->iov.iov_base, 0, task->alloc_len);
}

void
+7 −8
Original line number Diff line number Diff line
@@ -76,11 +76,9 @@ void
spdk_scsi_task_put(struct spdk_scsi_task *task)
{
	g_task_count--;

	if (task->rbuf) {
		free(task->rbuf);
	if (task->iov_flags & SPDK_SCSI_TASK_ALLOC_BUFFER) {
		free(task->iov.iov_base);
	}

	free(task);
}

@@ -98,7 +96,7 @@ spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
		alloc_len = 4096;

	task->alloc_len = alloc_len;
	*data = task->rbuf;
	*data = task->iov.iov_base;
}

void spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev,
@@ -420,7 +418,8 @@ lun_append_task_null_lun_task_cdb_spc_inquiry(void)
	/* alloc_len >= 4096 */
	task->cdb[3] = 0xFF;
	task->cdb[4] = 0xFF;
	task->rbuf = malloc(65536);
	task->iov.iov_base = malloc(65536);
	task->iov_flags |= SPDK_SCSI_TASK_ALLOC_BUFFER;
	task->lun = NULL;

	spdk_scsi_lun_append_task(NULL, task);
@@ -446,8 +445,8 @@ lun_append_task_null_lun_alloc_len_lt_4096(void)
	task->cdb[4] = 0;
	/* alloc_len is set to a minimal value of 4096
	 * Hence, rbuf of size 4096 is allocated*/
	task->rbuf = malloc(4096);

	task->iov.iov_base = malloc(4096);
	task->iov_flags |= SPDK_SCSI_TASK_ALLOC_BUFFER;
	spdk_scsi_lun_append_task(NULL, task);

	CU_ASSERT_EQUAL(task->status, SPDK_SCSI_STATUS_GOOD);
Loading