scsi: refactor usage of iov from spdk_scsi_task

This patch is preparation for fixing alloc_len overrun in SENSE 6/10 and
READCAP 6/10. To simplify code forbid usage of iov outside of
scsi/task.c.

This also drop SPDK_SCSI_TASK_ALLOC_BUFFER flag that obfuscate code. As
a replacement assume that if field alloc_len is non zero it mean that
iov.buffer is internally allocated. Functions
spdk_scsi_task_free_data(), spdk_scsi_task_set_data() and
spdk_scsi_task_alloc_data() manage this field.

Change-Id: Ife357a5bc36121f93a4c5d259b9a5a01559e7708
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
This commit is contained in:
Pawel Wodkowski 2016-11-04 19:45:54 +01:00 committed by Daniel Verkamp
parent 51c6917fad
commit f30f0c76f1
7 changed files with 205 additions and 76 deletions

View File

@ -63,10 +63,6 @@
#define SPDK_SCSI_LUN_MAX_NAME_LENGTH 16 #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 { enum spdk_scsi_data_dir {
SPDK_SCSI_DIR_NONE = 0, SPDK_SCSI_DIR_NONE = 0,
SPDK_SCSI_DIR_TO_DEV = 1, SPDK_SCSI_DIR_TO_DEV = 1,
@ -125,7 +121,6 @@ struct spdk_scsi_task {
* transfer_len - i.e. SCSI INQUIRY. * transfer_len - i.e. SCSI INQUIRY.
*/ */
uint32_t data_transferred; uint32_t data_transferred;
uint32_t alloc_len;
uint64_t offset; uint64_t offset;
struct spdk_scsi_task *parent; struct spdk_scsi_task *parent;
@ -134,10 +129,18 @@ struct spdk_scsi_task {
uint8_t *cdb; uint8_t *cdb;
/**
* \internal
* Size of internal buffer or zero when iov.iov_base is not internally managed.
*/
uint32_t alloc_len;
/**
* \internal
* iov is internal buffer. Use iovs to access elements of IO.
*/
struct iovec iov; struct iovec iov;
struct iovec *iovs; struct iovec *iovs;
uint16_t iovcnt; uint16_t iovcnt;
uint8_t iov_flags;
uint8_t sense_data[32]; uint8_t sense_data[32];
size_t sense_data_len; size_t sense_data_len;
@ -256,8 +259,30 @@ int spdk_scsi_port_construct(struct spdk_scsi_port *port, uint64_t id,
void spdk_scsi_task_construct(struct spdk_scsi_task *task, uint32_t *owner_task_ctr, void spdk_scsi_task_construct(struct spdk_scsi_task *task, uint32_t *owner_task_ctr,
struct spdk_scsi_task *parent); struct spdk_scsi_task *parent);
void spdk_scsi_task_put(struct spdk_scsi_task *task); void spdk_scsi_task_put(struct spdk_scsi_task *task);
void spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
uint8_t **data); void spdk_scsi_task_free_data(struct spdk_scsi_task *task);
/**
* Set internal buffer to given one. Caller is owner of that buffer.
*
* \param task Task struct
* \param data Pointer to buffer
* \param len Buffer length
*/
void spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len);
/**
* Allocate internal buffer of requested size. Caller is not owner of
* returned buffer and must not free it. Caller is permitted to call
* spdk_scsi_task_free_data() to free internal buffer if it is not required
* anymore, but must assert that task is done and not used by library.
* The count of io vectors must by one. Any previously allocated buffer will be
* invalid after this call.
*
* \param task Task struct
* \param alloc_len Size of allocated buffer.
* \return Pointer to buffer or NULL on error.
*/
void *spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len);
void spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc, void spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc,
int ascq); int ascq);
void spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk, int asc, void spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk, int asc,

View File

