diff --git a/include/spdk/scsi.h b/include/spdk/scsi.h index 02fc9f727..86b75bf89 100644 --- a/include/spdk/scsi.h +++ b/include/spdk/scsi.h @@ -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; diff --git a/lib/iscsi/iscsi.c b/lib/iscsi/iscsi.c index 0137b4043..7432e783f 100644 --- a/lib/iscsi/iscsi.c +++ b/lib/iscsi/iscsi.c @@ -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; diff --git a/lib/scsi/scsi_bdev.c b/lib/scsi/scsi_bdev.c index 1ef5eb5c9..5ddccd8a6 100644 --- a/lib/scsi/scsi_bdev.c +++ b/lib/scsi/scsi_bdev.c @@ -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); diff --git a/lib/scsi/task.c b/lib/scsi/task.c index 0c8426a29..d487a60aa 100644 --- a/lib/scsi/task.c +++ b/lib/scsi/task.c @@ -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 diff --git a/test/lib/scsi/lun/lun_ut.c b/test/lib/scsi/lun/lun_ut.c index 04371f662..8878d001b 100644 --- a/test/lib/scsi/lun/lun_ut.c +++ b/test/lib/scsi/lun/lun_ut.c @@ -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); diff --git a/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c b/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c index abe1e6ed6..36cc814b4 100644 --- a/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c +++ b/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c @@ -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);