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: Piotr Pelplinski <piotr.pelplinski@intel.com>
Change-Id: Ia3b2f6d18fd212b11d7b63b11dc46ec5bbc74788
This commit is contained in:
Piotr Pelplinski 2016-10-21 17:05:19 +02:00
parent 563b2caf06
commit a2d0fa5351
6 changed files with 45 additions and 36 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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,
spdk_bdev_scsi_task_complete, task);
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);

View File

@ -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

View File

@ -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);

View File

@ -69,7 +69,7 @@ spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
}
task->alloc_len = alloc_len;
*data = task->rbuf;
*data = task->iov.iov_base;
}
void
@ -127,6 +127,14 @@ spdk_bdev_read(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
return NULL;
}
struct spdk_bdev_io *
spdk_bdev_readv(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
struct iovec *iov, int iovcnt, uint64_t offset, uint64_t nbytes,
spdk_bdev_io_completion_cb cb, void *cb_arg)
{
return NULL;
}
struct spdk_bdev_io *
spdk_bdev_writev(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
struct iovec *iov, int iovcnt,
@ -261,7 +269,7 @@ mode_sense_6_test(void)
lun.dev = &dev;
task.lun = &lun;
task.rbuf = data;
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task);
mode_data_len = data[0];
@ -306,7 +314,7 @@ mode_sense_10_test(void)
lun.dev = &dev;
task.lun = &lun;
task.rbuf = data;
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task);
mode_data_len = ((data[0] << 8) + data[1]);
@ -350,7 +358,7 @@ inquiry_evpd_test(void)
task.lun = &lun;
memset(data, 0, 4096);
task.rbuf = data;
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task);
@ -394,7 +402,7 @@ inquiry_standard_test(void)
task.lun = &lun;
memset(data, 0, 4096);
task.rbuf = data;
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task);
@ -433,7 +441,7 @@ _inquiry_overflow_test(uint8_t alloc_len)
memset(data, 0, sizeof(data));
memset(data_compare, 0, sizeof(data_compare));
task.rbuf = data;
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task);
CU_ASSERT_EQUAL(rc, 0);