diff --git a/include/spdk/scsi.h b/include/spdk/scsi.h index 866a1e2fa..3cfa02b11 100644 --- a/include/spdk/scsi.h +++ b/include/spdk/scsi.h @@ -275,14 +275,17 @@ void spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t l * 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. + * + * Allocated buffer is stored in iov field of task object. * * \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); + +int spdk_scsi_task_scatter_data(struct spdk_scsi_task *task, const void *src, size_t len); +void *spdk_scsi_task_gather_data(struct spdk_scsi_task *task, int *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, diff --git a/lib/scsi/lun.c b/lib/scsi/lun.c index 9d5299705..e38d0b547 100644 --- a/lib/scsi/lun.c +++ b/lib/scsi/lun.c @@ -184,7 +184,6 @@ static void complete_task_with_no_lun(struct spdk_scsi_task *task) { uint8_t buffer[36]; - uint8_t *data; uint32_t allocation_len; uint32_t data_len; @@ -194,24 +193,19 @@ complete_task_with_no_lun(struct spdk_scsi_task *task) * must be served with PERIPHERAL QUALIFIER = 0x3 and * PERIPHERAL DEVICE TYPE = 0x1F. */ - allocation_len = from_be16(&task->cdb[3]); data_len = sizeof(buffer); - if (allocation_len > data_len) - allocation_len = data_len; - if (allocation_len) { - memset(buffer, 0, data_len); - /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */ - buffer[0] = 0x03 << 5 | 0x1f; - /* ADDITIONAL LENGTH */ - buffer[4] = data_len - 5; + memset(buffer, 0, data_len); + /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */ + buffer[0] = 0x03 << 5 | 0x1f; + /* ADDITIONAL LENGTH */ + buffer[4] = data_len - 5; - data = spdk_scsi_task_alloc_data(task, allocation_len); - memcpy(data, buffer, allocation_len); + allocation_len = from_be16(&task->cdb[3]); + if (spdk_scsi_task_scatter_data(task, buffer, SPDK_MIN(allocation_len, data_len)) >= 0) { + task->data_transferred = data_len; + task->status = SPDK_SCSI_STATUS_GOOD; } - - task->data_transferred = data_len; - task->status = SPDK_SCSI_STATUS_GOOD; } else { /* LOGICAL UNIT NOT SUPPORTED */ spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, diff --git a/lib/scsi/scsi_bdev.c b/lib/scsi/scsi_bdev.c index 06cfd57a5..39603a96a 100644 --- a/lib/scsi/scsi_bdev.c +++ b/lib/scsi/scsi_bdev.c @@ -1455,9 +1455,17 @@ spdk_bdev_scsi_unmap(struct spdk_bdev *bdev, { uint8_t *data; - uint16_t bdesc_data_len, bdesc_count; + struct spdk_scsi_unmap_bdesc *desc; + uint32_t bdesc_count; + int bdesc_data_len; + int data_len; - data = (uint8_t *)task->iovs[0].iov_base; + if (task->iovcnt == 1) { + data = (uint8_t *)task->iovs[0].iov_base; + data_len = task->iovs[0].iov_len; + } else { + data = spdk_scsi_task_gather_data(task, &data_len); + } /* * The UNMAP BLOCK DESCRIPTOR DATA LENGTH field specifies the length in @@ -1469,6 +1477,15 @@ spdk_bdev_scsi_unmap(struct spdk_bdev *bdev, */ bdesc_data_len = from_be16(&data[2]); bdesc_count = bdesc_data_len / 16; + assert(bdesc_data_len <= data_len); + + if (task->iovcnt == 1) { + desc = (struct spdk_scsi_unmap_bdesc *)&data[8]; + } else { + desc = spdk_scsi_task_alloc_data(task, bdesc_data_len - 8); + memcpy(desc, &data[8], bdesc_data_len - 8); + spdk_free(data); + } if (bdesc_count > bdev->max_unmap_bdesc_count) { SPDK_ERRLOG("Error - supported unmap block descriptor count limit" @@ -1478,9 +1495,17 @@ spdk_bdev_scsi_unmap(struct spdk_bdev *bdev, SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); return SPDK_SCSI_TASK_COMPLETE; + } else if (bdesc_data_len > data_len) { + SPDK_ERRLOG("Error - bdesc_data_len (%d) > data_len (%d)", + bdesc_data_len, data_len); + spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, + SPDK_SCSI_SENSE_ILLEGAL_REQUEST, + SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB, + SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); + return SPDK_SCSI_TASK_COMPLETE; } - task->blockdev_io = spdk_bdev_unmap(bdev, task->ch, (struct spdk_scsi_unmap_bdesc *)&data[8], + task->blockdev_io = spdk_bdev_unmap(bdev, task->ch, desc, bdesc_count, spdk_bdev_scsi_task_complete, task); @@ -1504,7 +1529,6 @@ spdk_bdev_scsi_process_block(struct spdk_bdev *bdev, uint32_t xfer_len; uint32_t len = 0; uint8_t *cdb = task->cdb; - uint8_t *data; /* XXX: We need to support FUA bit for writes! */ switch (cdb[0]) { @@ -1547,13 +1571,11 @@ spdk_bdev_scsi_process_block(struct spdk_bdev *bdev, } to_be32(&buffer[4], bdev->blocklen); - len = task->length < 8 ? task->length : sizeof(buffer); - if (len) { - data = spdk_scsi_task_alloc_data(task, len); - memcpy(data, buffer, len); - } + len = SPDK_MIN(task->length, sizeof(buffer)); + if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) + break; - task->data_transferred = 8; + task->data_transferred = len; task->status = SPDK_SCSI_STATUS_GOOD; break; } @@ -1574,12 +1596,9 @@ spdk_bdev_scsi_process_block(struct spdk_bdev *bdev, buffer[14] |= 1 << 7; } - len = from_be32(&cdb[10]); - if (len) { - len = len < sizeof(buffer) ? len : sizeof(buffer); - data = spdk_scsi_task_alloc_data(task, len); - memcpy(data, buffer, len); - } + len = SPDK_MIN(from_be32(&cdb[10]), sizeof(buffer)); + if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) + break; task->data_transferred = len; task->status = SPDK_SCSI_STATUS_GOOD; @@ -1618,38 +1637,48 @@ spdk_bdev_scsi_process_block(struct spdk_bdev *bdev, return SPDK_SCSI_TASK_COMPLETE; } +static int +spdk_bdev_scsi_check_len(struct spdk_scsi_task *task, int len, int min_len) +{ + if (len >= min_len) + return 0; + + /* INVALID FIELD IN CDB */ + spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, + SPDK_SCSI_SENSE_ILLEGAL_REQUEST, + SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB, + SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); + return -1; +} + static int spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, struct spdk_scsi_task *task) { - int alloc_len; - int data_len; + int alloc_len = -1; + int data_len = -1; uint8_t *cdb = task->cdb; - uint8_t *data; + uint8_t *data = NULL; + int rc = 0; int pllen, md = 0; int pf, sp; int bdlen, llba; int dbd, pc, page, subpage; int cmd_parsed = 0; + switch (cdb[0]) { case SPDK_SPC_INQUIRY: alloc_len = from_be16(&cdb[3]); - if (alloc_len) { - data = spdk_scsi_task_alloc_data(task, alloc_len); - } else { - data = NULL; - } - - data_len = spdk_bdev_scsi_inquiry(bdev, task, cdb, - data, alloc_len); - if (data_len < 0) { + data_len = SPDK_MAX(4096, alloc_len); + data = spdk_zmalloc(data_len, 0, NULL); + rc = spdk_bdev_scsi_inquiry(bdev, task, cdb, data, data_len); + data_len = SPDK_MIN(rc, data_len); + if (rc < 0) { break; } SPDK_TRACEDUMP(SPDK_TRACE_DEBUG, "INQUIRY", data, data_len); - task->data_transferred = (uint64_t)data_len; - task->status = SPDK_SCSI_STATUS_GOOD; break; case SPDK_SPC_REPORT_LUNS: { @@ -1659,18 +1688,16 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, SPDK_TRACELOG(SPDK_TRACE_DEBUG, "sel=%x\n", sel); alloc_len = from_be32(&cdb[6]); - if (alloc_len < 16) { - /* INVALID FIELD IN CDB */ - spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, - SPDK_SCSI_SENSE_ILLEGAL_REQUEST, - SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB, - SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); + rc = spdk_bdev_scsi_check_len(task, alloc_len, 16); + if (rc < 0) { break; } - 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) { + data_len = SPDK_MAX(4096, alloc_len); + data = spdk_zmalloc(data_len, 0, NULL); + rc = spdk_bdev_scsi_report_luns(task->lun, sel, data, data_len); + data_len = rc; + if (rc < 0) { spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, SPDK_SCSI_SENSE_NO_SENSE, SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE, @@ -1679,61 +1706,62 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, } SPDK_TRACEDUMP(SPDK_TRACE_DEBUG, "REPORT LUNS", data, data_len); - task->data_transferred = (uint64_t)data_len; - task->status = SPDK_SCSI_STATUS_GOOD; break; } case SPDK_SPC_MODE_SELECT_6: case SPDK_SPC_MODE_SELECT_10: - data = task->iovs[0].iov_base; - if (cdb[0] == SPDK_SPC_MODE_SELECT_6) { + /* MODE_SELECT(6) must have at least a 4 byte header. */ md = 4; pllen = cdb[4]; } else { + /* MODE_SELECT(10) must have at least an 8 byte header. */ md = 8; pllen = from_be16(&cdb[7]); } if (pllen == 0) { - task->data_transferred = 0; - task->status = SPDK_SCSI_STATUS_GOOD; - break; - } else if (cdb[0] == SPDK_SPC_MODE_SELECT_6 && pllen < 4) { - /* MODE_SELECT(6) must have at least a 4 byte header. */ - /* INVALID FIELD IN CDB */ - spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, - SPDK_SCSI_SENSE_ILLEGAL_REQUEST, - SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB, - SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); - break; - } else if (cdb[0] == SPDK_SPC_MODE_SELECT_10 && pllen < 8) { - /* MODE_SELECT(10) must have at least an 8 byte header. */ - /* INVALID FIELD IN CDB */ - spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, - SPDK_SCSI_SENSE_ILLEGAL_REQUEST, - SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB, - SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); break; } + rc = spdk_bdev_scsi_check_len(task, pllen, md); + if (rc < 0) { + break; + } + + data = spdk_scsi_task_gather_data(task, &rc); + if (rc < 0) { + break; + } + + data_len = rc; if (cdb[0] == SPDK_SPC_MODE_SELECT_6) { - bdlen = data[3]; + rc = spdk_bdev_scsi_check_len(task, data_len, 4); + if (rc >= 0) { + bdlen = data[3]; + } + } else { - bdlen = from_be16(&data[6]); + rc = spdk_bdev_scsi_check_len(task, data_len, 8); + if (rc >= 0) { + bdlen = from_be16(&data[6]); + } } + if (rc < 0) { + break; + } pf = !!(cdb[1] & 0x10); sp = !!(cdb[1] & 0x1); /* page data */ - data_len = spdk_bdev_scsi_mode_select_page( - bdev, cdb, - pf, sp, - &data[md + bdlen], - pllen - (md + bdlen)); - if (data_len != 0) { + rc = spdk_bdev_scsi_mode_select_page( + bdev, cdb, + pf, sp, + &data[md + bdlen], + pllen - (md + bdlen)); + if (rc < 0) { spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, SPDK_SCSI_SENSE_NO_SENSE, SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE, @@ -1741,8 +1769,8 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, break; } - task->data_transferred = pllen; - task->status = SPDK_SCSI_STATUS_GOOD; + rc = pllen; + data_len = 0; break; case SPDK_SPC_MODE_SENSE_6: @@ -1764,11 +1792,23 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, subpage = cdb[3]; /* First call with no buffer to discover needed buffer size */ - data_len = spdk_bdev_scsi_mode_sense(bdev, md, - cdb, dbd, llba, pc, - page, subpage, - NULL); - if (data_len < 0) { + rc = spdk_bdev_scsi_mode_sense(bdev, md, + cdb, dbd, llba, pc, + page, subpage, + NULL); + if (rc < 0) { + break; + } + + data_len = rc; + data = spdk_zmalloc(data_len, 0, NULL); + + /* First call with no buffer to discover needed buffer size */ + rc = spdk_bdev_scsi_mode_sense(bdev, md, + cdb, dbd, llba, pc, + page, subpage, + data); + if (rc < 0) { /* INVALID FIELD IN CDB */ spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, SPDK_SCSI_SENSE_ILLEGAL_REQUEST, @@ -1776,29 +1816,6 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); break; } - - if (alloc_len > data_len) - alloc_len = data_len; - - if (alloc_len) { - uint8_t *buffer; - - data = spdk_scsi_task_alloc_data(task, alloc_len); - buffer = alloc_len < data_len ? spdk_zmalloc(data_len, 0, NULL) : data; - - data_len = spdk_bdev_scsi_mode_sense(bdev, md, - cdb, dbd, llba, pc, - page, subpage, - buffer); - assert(data_len >= 0); - if (buffer != data) { - memcpy(data, buffer, alloc_len); - spdk_free(buffer); - } - } - - task->data_transferred = (uint64_t)data_len; - task->status = SPDK_SCSI_STATUS_GOOD; break; case SPDK_SPC_REQUEST_SENSE: { @@ -1816,7 +1833,6 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, } alloc_len = cdb[4]; - data = spdk_scsi_task_alloc_data(task, alloc_len); /* NO ADDITIONAL SENSE INFORMATION */ sk = SPDK_SCSI_SENSE_NO_SENSE; @@ -1826,9 +1842,8 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, spdk_scsi_task_build_sense_data(task, sk, asc, ascq); data_len = task->sense_data_len; + data = spdk_zmalloc(data_len, 0, NULL); memcpy(data, task->sense_data, data_len); - task->data_transferred = (uint64_t)data_len; - task->status = SPDK_SCSI_STATUS_GOOD; break; } @@ -1845,6 +1860,7 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, SPDK_SCSI_SENSE_ILLEGAL_REQUEST, SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); + rc = -1; break; case SPDK_SPC_TEST_UNIT_READY: @@ -1855,14 +1871,27 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev, SPDK_TRACELOG(SPDK_TRACE_SCSI, "START_STOP_UNIT\n"); } - task->data_transferred = 0; - task->status = SPDK_SCSI_STATUS_GOOD; + rc = 0; break; default: return SPDK_SCSI_TASK_UNKNOWN; } + if (rc >= 0 && data_len > 0) { + assert(alloc_len >= 0); + spdk_scsi_task_scatter_data(task, data, SPDK_MIN(alloc_len, data_len)); + rc = SPDK_MIN(data_len, alloc_len); + } + + if (rc >= 0) { + task->data_transferred = rc; + task->status = SPDK_SCSI_STATUS_GOOD; + } + + if (data) + spdk_free(data); + return SPDK_SCSI_TASK_COMPLETE; } diff --git a/lib/scsi/scsi_internal.h b/lib/scsi/scsi_internal.h index 02cd4ff22..43b07e89a 100644 --- a/lib/scsi/scsi_internal.h +++ b/lib/scsi/scsi_internal.h @@ -56,6 +56,25 @@ #include "spdk_internal/log.h" + +/** + * Macro to return the minimum of two numbers + */ +#define SPDK_MIN(a, b) ({ \ + typeof (a) _a = (a); \ + typeof (b) _b = (b); \ + _a < _b ? _a : _b; \ + }) + +/** + * Macro to return the maximum of two numbers + */ +#define SPDK_MAX(a, b) ({ \ + typeof (a) _a = (a); \ + typeof (b) _b = (b); \ + _a > _b ? _a : _b; \ + }) + enum { SPDK_SCSI_TASK_UNKNOWN = -1, SPDK_SCSI_TASK_COMPLETE, diff --git a/lib/scsi/task.c b/lib/scsi/task.c index b6503ff54..f0b946480 100644 --- a/lib/scsi/task.c +++ b/lib/scsi/task.c @@ -122,21 +122,87 @@ spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len) { assert(task->alloc_len == 0); - /* Only one buffer is managable */ - if (task->iovcnt != 1) { + task->iov.iov_base = spdk_zmalloc(alloc_len, 0, NULL); + task->iov.iov_len = alloc_len; + task->alloc_len = alloc_len; + + return task->iov.iov_base; +} + +int +spdk_scsi_task_scatter_data(struct spdk_scsi_task *task, const void *src, size_t buf_len) +{ + size_t len = 0; + size_t buf_left = buf_len; + int i; + struct iovec *iovs = task->iovs; + const uint8_t *pos; + + if (buf_len == 0) + return 0; + + if (task->iovcnt == 1 && iovs[0].iov_base == NULL) { + spdk_scsi_task_alloc_data(task, buf_len); + iovs[0] = task->iov; + } + + for (i = 0; i < task->iovcnt; i++) { + assert(iovs[i].iov_base != NULL); + len += iovs[i].iov_len; + } + + if (len < buf_len) { + spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, + SPDK_SCSI_SENSE_ILLEGAL_REQUEST, + SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB, + SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); + return -1; + } + + pos = src; + + for (i = 0; i < task->iovcnt; i++) { + len = SPDK_MIN(iovs[i].iov_len, buf_left); + buf_left -= len; + memcpy(iovs[i].iov_base, pos, len); + pos += len; + } + + return buf_len; +} + +void * +spdk_scsi_task_gather_data(struct spdk_scsi_task *task, int *len) +{ + int i; + struct iovec *iovs = task->iovs; + size_t buf_len = 0; + uint8_t *buf, *pos; + + for (i = 0; i < task->iovcnt; i++) { + assert(iovs[i].iov_base != NULL); + buf_len += iovs[i].iov_len; + } + + if (buf_len == 0) { + *len = 0; return 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->alloc_len = alloc_len; + buf = spdk_malloc(buf_len, 0, NULL); + if (buf == NULL) { + *len = -1; + return NULL; } - task->iov.iov_len = alloc_len; - assert(&task->iov == task->iovs); + pos = buf; + for (i = 0; i < task->iovcnt; i++) { + memcpy(pos, iovs[i].iov_base, iovs[i].iov_len); + pos += iovs[i].iov_len; + } - return task->iov.iov_base; + *len = buf_len; + return buf; } void diff --git a/test/lib/scsi/lun/lun_ut.c b/test/lib/scsi/lun/lun_ut.c index 27691bf09..688d44186 100644 --- a/test/lib/scsi/lun/lun_ut.c +++ b/test/lib/scsi/lun/lun_ut.c @@ -38,6 +38,7 @@ #include "spdk_cunit.h" +#include "task.c" #include "lun.c" #include "lun_db.c" @@ -55,6 +56,12 @@ void spdk_trace_record(uint16_t tpoint_id, uint16_t poller_id, uint32_t size, { } +static void +spdk_lun_ut_free_task(struct spdk_scsi_task *task) +{ + free(task); +} + static struct spdk_scsi_task * spdk_get_task(uint32_t *owner_task_ctr) { @@ -65,43 +72,41 @@ spdk_get_task(uint32_t *owner_task_ctr) return NULL; } - task->id = g_task_count; - task->iovs = &task->iov; - task->iovcnt = 1; - - g_task_count++; + spdk_scsi_task_construct(task, &g_task_count, NULL); + task->free_fn = spdk_lun_ut_free_task; return task; } -void -spdk_scsi_task_put(struct spdk_scsi_task *task) +void * +spdk_malloc(size_t size, size_t align, uint64_t *phys_addr) { - g_task_count--; - if (task->alloc_len) { - free(task->iov.iov_base); - } - free(task); -} - -void -spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk, - int asc, int ascq) -{ - task->status = sc; + void *buf = malloc(size); + if (phys_addr) + *phys_addr = (uint64_t)buf; + return buf; } void * -spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len) +spdk_zmalloc(size_t size, size_t align, uint64_t *phys_addr) { - if (alloc_len < 4096) - alloc_len = 4096; + void *buf = calloc(size, 1); + if (phys_addr) + *phys_addr = (uint64_t)buf; + return buf; +} - task->iovs = &task->iov; - task->iov.iov_base = malloc(alloc_len); - task->iov.iov_len = alloc_len; - task->alloc_len = alloc_len; - return task->iov.iov_base; +void +spdk_free(void *buf) +{ + free(buf); +} + +int +spdk_bdev_free_io(struct spdk_bdev_io *bdev_io) +{ + CU_ASSERT(0); + return -1; } void spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev, diff --git a/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c b/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c index 2f3f3a2f6..b0a3c1cde 100644 --- a/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c +++ b/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c @@ -35,6 +35,7 @@ #include #include +#include "task.c" #include "scsi_bdev.c" #include "spdk_cunit.h" @@ -43,12 +44,23 @@ SPDK_LOG_REGISTER_TRACE_FLAG("scsi", SPDK_TRACE_SCSI) struct spdk_scsi_globals g_spdk_scsi; +void * +spdk_malloc(size_t size, size_t align, uint64_t *phys_addr) +{ + void *buf = malloc(size); + if (phys_addr) + *phys_addr = (uint64_t)buf; + + return buf; +} + void * spdk_zmalloc(size_t size, size_t align, uint64_t *phys_addr) { void *buf = calloc(size, 1); if (phys_addr) *phys_addr = (uint64_t)buf; + return buf; } @@ -57,6 +69,14 @@ spdk_free(void *buf) { free(buf); } + +int +spdk_bdev_free_io(struct spdk_bdev_io *bdev_io) +{ + CU_ASSERT(0); + return -1; +} + void spdk_scsi_lun_clear_all(struct spdk_scsi_lun *lun) { @@ -67,19 +87,15 @@ spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *ta { } -void -spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk, - int asc, int ascq) -{ - spdk_scsi_task_build_sense_data(task, sk, asc, ascq); - task->status = sc; -} - - static void spdk_put_task(struct spdk_scsi_task *task) { - spdk_scsi_task_free_data(task); + if (task->alloc_len) + free(task->iov.iov_base); + + task->iov.iov_base = NULL; + task->iov.iov_len = 0; + task->alloc_len = 0; } @@ -92,88 +108,6 @@ spdk_init_task(struct spdk_scsi_task *task) task->iovcnt = 1; } -void -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 (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 -spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc, int ascq) -{ - uint8_t *cp; - int resp_code; - - resp_code = 0x70; /* Current + Fixed format */ - - /* Sense Data */ - cp = task->sense_data; - - /* VALID(7) RESPONSE CODE(6-0) */ - cp[0] = 0x80 | resp_code; - /* Obsolete */ - cp[1] = 0; - /* FILEMARK(7) EOM(6) ILI(5) SENSE KEY(3-0) */ - cp[2] = sk & 0xf; - /* INFORMATION */ - memset(&cp[3], 0, 4); - - /* ADDITIONAL SENSE LENGTH */ - cp[7] = 10; - - /* COMMAND-SPECIFIC INFORMATION */ - memset(&cp[8], 0, 4); - /* ADDITIONAL SENSE CODE */ - cp[12] = asc; - /* ADDITIONAL SENSE CODE QUALIFIER */ - cp[13] = ascq; - /* FIELD REPLACEABLE UNIT CODE */ - cp[14] = 0; - - /* SKSV(7) SENSE KEY SPECIFIC(6-0,7-0,7-0) */ - cp[15] = 0; - cp[16] = 0; - cp[17] = 0; - - /* SenseLength */ - task->sense_data_len = 18; -} - void spdk_scsi_nvme_translate(struct spdk_bdev_io *bdev_io, int *sc, int *sk, int *asc, int *ascq)