@ -2602,7 +2602,7 @@ spdk_iscsi_send_datain(struct spdk_iscsi_conn *conn,
/* DATA PDU */ /* DATA PDU */
rsp_pdu = spdk_get_pdu(); rsp_pdu = spdk_get_pdu();
rsph = (struct iscsi_bhs_data_in *)&rsp_pdu->bhs; rsph = (struct iscsi_bhs_data_in *)&rsp_pdu->bhs;
rsp_pdu->data = task->scsi.iov.iov_base + offset; rsp_pdu->data = task->scsi.iovs[0].iov_base + offset;
rsp_pdu->data_from_mempool = true; rsp_pdu->data_from_mempool = true;
task_tag = task->scsi.id; task_tag = task->scsi.id;
@ -2844,7 +2844,7 @@ int spdk_iscsi_conn_handle_queued_tasks(struct spdk_iscsi_conn *conn)
assert(subtask != NULL); assert(subtask != NULL);
subtask->scsi.offset = task->current_datain_offset; subtask->scsi.offset = task->current_datain_offset;
subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_RBUF_MAX_SIZE, remaining_size); subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_RBUF_MAX_SIZE, remaining_size);
subtask->scsi.iov.iov_base = NULL; spdk_scsi_task_set_data(&subtask->scsi, NULL, 0);
spdk_iscsi_queue_task(conn, subtask); spdk_iscsi_queue_task(conn, subtask);
task->current_datain_offset += subtask->scsi.length; task->current_datain_offset += subtask->scsi.length;
conn->data_in_cnt++; 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.parent = NULL;
task->scsi.offset = 0; task->scsi.offset = 0;
task->scsi.length = DMIN32(SPDK_BDEV_LARGE_RBUF_MAX_SIZE, task->scsi.transfer_len); task->scsi.length = DMIN32(SPDK_BDEV_LARGE_RBUF_MAX_SIZE, task->scsi.transfer_len);
task->scsi.iov.iov_base = NULL; spdk_scsi_task_set_data(&task->scsi, NULL, 0);
remaining_size = task->scsi.transfer_len - task->scsi.length; remaining_size = task->scsi.transfer_len - task->scsi.length;
task->current_datain_offset = 0; task->current_datain_offset = 0;
@ -2985,16 +2985,14 @@ spdk_iscsi_op_scsi(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
else { else {
/* we are doing the first partial write task */ /* we are doing the first partial write task */
task->scsi.ref++; task->scsi.ref++;
task->scsi.iov.iov_base = pdu->data; spdk_scsi_task_set_data(&task->scsi, pdu->data, pdu->data_segment_len);
task->scsi.iov.iov_len = pdu->data_segment_len;
task->scsi.length = pdu->data_segment_len; task->scsi.length = pdu->data_segment_len;
} }
} }
if (pdu->data_segment_len == transfer_len) { if (pdu->data_segment_len == transfer_len) {
/* we are doing small writes with no R2T */ /* we are doing small writes with no R2T */
task->scsi.iov.iov_len = transfer_len; spdk_scsi_task_set_data(&task->scsi, pdu->data, transfer_len);
task->scsi.iov.iov_base = pdu->data;
task->scsi.length = transfer_len; task->scsi.length = transfer_len;
} }
} else { } else {
@ -4083,8 +4081,7 @@ static int spdk_iscsi_op_data(struct spdk_iscsi_conn *conn,
} }
subtask->scsi.offset = buffer_offset; subtask->scsi.offset = buffer_offset;
subtask->scsi.length = pdu->data_segment_len; subtask->scsi.length = pdu->data_segment_len;
subtask->scsi.iov.iov_base = pdu->data; spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_segment_len);
subtask->scsi.iov.iov_len = pdu->data_segment_len;
spdk_iscsi_task_associate_pdu(subtask, pdu); spdk_iscsi_task_associate_pdu(subtask, pdu);
if (task->next_expected_r2t_offset == transfer_len) { if (task->next_expected_r2t_offset == transfer_len) {

View File

@ -194,7 +194,7 @@ complete_task_with_no_lun(struct spdk_scsi_task *task)
* PERIPHERAL DEVICE TYPE = 0x1F. * PERIPHERAL DEVICE TYPE = 0x1F.
*/ */
allocation_len = from_be16(&task->cdb[3]); allocation_len = from_be16(&task->cdb[3]);
spdk_scsi_task_alloc_data(task, allocation_len, &data); data = spdk_scsi_task_alloc_data(task, allocation_len);
data_len = 36; data_len = 36;
memset(data, 0, data_len); memset(data, 0, data_len);
/* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */ /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */

View File

@ -1317,8 +1317,9 @@ spdk_bdev_scsi_task_complete(spdk_event_t event)
spdk_scsi_lun_clear_all(task->lun); spdk_scsi_lun_clear_all(task->lun);
} }
} }
if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) { if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ && task->iovs != bdev_io->u.read.iovs) {
task->iov.iov_base = bdev_io->u.read.iovs[0].iov_base; assert(task->iovcnt == bdev_io->u.read.iovcnt);
memcpy(task->iovs, bdev_io->u.read.iovs, sizeof(task->iovs[0]) * task->iovcnt);
} }
spdk_scsi_lun_complete_task(task->lun, task); spdk_scsi_lun_complete_task(task->lun, task);
@ -1510,7 +1511,7 @@ spdk_bdev_scsi_unmap(struct spdk_bdev *bdev,
uint8_t *data; uint8_t *data;
uint16_t bdesc_data_len, bdesc_count; uint16_t bdesc_data_len, bdesc_count;
data = (uint8_t *)task->iov.iov_base; data = (uint8_t *)task->iovs[0].iov_base;
/* /*
* The UNMAP BLOCK DESCRIPTOR DATA LENGTH field specifies the length in * The UNMAP BLOCK DESCRIPTOR DATA LENGTH field specifies the length in
@ -1591,7 +1592,7 @@ spdk_bdev_scsi_process_block(struct spdk_bdev *bdev,
return spdk_bdev_scsi_readwrite(bdev, task, lba, xfer_len); return spdk_bdev_scsi_readwrite(bdev, task, lba, xfer_len);
case SPDK_SBC_READ_CAPACITY_10: case SPDK_SBC_READ_CAPACITY_10:
spdk_scsi_task_alloc_data(task, 8, &data); data = spdk_scsi_task_alloc_data(task, 8);
if (bdev->blockcnt - 1 > 0xffffffffULL) { if (bdev->blockcnt - 1 > 0xffffffffULL) {
memset(data, 0xff, 4); memset(data, 0xff, 4);
} else { } else {
@ -1605,7 +1606,7 @@ spdk_bdev_scsi_process_block(struct spdk_bdev *bdev,
case SPDK_SPC_SERVICE_ACTION_IN_16: case SPDK_SPC_SERVICE_ACTION_IN_16:
switch (cdb[1] & 0x1f) { /* SERVICE ACTION */ switch (cdb[1] & 0x1f) { /* SERVICE ACTION */
case SPDK_SBC_SAI_READ_CAPACITY_16: case SPDK_SBC_SAI_READ_CAPACITY_16:
spdk_scsi_task_alloc_data(task, 32, &data); data = spdk_scsi_task_alloc_data(task, 32);
to_be64(&data[0], bdev->blockcnt - 1); to_be64(&data[0], bdev->blockcnt - 1);
to_be32(&data[8], bdev->blocklen); to_be32(&data[8], bdev->blocklen);
/* /*
@ -1669,7 +1670,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
switch (cdb[0]) { switch (cdb[0]) {
case SPDK_SPC_INQUIRY: case SPDK_SPC_INQUIRY:
alloc_len = from_be16(&cdb[3]); alloc_len = from_be16(&cdb[3]);
spdk_scsi_task_alloc_data(task, alloc_len, &data); data = spdk_scsi_task_alloc_data(task, alloc_len);
data_len = spdk_bdev_scsi_inquiry(bdev, task, cdb, data_len = spdk_bdev_scsi_inquiry(bdev, task, cdb,
data, alloc_len); data, alloc_len);
if (data_len < 0) { if (data_len < 0) {
@ -1697,7 +1698,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
break; break;
} }
spdk_scsi_task_alloc_data(task, alloc_len, &data); data = spdk_scsi_task_alloc_data(task, alloc_len);
data_len = spdk_bdev_scsi_report_luns(task->lun, sel, data, task->alloc_len); data_len = spdk_bdev_scsi_report_luns(task->lun, sel, data, task->alloc_len);
if (data_len < 0) { if (data_len < 0) {
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
@ -1715,7 +1716,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
case SPDK_SPC_MODE_SELECT_6: case SPDK_SPC_MODE_SELECT_6:
case SPDK_SPC_MODE_SELECT_10: case SPDK_SPC_MODE_SELECT_10:
data = task->iov.iov_base; data = task->iovs[0].iov_base;
if (cdb[0] == SPDK_SPC_MODE_SELECT_6) { if (cdb[0] == SPDK_SPC_MODE_SELECT_6) {
md = 4; md = 4;
@ -1792,7 +1793,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
page = cdb[2] & 0x3f; page = cdb[2] & 0x3f;
subpage = cdb[3]; subpage = cdb[3];
spdk_scsi_task_alloc_data(task, alloc_len, &data); data = spdk_scsi_task_alloc_data(task, alloc_len);
if (md == 6) { if (md == 6) {
data_len = spdk_bdev_scsi_mode_sense6(bdev, data_len = spdk_bdev_scsi_mode_sense6(bdev,
@ -1838,7 +1839,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
} }
alloc_len = cdb[4]; alloc_len = cdb[4];
spdk_scsi_task_alloc_data(task, alloc_len, &data); data = spdk_scsi_task_alloc_data(task, alloc_len);
/* NO ADDITIONAL SENSE INFORMATION */ /* NO ADDITIONAL SENSE INFORMATION */
sk = SPDK_SCSI_SENSE_NO_SENSE; sk = SPDK_SCSI_SENSE_NO_SENSE;

View File

@ -59,11 +59,11 @@ spdk_scsi_task_put(struct spdk_scsi_task *task)
bdev_io->status = SPDK_BDEV_IO_STATUS_FAILED; bdev_io->status = SPDK_BDEV_IO_STATUS_FAILED;
} }
spdk_bdev_free_io(bdev_io); spdk_bdev_free_io(bdev_io);
} else if (task->iov_flags & SPDK_SCSI_TASK_ALLOC_BUFFER) {
spdk_free(task->iov.iov_base);
} }
spdk_scsi_task_free_data(task);
assert(task->owner_task_ctr != NULL); assert(task->owner_task_ctr != NULL);
if (*(task->owner_task_ctr) > 0) { if (*(task->owner_task_ctr) > 0) {
*(task->owner_task_ctr) -= 1; *(task->owner_task_ctr) -= 1;
} else { } else {
@ -87,6 +87,7 @@ spdk_scsi_task_construct(struct spdk_scsi_task *task, uint32_t *owner_task_ctr,
/* /*
* Pre-fill the iov_buffers to point to the embedded iov * Pre-fill the iov_buffers to point to the embedded iov
*/ */
assert(task->iov.iov_base == NULL);
task->iovs = &task->iov; task->iovs = &task->iov;
task->iovcnt = 1; task->iovcnt = 1;
@ -105,8 +106,19 @@ spdk_scsi_task_construct(struct spdk_scsi_task *task, uint32_t *owner_task_ctr,
} }
void void
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len, spdk_scsi_task_free_data(struct spdk_scsi_task *task)
uint8_t **data) {
if (task->alloc_len != 0) {
spdk_free(task->iov.iov_base);
task->alloc_len = 0;
}
task->iov.iov_base = NULL;
task->iov.iov_len = 0;
}
void *
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
{ {
/* /*
* SPDK iSCSI target depends on allocating at least 4096 bytes, even if * SPDK iSCSI target depends on allocating at least 4096 bytes, even if
@ -117,17 +129,37 @@ spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
* care of only sending back the amount of data specified in the * care of only sending back the amount of data specified in the
* allocation length. * allocation length.
*/ */
assert(task->alloc_len == 0);
/* Only one buffer is managable */
if (task->iovcnt != 1) {
return NULL;
}
if (alloc_len < 4096) { if (alloc_len < 4096) {
alloc_len = 4096; alloc_len = 4096;
} }
/* This is workaround for buffers shorter than 4kb */ /* This is workaround for buffers shorter than 4kb */
if (task->iov.iov_base == NULL) { if (task->iov.iov_base == NULL) {
task->iov.iov_base = spdk_zmalloc(alloc_len, 0, NULL); task->iov.iov_base = spdk_zmalloc(alloc_len, 0, NULL);
task->iov_flags |= SPDK_SCSI_TASK_ALLOC_BUFFER; task->alloc_len = alloc_len;
} }
task->alloc_len = alloc_len;
*data = task->iov.iov_base; task->iov.iov_len = alloc_len;
memset(task->iov.iov_base, 0, task->alloc_len); assert(&task->iov == task->iovs);
return task->iov.iov_base;
}
void
spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
{
assert(task->iovcnt == 1);
assert(task->alloc_len == 0);
task->iovs[0].iov_base = data;
task->iovs[0].iov_len = len;
} }
void void

View File

@ -66,6 +66,8 @@ spdk_get_task(uint32_t *owner_task_ctr)
} }
task->id = g_task_count; task->id = g_task_count;
task->iovs = &task->iov;
task->iovcnt = 1;
g_task_count++; g_task_count++;
@ -76,7 +78,7 @@ void
spdk_scsi_task_put(struct spdk_scsi_task *task) spdk_scsi_task_put(struct spdk_scsi_task *task)
{ {
g_task_count--; g_task_count--;
if (task->iov_flags & SPDK_SCSI_TASK_ALLOC_BUFFER) { if (task->alloc_len) {
free(task->iov.iov_base); free(task->iov.iov_base);
} }
free(task); free(task);
@ -89,15 +91,17 @@ spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
task->status = sc; task->status = sc;
} }
void void *
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len, spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
uint8_t **data)
{ {
if (alloc_len < 4096) if (alloc_len < 4096)
alloc_len = 4096; alloc_len = 4096;
task->iovs = &task->iov;
task->iov.iov_base = malloc(alloc_len);
task->iov.iov_len = alloc_len;
task->alloc_len = alloc_len; task->alloc_len = alloc_len;
*data = task->iov.iov_base; return task->iov.iov_base;
} }
void spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev, void spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev,
@ -419,8 +423,6 @@ lun_append_task_null_lun_task_cdb_spc_inquiry(void)
/* alloc_len >= 4096 */ /* alloc_len >= 4096 */
task->cdb[3] = 0xFF; task->cdb[3] = 0xFF;
task->cdb[4] = 0xFF; task->cdb[4] = 0xFF;
task->iov.iov_base = malloc(65536);
task->iov_flags |= SPDK_SCSI_TASK_ALLOC_BUFFER;
task->lun = NULL; task->lun = NULL;
spdk_scsi_lun_append_task(NULL, task); spdk_scsi_lun_append_task(NULL, task);
@ -446,8 +448,6 @@ lun_append_task_null_lun_alloc_len_lt_4096(void)
task->cdb[4] = 0; task->cdb[4] = 0;
/* alloc_len is set to a minimal value of 4096 /* alloc_len is set to a minimal value of 4096
* Hence, rbuf of size 4096 is allocated*/ * Hence, rbuf of size 4096 is allocated*/
task->iov.iov_base = malloc(4096);
task->iov_flags |= SPDK_SCSI_TASK_ALLOC_BUFFER;
spdk_scsi_lun_append_task(NULL, task); spdk_scsi_lun_append_task(NULL, task);
CU_ASSERT_EQUAL(task->status, SPDK_SCSI_STATUS_GOOD); CU_ASSERT_EQUAL(task->status, SPDK_SCSI_STATUS_GOOD);

