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:
parent
51c6917fad
commit
f30f0c76f1
@ -63,10 +63,6 @@
|
||||
|
||||
#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,
|
||||
@ -125,7 +121,6 @@ struct spdk_scsi_task {
|
||||
* transfer_len - i.e. SCSI INQUIRY.
|
||||
*/
|
||||
uint32_t data_transferred;
|
||||
uint32_t alloc_len;
|
||||
|
||||
uint64_t offset;
|
||||
struct spdk_scsi_task *parent;
|
||||
@ -134,10 +129,18 @@ struct spdk_scsi_task {
|
||||
|
||||
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 *iovs;
|
||||
uint16_t iovcnt;
|
||||
uint8_t iov_flags;
|
||||
|
||||
uint8_t sense_data[32];
|
||||
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,
|
||||
struct spdk_scsi_task *parent);
|
||||
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,
|
||||
int ascq);
|
||||
void spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk, int asc,
|
||||
|
@ -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.iov.iov_base + offset;
|
||||
rsp_pdu->data = task->scsi.iovs[0].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.iov.iov_base = NULL;
|
||||
spdk_scsi_task_set_data(&subtask->scsi, NULL, 0);
|
||||
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.iov.iov_base = NULL;
|
||||
spdk_scsi_task_set_data(&task->scsi, NULL, 0);
|
||||
|
||||
remaining_size = task->scsi.transfer_len - task->scsi.length;
|
||||
task->current_datain_offset = 0;
|
||||
@ -2985,16 +2985,14 @@ spdk_iscsi_op_scsi(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
||||
else {
|
||||
/* we are doing the first partial write task */
|
||||
task->scsi.ref++;
|
||||
task->scsi.iov.iov_base = pdu->data;
|
||||
task->scsi.iov.iov_len = pdu->data_segment_len;
|
||||
spdk_scsi_task_set_data(&task->scsi, pdu->data, pdu->data_segment_len);
|
||||
task->scsi.length = pdu->data_segment_len;
|
||||
}
|
||||
}
|
||||
|
||||
if (pdu->data_segment_len == transfer_len) {
|
||||
/* we are doing small writes with no R2T */
|
||||
task->scsi.iov.iov_len = transfer_len;
|
||||
task->scsi.iov.iov_base = pdu->data;
|
||||
spdk_scsi_task_set_data(&task->scsi, pdu->data, transfer_len);
|
||||
task->scsi.length = transfer_len;
|
||||
}
|
||||
} else {
|
||||
@ -4083,8 +4081,7 @@ static int spdk_iscsi_op_data(struct spdk_iscsi_conn *conn,
|
||||
}
|
||||
subtask->scsi.offset = buffer_offset;
|
||||
subtask->scsi.length = pdu->data_segment_len;
|
||||
subtask->scsi.iov.iov_base = pdu->data;
|
||||
subtask->scsi.iov.iov_len = pdu->data_segment_len;
|
||||
spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_segment_len);
|
||||
spdk_iscsi_task_associate_pdu(subtask, pdu);
|
||||
|
||||
if (task->next_expected_r2t_offset == transfer_len) {
|
||||
|
@ -194,7 +194,7 @@ complete_task_with_no_lun(struct spdk_scsi_task *task)
|
||||
* PERIPHERAL DEVICE TYPE = 0x1F.
|
||||
*/
|
||||
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;
|
||||
memset(data, 0, data_len);
|
||||
/* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
|
||||
|
@ -1317,8 +1317,9 @@ 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->iov.iov_base = bdev_io->u.read.iovs[0].iov_base;
|
||||
if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ && task->iovs != bdev_io->u.read.iovs) {
|
||||
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);
|
||||
@ -1510,7 +1511,7 @@ spdk_bdev_scsi_unmap(struct spdk_bdev *bdev,
|
||||
uint8_t *data;
|
||||
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
|
||||
@ -1591,7 +1592,7 @@ spdk_bdev_scsi_process_block(struct spdk_bdev *bdev,
|
||||
return spdk_bdev_scsi_readwrite(bdev, task, lba, xfer_len);
|
||||
|
||||
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) {
|
||||
memset(data, 0xff, 4);
|
||||
} else {
|
||||
@ -1605,7 +1606,7 @@ spdk_bdev_scsi_process_block(struct spdk_bdev *bdev,
|
||||
case SPDK_SPC_SERVICE_ACTION_IN_16:
|
||||
switch (cdb[1] & 0x1f) { /* SERVICE ACTION */
|
||||
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_be32(&data[8], bdev->blocklen);
|
||||
/*
|
||||
@ -1669,7 +1670,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
switch (cdb[0]) {
|
||||
case SPDK_SPC_INQUIRY:
|
||||
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, alloc_len);
|
||||
if (data_len < 0) {
|
||||
@ -1697,7 +1698,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
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);
|
||||
if (data_len < 0) {
|
||||
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_10:
|
||||
data = task->iov.iov_base;
|
||||
data = task->iovs[0].iov_base;
|
||||
|
||||
if (cdb[0] == SPDK_SPC_MODE_SELECT_6) {
|
||||
md = 4;
|
||||
@ -1792,7 +1793,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
page = cdb[2] & 0x3f;
|
||||
subpage = cdb[3];
|
||||
|
||||
spdk_scsi_task_alloc_data(task, alloc_len, &data);
|
||||
data = spdk_scsi_task_alloc_data(task, alloc_len);
|
||||
|
||||
if (md == 6) {
|
||||
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];
|
||||
spdk_scsi_task_alloc_data(task, alloc_len, &data);
|
||||
data = spdk_scsi_task_alloc_data(task, alloc_len);
|
||||
|
||||
/* NO ADDITIONAL SENSE INFORMATION */
|
||||
sk = SPDK_SCSI_SENSE_NO_SENSE;
|
||||
|
@ -59,11 +59,11 @@ spdk_scsi_task_put(struct spdk_scsi_task *task)
|
||||
bdev_io->status = SPDK_BDEV_IO_STATUS_FAILED;
|
||||
}
|
||||
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);
|
||||
|
||||
if (*(task->owner_task_ctr) > 0) {
|
||||
*(task->owner_task_ctr) -= 1;
|
||||
} 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
|
||||
*/
|
||||
assert(task->iov.iov_base == NULL);
|
||||
task->iovs = &task->iov;
|
||||
task->iovcnt = 1;
|
||||
|
||||
@ -105,8 +106,19 @@ spdk_scsi_task_construct(struct spdk_scsi_task *task, uint32_t *owner_task_ctr,
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
|
||||
uint8_t **data)
|
||||
spdk_scsi_task_free_data(struct spdk_scsi_task *task)
|
||||
{
|
||||
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
|
||||
@ -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
|
||||
* allocation length.
|
||||
*/
|
||||
assert(task->alloc_len == 0);
|
||||
|
||||
/* Only one buffer is managable */
|
||||
if (task->iovcnt != 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (alloc_len < 4096) {
|
||||
alloc_len = 4096;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
task->alloc_len = alloc_len;
|
||||
}
|
||||
task->alloc_len = alloc_len;
|
||||
*data = task->iov.iov_base;
|
||||
memset(task->iov.iov_base, 0, task->alloc_len);
|
||||
|
||||
task->iov.iov_len = 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
|
||||
|
@ -66,6 +66,8 @@ spdk_get_task(uint32_t *owner_task_ctr)
|
||||
}
|
||||
|
||||
task->id = g_task_count;
|
||||
task->iovs = &task->iov;
|
||||
task->iovcnt = 1;
|
||||
|
||||
g_task_count++;
|
||||
|
||||
@ -76,7 +78,7 @@ void
|
||||
spdk_scsi_task_put(struct spdk_scsi_task *task)
|
||||
{
|
||||
g_task_count--;
|
||||
if (task->iov_flags & SPDK_SCSI_TASK_ALLOC_BUFFER) {
|
||||
if (task->alloc_len) {
|
||||
free(task->iov.iov_base);
|
||||
}
|
||||
free(task);
|
||||
@ -89,15 +91,17 @@ spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
|
||||
task->status = sc;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
|
||||
uint8_t **data)
|
||||
void *
|
||||
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
|
||||
{
|
||||
if (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;
|
||||
*data = task->iov.iov_base;
|
||||
return task->iov.iov_base;
|
||||
}
|
||||
|
||||
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 */
|
||||
task->cdb[3] = 0xFF;
|
||||
task->cdb[4] = 0xFF;
|
||||
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 +448,6 @@ 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->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);
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
#include "scsi_bdev.c"
|
||||
|
||||
#include "CUnit/Basic.h"
|
||||
#include "spdk_cunit.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
|
||||
uint8_t **data)
|
||||
spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
|
||||
{
|
||||
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) {
|
||||
alloc_len = 4096;
|
||||
}
|
||||
|
||||
task->alloc_len = alloc_len;
|
||||
*data = task->iov.iov_base;
|
||||
if (task->iov.iov_base != NULL) {
|
||||
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
|
||||
@ -184,6 +234,8 @@ mode_select_6_test(void)
|
||||
char data[24];
|
||||
int rc;
|
||||
|
||||
spdk_init_task(&task);
|
||||
|
||||
cdb[0] = 0x15;
|
||||
cdb[1] = 0x11;
|
||||
cdb[2] = 0x00;
|
||||
@ -199,11 +251,13 @@ mode_select_6_test(void)
|
||||
memset(data, 0, sizeof(data));
|
||||
data[4] = 0x08;
|
||||
data[5] = 0x02;
|
||||
task.iov.iov_base = data;
|
||||
spdk_scsi_task_set_data(&task, data, sizeof(data));
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
spdk_put_task(&task);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -220,6 +274,8 @@ mode_select_6_test2(void)
|
||||
char cdb[16];
|
||||
int rc;
|
||||
|
||||
spdk_init_task(&task);
|
||||
|
||||
cdb[0] = 0x15;
|
||||
cdb[1] = 0x00;
|
||||
cdb[2] = 0x00;
|
||||
@ -232,11 +288,11 @@ mode_select_6_test2(void)
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
task.iov.iov_base = NULL;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
|
||||
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_dev dev;
|
||||
char cdb[12];
|
||||
unsigned char data[4096];
|
||||
int rc = 0;
|
||||
unsigned char *data;
|
||||
int rc;
|
||||
unsigned char mode_data_len = 0;
|
||||
unsigned char medium_type = 0;
|
||||
unsigned char dev_specific_param = 0;
|
||||
unsigned char blk_descriptor_len = 0;
|
||||
|
||||
memset(&bdev, 0 , sizeof(struct spdk_bdev));
|
||||
spdk_init_task(&task);
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
|
||||
cdb[0] = 0x1A;
|
||||
@ -270,9 +327,10 @@ mode_sense_6_test(void)
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
task.iov.iov_base = data;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
SPDK_CU_ASSERT_FATAL(rc == 0);
|
||||
|
||||
data = task.iovs[0].iov_base;
|
||||
mode_data_len = data[0];
|
||||
medium_type = data[1];
|
||||
dev_specific_param = data[2];
|
||||
@ -282,7 +340,8 @@ mode_sense_6_test(void)
|
||||
CU_ASSERT_EQUAL(medium_type, 0);
|
||||
CU_ASSERT_EQUAL(dev_specific_param, 0);
|
||||
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_dev dev;
|
||||
char cdb[12];
|
||||
unsigned char data[4096];
|
||||
unsigned char *data;
|
||||
int rc;
|
||||
unsigned short mode_data_len = 0;
|
||||
unsigned char medium_type = 0;
|
||||
@ -305,6 +364,7 @@ mode_sense_10_test(void)
|
||||
unsigned short blk_descriptor_len = 0;
|
||||
|
||||
memset(&bdev, 0 , sizeof(struct spdk_bdev));
|
||||
spdk_init_task(&task);
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = 0x5A;
|
||||
cdb[2] = 0x3F;
|
||||
@ -315,9 +375,10 @@ mode_sense_10_test(void)
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
task.iov.iov_base = data;
|
||||
|
||||
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]);
|
||||
medium_type = data[2];
|
||||
dev_specific_param = data[3];
|
||||
@ -327,7 +388,8 @@ mode_sense_10_test(void)
|
||||
CU_ASSERT_EQUAL(medium_type, 0);
|
||||
CU_ASSERT_EQUAL(dev_specific_param, 0);
|
||||
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_dev dev;
|
||||
char cdb[6];
|
||||
char data[4096];
|
||||
int rc;
|
||||
|
||||
spdk_init_task(&task);
|
||||
|
||||
cdb[0] = 0x12;
|
||||
cdb[1] = 0x00; // EVPD = 0
|
||||
cdb[2] = 0xff; // PageCode non-zero
|
||||
@ -358,16 +421,15 @@ inquiry_evpd_test(void)
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
memset(data, 0, 4096);
|
||||
task.iov.iov_base = data;
|
||||
|
||||
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.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
|
||||
CU_ASSERT_EQUAL(task.sense_data[12], 0x24);
|
||||
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;
|
||||
char cdb[6];
|
||||
/* expects a 4K internal data buffer */
|
||||
char data[4096];
|
||||
char *data;
|
||||
struct spdk_scsi_cdb_inquiry_data *inq_data;
|
||||
int rc;
|
||||
|
||||
spdk_init_task(&task);
|
||||
|
||||
cdb[0] = 0x12;
|
||||
cdb[1] = 0x00; // EVPD = 0
|
||||
cdb[2] = 0x00; // PageCode zero - requesting standard inquiry
|
||||
@ -399,15 +463,15 @@ inquiry_standard_test(void)
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
memset(data, 0, 4096);
|
||||
task.iov.iov_base = data;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
|
||||
data = task.iovs[0].iov_base;
|
||||
inq_data = (struct spdk_scsi_cdb_inquiry_data *)&data[0];
|
||||
|
||||
CU_ASSERT_EQUAL(inq_data->version, SPDK_SPC_VERSION_SPC3);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
spdk_put_task(&task);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -418,9 +482,11 @@ _inquiry_overflow_test(uint8_t alloc_len)
|
||||
struct spdk_scsi_lun lun;
|
||||
struct spdk_scsi_dev dev;
|
||||
uint8_t cdb[6];
|
||||
/* expects a 4K internal data buffer */
|
||||
char data[256], data_compare[256];
|
||||
int rc;
|
||||
/* expects a 4K internal data buffer */
|
||||
char data[4096], data_compare[4096];
|
||||
|
||||
spdk_init_task(&task);
|
||||
|
||||
cdb[0] = 0x12;
|
||||
cdb[1] = 0x00; // EVPD = 0
|
||||
@ -436,12 +502,16 @@ _inquiry_overflow_test(uint8_t alloc_len)
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
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);
|
||||
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(task.data_transferred <= alloc_len);
|
||||
|
||||
spdk_put_task(&task);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -461,10 +531,12 @@ static void
|
||||
task_complete_test(void)
|
||||
{
|
||||
struct spdk_event event;
|
||||
struct spdk_scsi_task task = {};
|
||||
struct spdk_scsi_task task;
|
||||
struct spdk_bdev_io bdev_io = {};
|
||||
struct spdk_scsi_lun lun;
|
||||
|
||||
spdk_init_task(&task);
|
||||
|
||||
TAILQ_INIT(&lun.tasks);
|
||||
TAILQ_INSERT_TAIL(&lun.tasks, &task, scsi_link);
|
||||
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[12], SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
|
||||
CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
|
||||
spdk_put_task(&task);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user