View File

@ -37,7 +37,7 @@
#include "scsi_bdev.c" #include "scsi_bdev.c"
#include "CUnit/Basic.h" #include "spdk_cunit.h"
SPDK_LOG_REGISTER_TRACE_FLAG("scsi", SPDK_TRACE_SCSI) SPDK_LOG_REGISTER_TRACE_FLAG("scsi", SPDK_TRACE_SCSI)
@ -61,16 +61,66 @@ spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
task->status = sc; task->status = sc;
} }
static void
spdk_put_task(struct spdk_scsi_task *task)
{
spdk_scsi_task_free_data(task);
}
static void
spdk_init_task(struct spdk_scsi_task *task)
{
memset(task, 0, sizeof(*task));
task->id = 1;
task->iovs = &task->iov;
task->iovcnt = 1;
}
void void
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len, spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
uint8_t **data) {
assert(task->alloc_len == 0);
task->iov.iov_base = data;
task->iov.iov_len = len;
task->alloc_len = 0;
}
void *
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
{ {
if (alloc_len < 4096) { if (alloc_len < 4096) {
alloc_len = 4096; alloc_len = 4096;
} }
task->alloc_len = alloc_len; if (task->iov.iov_base != NULL) {
*data = task->iov.iov_base; if (task->alloc_len != 0 && alloc_len > task->alloc_len) {
spdk_put_task(task);
} else if (task->alloc_len == 0 && alloc_len > task->iov.iov_len) {
/* External data buffer less than requested. */
return NULL;
}
}
if (task->iov.iov_base == NULL) {
task->iov.iov_base = calloc(alloc_len, 1);
task->alloc_len = alloc_len;
}
task->iov.iov_len = alloc_len;
return task->iov.iov_base;
}
void
spdk_scsi_task_free_data(struct spdk_scsi_task *task)
{
if (task->alloc_len)
free(task->iov.iov_base);
task->iov.iov_base = NULL;
task->iov.iov_len = 0;
task->alloc_len = 0;
} }
void void
@ -184,6 +234,8 @@ mode_select_6_test(void)
char data[24]; char data[24];
int rc; int rc;
spdk_init_task(&task);
cdb[0] = 0x15; cdb[0] = 0x15;
cdb[1] = 0x11; cdb[1] = 0x11;
cdb[2] = 0x00; cdb[2] = 0x00;
@ -199,11 +251,13 @@ mode_select_6_test(void)
memset(data, 0, sizeof(data)); memset(data, 0, sizeof(data));
data[4] = 0x08; data[4] = 0x08;
data[5] = 0x02; data[5] = 0x02;
task.iov.iov_base = data; spdk_scsi_task_set_data(&task, data, sizeof(data));
rc = spdk_bdev_scsi_execute(&bdev, &task); rc = spdk_bdev_scsi_execute(&bdev, &task);
CU_ASSERT_EQUAL(rc, 0); CU_ASSERT_EQUAL(rc, 0);
spdk_put_task(&task);
} }
/* /*
@ -220,6 +274,8 @@ mode_select_6_test2(void)
char cdb[16]; char cdb[16];
int rc; int rc;
spdk_init_task(&task);
cdb[0] = 0x15; cdb[0] = 0x15;
cdb[1] = 0x00; cdb[1] = 0x00;
cdb[2] = 0x00; cdb[2] = 0x00;
@ -232,11 +288,11 @@ mode_select_6_test2(void)
lun.dev = &dev; lun.dev = &dev;
task.lun = &lun; task.lun = &lun;
task.iov.iov_base = NULL;
rc = spdk_bdev_scsi_execute(&bdev, &task); rc = spdk_bdev_scsi_execute(&bdev, &task);
CU_ASSERT_EQUAL(rc, 0); CU_ASSERT_EQUAL(rc, 0);
spdk_put_task(&task);
} }
/* /*
@ -251,14 +307,15 @@ mode_sense_6_test(void)
struct spdk_scsi_lun lun; struct spdk_scsi_lun lun;
struct spdk_scsi_dev dev; struct spdk_scsi_dev dev;
char cdb[12]; char cdb[12];
unsigned char data[4096]; unsigned char *data;
int rc = 0; int rc;
unsigned char mode_data_len = 0; unsigned char mode_data_len = 0;
unsigned char medium_type = 0; unsigned char medium_type = 0;
unsigned char dev_specific_param = 0; unsigned char dev_specific_param = 0;
unsigned char blk_descriptor_len = 0; unsigned char blk_descriptor_len = 0;
memset(&bdev, 0 , sizeof(struct spdk_bdev)); memset(&bdev, 0 , sizeof(struct spdk_bdev));
spdk_init_task(&task);
memset(cdb, 0, sizeof(cdb)); memset(cdb, 0, sizeof(cdb));
cdb[0] = 0x1A; cdb[0] = 0x1A;
@ -270,9 +327,10 @@ mode_sense_6_test(void)
lun.dev = &dev; lun.dev = &dev;
task.lun = &lun; task.lun = &lun;
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task); rc = spdk_bdev_scsi_execute(&bdev, &task);
SPDK_CU_ASSERT_FATAL(rc == 0);
data = task.iovs[0].iov_base;
mode_data_len = data[0]; mode_data_len = data[0];
medium_type = data[1]; medium_type = data[1];
dev_specific_param = data[2]; dev_specific_param = data[2];
@ -282,7 +340,8 @@ mode_sense_6_test(void)
CU_ASSERT_EQUAL(medium_type, 0); CU_ASSERT_EQUAL(medium_type, 0);
CU_ASSERT_EQUAL(dev_specific_param, 0); CU_ASSERT_EQUAL(dev_specific_param, 0);
CU_ASSERT_EQUAL(blk_descriptor_len, 8); CU_ASSERT_EQUAL(blk_descriptor_len, 8);
CU_ASSERT_EQUAL(rc, 0);
spdk_put_task(&task);
} }
/* /*
@ -297,7 +356,7 @@ mode_sense_10_test(void)
struct spdk_scsi_lun lun; struct spdk_scsi_lun lun;
struct spdk_scsi_dev dev; struct spdk_scsi_dev dev;
char cdb[12]; char cdb[12];
unsigned char data[4096]; unsigned char *data;
int rc; int rc;
unsigned short mode_data_len = 0; unsigned short mode_data_len = 0;
unsigned char medium_type = 0; unsigned char medium_type = 0;
@ -305,6 +364,7 @@ mode_sense_10_test(void)
unsigned short blk_descriptor_len = 0; unsigned short blk_descriptor_len = 0;
memset(&bdev, 0 , sizeof(struct spdk_bdev)); memset(&bdev, 0 , sizeof(struct spdk_bdev));
spdk_init_task(&task);
memset(cdb, 0, sizeof(cdb)); memset(cdb, 0, sizeof(cdb));
cdb[0] = 0x5A; cdb[0] = 0x5A;
cdb[2] = 0x3F; cdb[2] = 0x3F;
@ -315,9 +375,10 @@ mode_sense_10_test(void)
lun.dev = &dev; lun.dev = &dev;
task.lun = &lun; task.lun = &lun;
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task); rc = spdk_bdev_scsi_execute(&bdev, &task);
SPDK_CU_ASSERT_FATAL(rc == 0);
data = task.iovs[0].iov_base;
mode_data_len = ((data[0] << 8) + data[1]); mode_data_len = ((data[0] << 8) + data[1]);
medium_type = data[2]; medium_type = data[2];
dev_specific_param = data[3]; dev_specific_param = data[3];
@ -327,7 +388,8 @@ mode_sense_10_test(void)
CU_ASSERT_EQUAL(medium_type, 0); CU_ASSERT_EQUAL(medium_type, 0);
CU_ASSERT_EQUAL(dev_specific_param, 0); CU_ASSERT_EQUAL(dev_specific_param, 0);
CU_ASSERT_EQUAL(blk_descriptor_len, 8); CU_ASSERT_EQUAL(blk_descriptor_len, 8);
CU_ASSERT_EQUAL(rc, 0);
spdk_put_task(&task);
} }
/* /*
@ -343,9 +405,10 @@ inquiry_evpd_test(void)
struct spdk_scsi_lun lun; struct spdk_scsi_lun lun;
struct spdk_scsi_dev dev; struct spdk_scsi_dev dev;
char cdb[6]; char cdb[6];
char data[4096];
int rc; int rc;
spdk_init_task(&task);
cdb[0] = 0x12; cdb[0] = 0x12;
cdb[1] = 0x00; // EVPD = 0 cdb[1] = 0x00; // EVPD = 0
cdb[2] = 0xff; // PageCode non-zero cdb[2] = 0xff; // PageCode non-zero
@ -358,16 +421,15 @@ inquiry_evpd_test(void)
lun.dev = &dev; lun.dev = &dev;
task.lun = &lun; task.lun = &lun;
memset(data, 0, 4096);
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task); rc = spdk_bdev_scsi_execute(&bdev, &task);
SPDK_CU_ASSERT_FATAL(rc == 0);
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION); CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ILLEGAL_REQUEST); CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
CU_ASSERT_EQUAL(task.sense_data[12], 0x24); CU_ASSERT_EQUAL(task.sense_data[12], 0x24);
CU_ASSERT_EQUAL(task.sense_data[13], 0x0); CU_ASSERT_EQUAL(task.sense_data[13], 0x0);
CU_ASSERT_EQUAL(rc, 0);
spdk_put_task(&task);
} }
/* /*
@ -383,10 +445,12 @@ inquiry_standard_test(void)
struct spdk_scsi_dev dev; struct spdk_scsi_dev dev;
char cdb[6]; char cdb[6];
/* expects a 4K internal data buffer */ /* expects a 4K internal data buffer */
char data[4096]; char *data;
struct spdk_scsi_cdb_inquiry_data *inq_data; struct spdk_scsi_cdb_inquiry_data *inq_data;
int rc; int rc;
spdk_init_task(&task);
cdb[0] = 0x12; cdb[0] = 0x12;
cdb[1] = 0x00; // EVPD = 0 cdb[1] = 0x00; // EVPD = 0
cdb[2] = 0x00; // PageCode zero - requesting standard inquiry cdb[2] = 0x00; // PageCode zero - requesting standard inquiry
@ -399,15 +463,15 @@ inquiry_standard_test(void)
lun.dev = &dev; lun.dev = &dev;
task.lun = &lun; task.lun = &lun;
memset(data, 0, 4096);
task.iov.iov_base = data;
rc = spdk_bdev_scsi_execute(&bdev, &task); rc = spdk_bdev_scsi_execute(&bdev, &task);
data = task.iovs[0].iov_base;
inq_data = (struct spdk_scsi_cdb_inquiry_data *)&data[0]; inq_data = (struct spdk_scsi_cdb_inquiry_data *)&data[0];
CU_ASSERT_EQUAL(inq_data->version, SPDK_SPC_VERSION_SPC3); CU_ASSERT_EQUAL(inq_data->version, SPDK_SPC_VERSION_SPC3);
CU_ASSERT_EQUAL(rc, 0); CU_ASSERT_EQUAL(rc, 0);
spdk_put_task(&task);
} }
static void static void
@ -418,9 +482,11 @@ _inquiry_overflow_test(uint8_t alloc_len)
struct spdk_scsi_lun lun; struct spdk_scsi_lun lun;
struct spdk_scsi_dev dev; struct spdk_scsi_dev dev;
uint8_t cdb[6]; uint8_t cdb[6];
/* expects a 4K internal data buffer */
char data[256], data_compare[256];
int rc; int rc;
/* expects a 4K internal data buffer */
char data[4096], data_compare[4096];
spdk_init_task(&task);
cdb[0] = 0x12; cdb[0] = 0x12;
cdb[1] = 0x00; // EVPD = 0 cdb[1] = 0x00; // EVPD = 0
@ -436,12 +502,16 @@ _inquiry_overflow_test(uint8_t alloc_len)
memset(data, 0, sizeof(data)); memset(data, 0, sizeof(data));
memset(data_compare, 0, sizeof(data_compare)); memset(data_compare, 0, sizeof(data_compare));
task.iov.iov_base = data;
spdk_scsi_task_set_data(&task, data, sizeof(data));
rc = spdk_bdev_scsi_execute(&bdev, &task); rc = spdk_bdev_scsi_execute(&bdev, &task);
CU_ASSERT_EQUAL(rc, 0); SPDK_CU_ASSERT_FATAL(rc == 0);
CU_ASSERT_EQUAL(memcmp(data + alloc_len, data_compare + alloc_len, sizeof(data) - alloc_len), 0); CU_ASSERT_EQUAL(memcmp(data + alloc_len, data_compare + alloc_len, sizeof(data) - alloc_len), 0);
CU_ASSERT(task.data_transferred <= alloc_len); CU_ASSERT(task.data_transferred <= alloc_len);
spdk_put_task(&task);
} }
static void static void
@ -461,10 +531,12 @@ static void
task_complete_test(void) task_complete_test(void)
{ {
struct spdk_event event; struct spdk_event event;
struct spdk_scsi_task task = {}; struct spdk_scsi_task task;
struct spdk_bdev_io bdev_io = {}; struct spdk_bdev_io bdev_io = {};
struct spdk_scsi_lun lun; struct spdk_scsi_lun lun;
spdk_init_task(&task);
TAILQ_INIT(&lun.tasks); TAILQ_INIT(&lun.tasks);
TAILQ_INSERT_TAIL(&lun.tasks, &task, scsi_link); TAILQ_INSERT_TAIL(&lun.tasks, &task, scsi_link);
task.lun = &lun; task.lun = &lun;
@ -494,6 +566,8 @@ task_complete_test(void)
CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ABORTED_COMMAND); CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ABORTED_COMMAND);
CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE); CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
spdk_put_task(&task);
} }
int int