2016-07-27 16:32:00 +00:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
|
|
|
*
|
|
|
|
* Copyright (c) Intel Corporation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2017-05-02 18:18:25 +00:00
|
|
|
#include "spdk/stdinc.h"
|
2016-07-27 16:32:00 +00:00
|
|
|
|
2018-02-13 16:09:42 +00:00
|
|
|
#include "scsi/task.c"
|
|
|
|
#include "scsi/scsi_bdev.c"
|
2018-11-12 13:58:15 +00:00
|
|
|
#include "common/lib/test_env.c"
|
2016-07-27 16:32:00 +00:00
|
|
|
|
2016-11-04 18:45:54 +00:00
|
|
|
#include "spdk_cunit.h"
|
2016-07-27 16:32:00 +00:00
|
|
|
|
2018-12-10 00:10:56 +00:00
|
|
|
#include "spdk_internal/mock.h"
|
|
|
|
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_LOG_REGISTER_COMPONENT("scsi", SPDK_LOG_SCSI)
|
2016-07-27 16:32:00 +00:00
|
|
|
|
|
|
|
struct spdk_scsi_globals g_spdk_scsi;
|
|
|
|
|
2017-05-12 18:13:54 +00:00
|
|
|
static uint64_t g_test_bdev_num_blocks;
|
|
|
|
|
2018-07-03 13:21:56 +00:00
|
|
|
TAILQ_HEAD(, spdk_bdev_io) g_bdev_io_queue;
|
|
|
|
int g_scsi_cb_called = 0;
|
|
|
|
|
2018-07-05 07:32:48 +00:00
|
|
|
TAILQ_HEAD(, spdk_bdev_io_wait_entry) g_io_wait_queue;
|
|
|
|
bool g_bdev_io_pool_full = false;
|
|
|
|
|
2017-05-05 22:57:06 +00:00
|
|
|
bool
|
|
|
|
spdk_bdev_io_type_supported(struct spdk_bdev *bdev, enum spdk_bdev_io_type io_type)
|
|
|
|
{
|
|
|
|
abort();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-31 16:28:45 +00:00
|
|
|
void
|
2016-11-14 19:14:12 +00:00
|
|
|
spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
|
2016-07-27 16:32:00 +00:00
|
|
|
{
|
2016-11-14 19:14:12 +00:00
|
|
|
CU_ASSERT(0);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 00:10:56 +00:00
|
|
|
DEFINE_STUB(spdk_bdev_get_name, const char *,
|
|
|
|
(const struct spdk_bdev *bdev), "test");
|
2017-05-10 20:29:31 +00:00
|
|
|
|
2018-12-10 00:10:56 +00:00
|
|
|
DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
|
|
|
|
(const struct spdk_bdev *bdev), 512);
|
2017-05-12 17:29:00 +00:00
|
|
|
|
2019-02-26 06:53:10 +00:00
|
|
|
DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
|
|
|
|
(const struct spdk_bdev *bdev), 8);
|
|
|
|
|
|
|
|
DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
|
|
|
|
(const struct spdk_bdev *bdev), false);
|
|
|
|
|
2019-03-01 07:01:56 +00:00
|
|
|
DEFINE_STUB(spdk_bdev_get_data_block_size, uint32_t,
|
|
|
|
(const struct spdk_bdev *bdev), 512);
|
|
|
|
|
2017-05-12 17:29:00 +00:00
|
|
|
uint64_t
|
|
|
|
spdk_bdev_get_num_blocks(const struct spdk_bdev *bdev)
|
|
|
|
{
|
2017-05-12 18:13:54 +00:00
|
|
|
return g_test_bdev_num_blocks;
|
2017-05-12 17:29:00 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 00:10:56 +00:00
|
|
|
DEFINE_STUB(spdk_bdev_get_product_name, const char *,
|
|
|
|
(const struct spdk_bdev *bdev), "test product");
|
2017-05-10 20:29:31 +00:00
|
|
|
|
2018-12-10 00:10:56 +00:00
|
|
|
DEFINE_STUB(spdk_bdev_has_write_cache, bool,
|
|
|
|
(const struct spdk_bdev *bdev), false);
|
2017-05-16 19:57:33 +00:00
|
|
|
|
2019-02-26 06:53:10 +00:00
|
|
|
DEFINE_STUB(spdk_bdev_get_dif_type, enum spdk_dif_type,
|
|
|
|
(const struct spdk_bdev *bdev), SPDK_DIF_DISABLE);
|
|
|
|
|
|
|
|
DEFINE_STUB(spdk_bdev_is_dif_head_of_md, bool,
|
|
|
|
(const struct spdk_bdev *bdev), false);
|
|
|
|
|
|
|
|
DEFINE_STUB(spdk_bdev_is_dif_check_enabled, bool,
|
|
|
|
(const struct spdk_bdev *bdev, enum spdk_dif_check_type check_type), false);
|
|
|
|
|
2016-07-27 16:32:00 +00:00
|
|
|
void
|
2016-11-14 19:14:12 +00:00
|
|
|
spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
2016-07-27 16:32:00 +00:00
|
|
|
{
|
2018-07-03 13:21:56 +00:00
|
|
|
g_scsi_cb_called++;
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
2018-12-10 00:10:56 +00:00
|
|
|
DEFINE_STUB_V(spdk_scsi_lun_complete_reset_task,
|
|
|
|
(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task));
|
2017-05-13 00:31:46 +00:00
|
|
|
|
2016-11-04 18:45:54 +00:00
|
|
|
static void
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(struct spdk_scsi_task *task)
|
2016-11-04 18:45:54 +00:00
|
|
|
{
|
2017-12-07 23:23:48 +00:00
|
|
|
if (task->alloc_len) {
|
2016-11-14 19:14:12 +00:00
|
|
|
free(task->iov.iov_base);
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2016-11-14 19:14:12 +00:00
|
|
|
|
|
|
|
task->iov.iov_base = NULL;
|
|
|
|
task->iov.iov_len = 0;
|
|
|
|
task->alloc_len = 0;
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
|
2016-11-04 18:45:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(struct spdk_scsi_task *task)
|
2016-11-04 18:45:54 +00:00
|
|
|
{
|
2018-07-03 09:05:28 +00:00
|
|
|
memset(task, 0xFF, sizeof(*task));
|
|
|
|
task->iov.iov_base = NULL;
|
2016-11-04 18:45:54 +00:00
|
|
|
task->iovs = &task->iov;
|
|
|
|
task->iovcnt = 1;
|
2018-07-03 09:05:28 +00:00
|
|
|
task->alloc_len = 0;
|
|
|
|
task->dxfer_dir = SPDK_SCSI_DIR_NONE;
|
2016-11-04 18:45:54 +00:00
|
|
|
}
|
|
|
|
|
2016-10-28 19:56:36 +00:00
|
|
|
void
|
2017-01-18 22:15:35 +00:00
|
|
|
spdk_bdev_io_get_scsi_status(const struct spdk_bdev_io *bdev_io,
|
|
|
|
int *sc, int *sk, int *asc, int *ascq)
|
2016-10-28 19:56:36 +00:00
|
|
|
{
|
2018-06-19 23:19:49 +00:00
|
|
|
switch (bdev_io->internal.status) {
|
2017-01-18 22:15:35 +00:00
|
|
|
case SPDK_BDEV_IO_STATUS_SUCCESS:
|
|
|
|
*sc = SPDK_SCSI_STATUS_GOOD;
|
|
|
|
*sk = SPDK_SCSI_SENSE_NO_SENSE;
|
|
|
|
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
|
|
|
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
|
|
|
break;
|
|
|
|
case SPDK_BDEV_IO_STATUS_SCSI_ERROR:
|
2018-06-20 23:38:35 +00:00
|
|
|
*sc = bdev_io->internal.error.scsi.sc;
|
|
|
|
*sk = bdev_io->internal.error.scsi.sk;
|
|
|
|
*asc = bdev_io->internal.error.scsi.asc;
|
|
|
|
*ascq = bdev_io->internal.error.scsi.ascq;
|
2017-01-18 22:15:35 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
|
|
|
*sk = SPDK_SCSI_SENSE_ABORTED_COMMAND;
|
|
|
|
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
|
|
|
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
|
|
|
break;
|
|
|
|
}
|
2016-10-28 19:56:36 +00:00
|
|
|
}
|
|
|
|
|
2017-05-04 20:57:07 +00:00
|
|
|
void
|
|
|
|
spdk_bdev_io_get_iovec(struct spdk_bdev_io *bdev_io, struct iovec **iovp, int *iovcntp)
|
|
|
|
{
|
|
|
|
*iovp = NULL;
|
|
|
|
*iovcntp = 0;
|
|
|
|
}
|
|
|
|
|
2018-07-03 13:21:56 +00:00
|
|
|
static void
|
|
|
|
ut_bdev_io_flush(void)
|
|
|
|
{
|
|
|
|
struct spdk_bdev_io *bdev_io;
|
2018-07-05 07:32:48 +00:00
|
|
|
struct spdk_bdev_io_wait_entry *entry;
|
|
|
|
|
|
|
|
while (!TAILQ_EMPTY(&g_bdev_io_queue) || !TAILQ_EMPTY(&g_io_wait_queue)) {
|
|
|
|
while (!TAILQ_EMPTY(&g_bdev_io_queue)) {
|
|
|
|
bdev_io = TAILQ_FIRST(&g_bdev_io_queue);
|
|
|
|
TAILQ_REMOVE(&g_bdev_io_queue, bdev_io, internal.link);
|
|
|
|
bdev_io->internal.cb(bdev_io, true, bdev_io->internal.caller_ctx);
|
|
|
|
free(bdev_io);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!TAILQ_EMPTY(&g_io_wait_queue)) {
|
|
|
|
entry = TAILQ_FIRST(&g_io_wait_queue);
|
|
|
|
TAILQ_REMOVE(&g_io_wait_queue, entry, link);
|
|
|
|
entry->cb_fn(entry->cb_arg);
|
|
|
|
}
|
2018-07-03 13:21:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
_spdk_bdev_io_op(spdk_bdev_io_completion_cb cb, void *cb_arg)
|
|
|
|
{
|
|
|
|
struct spdk_bdev_io *bdev_io;
|
|
|
|
|
2018-07-05 07:32:48 +00:00
|
|
|
if (g_bdev_io_pool_full) {
|
|
|
|
g_bdev_io_pool_full = false;
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2018-07-03 13:21:56 +00:00
|
|
|
bdev_io = calloc(1, sizeof(*bdev_io));
|
|
|
|
SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
|
|
|
|
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
|
|
|
bdev_io->internal.cb = cb;
|
|
|
|
bdev_io->internal.caller_ctx = cb_arg;
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&g_bdev_io_queue, bdev_io, internal.link);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-05 18:39:38 +00:00
|
|
|
int
|
2019-02-15 00:03:59 +00:00
|
|
|
spdk_bdev_readv_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|
|
|
struct iovec *iov, int iovcnt,
|
|
|
|
uint64_t offset_blocks, uint64_t num_blocks,
|
|
|
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
2016-10-21 15:05:19 +00:00
|
|
|
{
|
2018-07-03 13:21:56 +00:00
|
|
|
return _spdk_bdev_io_op(cb, cb_arg);
|
2016-10-21 15:05:19 +00:00
|
|
|
}
|
|
|
|
|
2017-06-05 18:39:38 +00:00
|
|
|
int
|
2019-02-15 01:23:45 +00:00
|
|
|
spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|
|
|
struct iovec *iov, int iovcnt,
|
|
|
|
uint64_t offset_blocks, uint64_t num_blocks,
|
|
|
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
2016-07-27 16:32:00 +00:00
|
|
|
{
|
2018-07-03 13:21:56 +00:00
|
|
|
return _spdk_bdev_io_op(cb, cb_arg);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
2017-06-05 18:39:38 +00:00
|
|
|
int
|
2017-12-28 19:50:59 +00:00
|
|
|
spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|
|
|
uint64_t offset_blocks, uint64_t num_blocks,
|
|
|
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
2016-07-27 16:32:00 +00:00
|
|
|
{
|
2018-07-03 13:21:56 +00:00
|
|
|
return _spdk_bdev_io_op(cb, cb_arg);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-07-06 19:39:19 +00:00
|
|
|
spdk_bdev_reset(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
2016-07-27 16:32:00 +00:00
|
|
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
|
|
|
{
|
2018-07-03 13:21:56 +00:00
|
|
|
return _spdk_bdev_io_op(cb, cb_arg);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
2017-06-05 18:39:38 +00:00
|
|
|
int
|
2017-12-28 19:47:23 +00:00
|
|
|
spdk_bdev_flush_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|
|
|
uint64_t offset_blocks, uint64_t num_blocks,
|
|
|
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
2016-07-27 16:32:00 +00:00
|
|
|
{
|
2018-07-03 13:21:56 +00:00
|
|
|
return _spdk_bdev_io_op(cb, cb_arg);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
2018-07-05 07:32:48 +00:00
|
|
|
int
|
|
|
|
spdk_bdev_queue_io_wait(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
|
|
|
struct spdk_bdev_io_wait_entry *entry)
|
|
|
|
{
|
|
|
|
TAILQ_INSERT_TAIL(&g_io_wait_queue, entry, link);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:53:10 +00:00
|
|
|
int
|
|
|
|
spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
|
|
|
|
bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
|
|
|
|
uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
|
|
|
|
uint16_t guard_seed)
|
|
|
|
{
|
|
|
|
ctx->init_ref_tag = init_ref_tag;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-07-27 16:32:00 +00:00
|
|
|
/*
|
|
|
|
* This test specifically tests a mode select 6 command from the
|
|
|
|
* Windows SCSI compliance test that caused SPDK to crash.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
mode_select_6_test(void)
|
|
|
|
{
|
|
|
|
struct spdk_bdev bdev;
|
|
|
|
struct spdk_scsi_task task;
|
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
struct spdk_scsi_dev dev;
|
|
|
|
char cdb[16];
|
|
|
|
char data[24];
|
|
|
|
int rc;
|
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2016-07-27 16:32:00 +00:00
|
|
|
cdb[0] = 0x15;
|
|
|
|
cdb[1] = 0x11;
|
|
|
|
cdb[2] = 0x00;
|
|
|
|
cdb[3] = 0x00;
|
|
|
|
cdb[4] = 0x18;
|
|
|
|
cdb[5] = 0x00;
|
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
2016-07-27 16:32:00 +00:00
|
|
|
lun.dev = &dev;
|
|
|
|
task.lun = &lun;
|
|
|
|
|
|
|
|
memset(data, 0, sizeof(data));
|
|
|
|
data[4] = 0x08;
|
|
|
|
data[5] = 0x02;
|
2016-11-04 18:45:54 +00:00
|
|
|
spdk_scsi_task_set_data(&task, data, sizeof(data));
|
2016-07-27 16:32:00 +00:00
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
|
|
|
|
CU_ASSERT_EQUAL(rc, 0);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This test specifically tests a mode select 6 command which
|
|
|
|
* contains no mode pages.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
mode_select_6_test2(void)
|
|
|
|
{
|
|
|
|
struct spdk_bdev bdev;
|
|
|
|
struct spdk_scsi_task task;
|
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
struct spdk_scsi_dev dev;
|
|
|
|
char cdb[16];
|
|
|
|
int rc;
|
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2016-07-27 16:32:00 +00:00
|
|
|
cdb[0] = 0x15;
|
|
|
|
cdb[1] = 0x00;
|
|
|
|
cdb[2] = 0x00;
|
|
|
|
cdb[3] = 0x00;
|
|
|
|
cdb[4] = 0x00;
|
|
|
|
cdb[5] = 0x00;
|
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
2016-07-27 16:32:00 +00:00
|
|
|
lun.dev = &dev;
|
|
|
|
task.lun = &lun;
|
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
|
|
|
|
CU_ASSERT_EQUAL(rc, 0);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This test specifically tests a mode sense 6 command which
|
|
|
|
* return all subpage 00h mode pages.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
mode_sense_6_test(void)
|
|
|
|
{
|
|
|
|
struct spdk_bdev bdev;
|
|
|
|
struct spdk_scsi_task task;
|
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
struct spdk_scsi_dev dev;
|
|
|
|
char cdb[12];
|
2016-11-04 18:45:54 +00:00
|
|
|
unsigned char *data;
|
|
|
|
int rc;
|
2016-07-27 16:32:00 +00:00
|
|
|
unsigned char mode_data_len = 0;
|
|
|
|
unsigned char medium_type = 0;
|
|
|
|
unsigned char dev_specific_param = 0;
|
|
|
|
unsigned char blk_descriptor_len = 0;
|
|
|
|
|
2017-04-24 22:39:53 +00:00
|
|
|
memset(&bdev, 0, sizeof(struct spdk_bdev));
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
memset(cdb, 0, sizeof(cdb));
|
|
|
|
|
|
|
|
cdb[0] = 0x1A;
|
|
|
|
cdb[2] = 0x3F;
|
|
|
|
cdb[4] = 0xFF;
|
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
2016-07-27 16:32:00 +00:00
|
|
|
lun.dev = &dev;
|
|
|
|
task.lun = &lun;
|
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(rc == 0);
|
|
|
|
|
|
|
|
data = task.iovs[0].iov_base;
|
2016-07-27 16:32:00 +00:00
|
|
|
mode_data_len = data[0];
|
|
|
|
medium_type = data[1];
|
|
|
|
dev_specific_param = data[2];
|
|
|
|
blk_descriptor_len = data[3];
|
|
|
|
|
|
|
|
CU_ASSERT(mode_data_len >= 11);
|
|
|
|
CU_ASSERT_EQUAL(medium_type, 0);
|
|
|
|
CU_ASSERT_EQUAL(dev_specific_param, 0);
|
|
|
|
CU_ASSERT_EQUAL(blk_descriptor_len, 8);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This test specifically tests a mode sense 10 command which
|
|
|
|
* return all subpage 00h mode pages.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
mode_sense_10_test(void)
|
|
|
|
{
|
|
|
|
struct spdk_bdev bdev;
|
|
|
|
struct spdk_scsi_task task;
|
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
struct spdk_scsi_dev dev;
|
|
|
|
char cdb[12];
|
2016-11-04 18:45:54 +00:00
|
|
|
unsigned char *data;
|
2016-07-27 16:32:00 +00:00
|
|
|
int rc;
|
|
|
|
unsigned short mode_data_len = 0;
|
|
|
|
unsigned char medium_type = 0;
|
|
|
|
unsigned char dev_specific_param = 0;
|
|
|
|
unsigned short blk_descriptor_len = 0;
|
|
|
|
|
2017-04-24 22:39:53 +00:00
|
|
|
memset(&bdev, 0, sizeof(struct spdk_bdev));
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
memset(cdb, 0, sizeof(cdb));
|
|
|
|
cdb[0] = 0x5A;
|
|
|
|
cdb[2] = 0x3F;
|
|
|
|
cdb[8] = 0xFF;
|
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
2016-07-27 16:32:00 +00:00
|
|
|
lun.dev = &dev;
|
|
|
|
task.lun = &lun;
|
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(rc == 0);
|
|
|
|
|
|
|
|
data = task.iovs[0].iov_base;
|
2016-07-27 16:32:00 +00:00
|
|
|
mode_data_len = ((data[0] << 8) + data[1]);
|
|
|
|
medium_type = data[2];
|
|
|
|
dev_specific_param = data[3];
|
|
|
|
blk_descriptor_len = ((data[6] << 8) + data[7]);
|
|
|
|
|
|
|
|
CU_ASSERT(mode_data_len >= 14);
|
|
|
|
CU_ASSERT_EQUAL(medium_type, 0);
|
|
|
|
CU_ASSERT_EQUAL(dev_specific_param, 0);
|
|
|
|
CU_ASSERT_EQUAL(blk_descriptor_len, 8);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This test specifically tests a scsi inquiry command from the
|
|
|
|
* Windows SCSI compliance test that failed to return the
|
|
|
|
* expected SCSI error sense code.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
inquiry_evpd_test(void)
|
|
|
|
{
|
|
|
|
struct spdk_bdev bdev;
|
|
|
|
struct spdk_scsi_task task;
|
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
struct spdk_scsi_dev dev;
|
|
|
|
char cdb[6];
|
|
|
|
int rc;
|
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2016-07-27 16:32:00 +00:00
|
|
|
cdb[0] = 0x12;
|
2018-10-29 02:39:27 +00:00
|
|
|
cdb[1] = 0x00; /* EVPD = 0 */
|
|
|
|
cdb[2] = 0xff; /* PageCode non-zero */
|
2016-07-27 16:32:00 +00:00
|
|
|
cdb[3] = 0x00;
|
|
|
|
cdb[4] = 0xff;
|
|
|
|
cdb[5] = 0x00;
|
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
2016-07-27 16:32:00 +00:00
|
|
|
lun.dev = &dev;
|
|
|
|
task.lun = &lun;
|
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(rc == 0);
|
2016-07-27 16:32:00 +00:00
|
|
|
|
|
|
|
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
2016-10-31 17:39:59 +00:00
|
|
|
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);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This test is to verify specific return data for a standard scsi inquiry
|
|
|
|
* command: Version
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
inquiry_standard_test(void)
|
|
|
|
{
|
2017-03-30 15:28:43 +00:00
|
|
|
struct spdk_bdev bdev = { .blocklen = 512 };
|
2016-07-27 16:32:00 +00:00
|
|
|
struct spdk_scsi_task task;
|
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
struct spdk_scsi_dev dev;
|
|
|
|
char cdb[6];
|
2016-11-04 18:45:54 +00:00
|
|
|
char *data;
|
2016-07-27 16:32:00 +00:00
|
|
|
struct spdk_scsi_cdb_inquiry_data *inq_data;
|
|
|
|
int rc;
|
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2016-07-27 16:32:00 +00:00
|
|
|
cdb[0] = 0x12;
|
2018-10-29 02:39:27 +00:00
|
|
|
cdb[1] = 0x00; /* EVPD = 0 */
|
|
|
|
cdb[2] = 0x00; /* PageCode zero - requesting standard inquiry */
|
2016-07-27 16:32:00 +00:00
|
|
|
cdb[3] = 0x00;
|
2018-10-29 02:39:27 +00:00
|
|
|
cdb[4] = 0xff; /* Indicate data size used by conformance test */
|
2016-07-27 16:32:00 +00:00
|
|
|
cdb[5] = 0x00;
|
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
2016-07-27 16:32:00 +00:00
|
|
|
lun.dev = &dev;
|
|
|
|
task.lun = &lun;
|
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
|
2016-11-04 18:45:54 +00:00
|
|
|
data = task.iovs[0].iov_base;
|
2016-07-27 16:32:00 +00:00
|
|
|
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);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2016-07-27 16:32:00 +00:00
|
|
|
}
|
|
|
|
|
2016-09-06 19:36:29 +00:00
|
|
|
static void
|
|
|
|
_inquiry_overflow_test(uint8_t alloc_len)
|
|
|
|
{
|
2017-03-30 15:28:43 +00:00
|
|
|
struct spdk_bdev bdev = { .blocklen = 512 };
|
2016-09-06 19:36:29 +00:00
|
|
|
struct spdk_scsi_task task;
|
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
struct spdk_scsi_dev dev;
|
|
|
|
uint8_t cdb[6];
|
|
|
|
int rc;
|
2016-11-04 18:45:54 +00:00
|
|
|
/* expects a 4K internal data buffer */
|
|
|
|
char data[4096], data_compare[4096];
|
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2016-09-06 19:36:29 +00:00
|
|
|
|
|
|
|
cdb[0] = 0x12;
|
2018-10-29 02:39:27 +00:00
|
|
|
cdb[1] = 0x00; /* EVPD = 0 */
|
|
|
|
cdb[2] = 0x00; /* PageCode zero - requesting standard inquiry */
|
2016-09-06 19:36:29 +00:00
|
|
|
cdb[3] = 0x00;
|
2018-10-29 02:39:27 +00:00
|
|
|
cdb[4] = alloc_len; /* Indicate data size used by conformance test */
|
2016-09-06 19:36:29 +00:00
|
|
|
cdb[5] = 0x00;
|
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
2016-09-06 19:36:29 +00:00
|
|
|
lun.dev = &dev;
|
|
|
|
task.lun = &lun;
|
|
|
|
|
|
|
|
memset(data, 0, sizeof(data));
|
|
|
|
memset(data_compare, 0, sizeof(data_compare));
|
2016-11-04 18:45:54 +00:00
|
|
|
|
|
|
|
spdk_scsi_task_set_data(&task, data, sizeof(data));
|
2016-09-06 19:36:29 +00:00
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(rc == 0);
|
|
|
|
|
2016-09-06 19:36:29 +00:00
|
|
|
CU_ASSERT_EQUAL(memcmp(data + alloc_len, data_compare + alloc_len, sizeof(data) - alloc_len), 0);
|
|
|
|
CU_ASSERT(task.data_transferred <= alloc_len);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2016-09-06 19:36:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
inquiry_overflow_test(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
_inquiry_overflow_test(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-04 02:58:32 +00:00
|
|
|
static void
|
|
|
|
scsi_name_padding_test(void)
|
|
|
|
{
|
2018-04-09 17:19:08 +00:00
|
|
|
char name[SPDK_SCSI_DEV_MAX_NAME + 1];
|
2018-01-04 02:58:32 +00:00
|
|
|
char buf[SPDK_SCSI_DEV_MAX_NAME + 1];
|
|
|
|
int written, i;
|
|
|
|
|
|
|
|
/* case 1 */
|
|
|
|
memset(name, '\0', sizeof(name));
|
|
|
|
memset(name, 'x', 251);
|
|
|
|
written = spdk_bdev_scsi_pad_scsi_name(buf, name);
|
|
|
|
|
|
|
|
CU_ASSERT(written == 252);
|
|
|
|
CU_ASSERT(buf[250] == 'x');
|
|
|
|
CU_ASSERT(buf[251] == '\0');
|
|
|
|
|
|
|
|
/* case 2: */
|
|
|
|
memset(name, '\0', sizeof(name));
|
|
|
|
memset(name, 'x', 252);
|
|
|
|
written = spdk_bdev_scsi_pad_scsi_name(buf, name);
|
|
|
|
|
|
|
|
CU_ASSERT(written == 256);
|
|
|
|
CU_ASSERT(buf[251] == 'x');
|
|
|
|
for (i = 252; i < 256; i++) {
|
|
|
|
CU_ASSERT(buf[i] == '\0');
|
|
|
|
}
|
|
|
|
|
|
|
|
/* case 3 */
|
|
|
|
memset(name, '\0', sizeof(name));
|
|
|
|
memset(name, 'x', 255);
|
|
|
|
written = spdk_bdev_scsi_pad_scsi_name(buf, name);
|
|
|
|
|
|
|
|
CU_ASSERT(written == 256);
|
|
|
|
CU_ASSERT(buf[254] == 'x');
|
|
|
|
CU_ASSERT(buf[255] == '\0');
|
|
|
|
}
|
|
|
|
|
2016-10-28 19:56:36 +00:00
|
|
|
/*
|
|
|
|
* This test is to verify specific error translation from bdev to scsi.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
task_complete_test(void)
|
|
|
|
{
|
2016-11-04 18:45:54 +00:00
|
|
|
struct spdk_scsi_task task;
|
2016-10-28 19:56:36 +00:00
|
|
|
struct spdk_bdev_io bdev_io = {};
|
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2016-10-28 19:56:36 +00:00
|
|
|
TAILQ_INIT(&lun.tasks);
|
|
|
|
TAILQ_INSERT_TAIL(&lun.tasks, &task, scsi_link);
|
|
|
|
task.lun = &lun;
|
|
|
|
|
2018-06-19 23:19:49 +00:00
|
|
|
bdev_io.internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
|
|
|
spdk_bdev_scsi_task_complete_cmd(&bdev_io, bdev_io.internal.status, &task);
|
2016-10-28 19:56:36 +00:00
|
|
|
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD);
|
2018-07-03 13:21:56 +00:00
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
2016-10-28 19:56:36 +00:00
|
|
|
|
2018-06-19 23:19:49 +00:00
|
|
|
bdev_io.internal.status = SPDK_BDEV_IO_STATUS_SCSI_ERROR;
|
2018-06-20 23:38:35 +00:00
|
|
|
bdev_io.internal.error.scsi.sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
|
|
|
bdev_io.internal.error.scsi.sk = SPDK_SCSI_SENSE_HARDWARE_ERROR;
|
|
|
|
bdev_io.internal.error.scsi.asc = SPDK_SCSI_ASC_WARNING;
|
|
|
|
bdev_io.internal.error.scsi.ascq = SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED;
|
2018-06-19 23:19:49 +00:00
|
|
|
spdk_bdev_scsi_task_complete_cmd(&bdev_io, bdev_io.internal.status, &task);
|
2016-11-07 20:14:47 +00:00
|
|
|
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
|
|
|
CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_HARDWARE_ERROR);
|
|
|
|
CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_WARNING);
|
|
|
|
CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED);
|
2018-07-03 13:21:56 +00:00
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
2016-11-07 20:14:47 +00:00
|
|
|
|
2018-06-19 23:19:49 +00:00
|
|
|
bdev_io.internal.status = SPDK_BDEV_IO_STATUS_FAILED;
|
|
|
|
spdk_bdev_scsi_task_complete_cmd(&bdev_io, bdev_io.internal.status, &task);
|
2016-10-28 19:56:36 +00:00
|
|
|
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
2016-11-07 20:14:47 +00:00
|
|
|
CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ABORTED_COMMAND);
|
2016-10-31 17:39:59 +00:00
|
|
|
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);
|
2018-07-03 13:21:56 +00:00
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
2016-11-04 18:45:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2016-10-28 19:56:36 +00:00
|
|
|
}
|
|
|
|
|
2017-05-12 18:13:54 +00:00
|
|
|
static void
|
|
|
|
lba_range_test(void)
|
|
|
|
{
|
2019-02-15 00:03:59 +00:00
|
|
|
struct spdk_bdev bdev = { .blocklen = 512 };
|
2018-01-04 22:45:01 +00:00
|
|
|
struct spdk_scsi_lun lun;
|
2017-05-12 18:13:54 +00:00
|
|
|
struct spdk_scsi_task task;
|
|
|
|
uint8_t cdb[16];
|
|
|
|
int rc;
|
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2018-01-04 22:45:01 +00:00
|
|
|
task.lun = &lun;
|
2018-08-30 20:36:33 +00:00
|
|
|
task.lun->bdev_desc = NULL;
|
|
|
|
task.lun->io_channel = NULL;
|
2017-05-12 18:13:54 +00:00
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
memset(cdb, 0, sizeof(cdb));
|
|
|
|
cdb[0] = 0x88; /* READ (16) */
|
|
|
|
|
|
|
|
/* Test block device size of 4 blocks */
|
|
|
|
g_test_bdev_num_blocks = 4;
|
|
|
|
|
|
|
|
/* LBA = 0, length = 1 (in range) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], 1); /* transfer length */
|
|
|
|
task.transfer_len = 1 * 512;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-05-12 18:13:54 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
|
2018-07-03 13:02:19 +00:00
|
|
|
CU_ASSERT(task.status == 0xFF);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_bdev_io_queue));
|
|
|
|
ut_bdev_io_flush();
|
2018-07-03 13:02:19 +00:00
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
2018-07-03 13:21:56 +00:00
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
2017-05-12 18:13:54 +00:00
|
|
|
|
|
|
|
/* LBA = 4, length = 1 (LBA out of range) */
|
|
|
|
to_be64(&cdb[2], 4); /* LBA */
|
|
|
|
to_be32(&cdb[10], 1); /* transfer length */
|
|
|
|
task.transfer_len = 1 * 512;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-05-12 18:13:54 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
|
|
|
CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
|
2017-05-12 18:13:54 +00:00
|
|
|
|
|
|
|
/* LBA = 0, length = 4 (in range, max valid size) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], 4); /* transfer length */
|
|
|
|
task.transfer_len = 4 * 512;
|
2018-07-03 13:02:19 +00:00
|
|
|
task.status = 0xFF;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-05-12 18:13:54 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
|
2018-07-03 13:02:19 +00:00
|
|
|
CU_ASSERT(task.status == 0xFF);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_bdev_io_queue));
|
|
|
|
ut_bdev_io_flush();
|
2018-07-03 13:02:19 +00:00
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
2018-07-03 13:21:56 +00:00
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
2017-05-12 18:13:54 +00:00
|
|
|
|
|
|
|
/* LBA = 0, length = 5 (LBA in range, length beyond end of bdev) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], 5); /* transfer length */
|
|
|
|
task.transfer_len = 5 * 512;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-05-12 18:13:54 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
|
|
|
CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
|
2017-05-12 18:13:54 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2017-05-12 18:13:54 +00:00
|
|
|
}
|
|
|
|
|
2017-05-12 20:24:15 +00:00
|
|
|
static void
|
|
|
|
xfer_len_test(void)
|
|
|
|
{
|
2019-02-15 00:03:59 +00:00
|
|
|
struct spdk_bdev bdev = { .blocklen = 512 };
|
2018-01-04 22:45:01 +00:00
|
|
|
struct spdk_scsi_lun lun;
|
2017-05-12 20:24:15 +00:00
|
|
|
struct spdk_scsi_task task;
|
|
|
|
uint8_t cdb[16];
|
|
|
|
int rc;
|
|
|
|
|
2018-01-04 22:45:01 +00:00
|
|
|
lun.bdev = &bdev;
|
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_init_task(&task);
|
2018-01-04 22:45:01 +00:00
|
|
|
task.lun = &lun;
|
2018-08-30 20:36:33 +00:00
|
|
|
task.lun->bdev_desc = NULL;
|
|
|
|
task.lun->io_channel = NULL;
|
2017-05-12 20:24:15 +00:00
|
|
|
task.cdb = cdb;
|
|
|
|
|
|
|
|
memset(cdb, 0, sizeof(cdb));
|
|
|
|
cdb[0] = 0x88; /* READ (16) */
|
|
|
|
|
|
|
|
/* Test block device size of 512 MiB */
|
|
|
|
g_test_bdev_num_blocks = 512 * 1024 * 1024;
|
|
|
|
|
|
|
|
/* 1 block */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], 1); /* transfer length */
|
|
|
|
task.transfer_len = 1 * 512;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-05-12 20:24:15 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
|
2018-07-03 13:02:19 +00:00
|
|
|
CU_ASSERT(task.status == 0xFF);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_bdev_io_queue));
|
|
|
|
ut_bdev_io_flush();
|
2018-07-03 13:02:19 +00:00
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
2018-07-03 13:21:56 +00:00
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
2017-05-12 20:24:15 +00:00
|
|
|
|
|
|
|
/* max transfer length (as reported in block limits VPD page) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], SPDK_WORK_BLOCK_SIZE / 512); /* transfer length */
|
|
|
|
task.transfer_len = SPDK_WORK_BLOCK_SIZE;
|
2018-07-03 13:02:19 +00:00
|
|
|
task.status = 0xFF;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-05-12 20:24:15 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
|
2018-07-03 13:02:19 +00:00
|
|
|
CU_ASSERT(task.status == 0xFF);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_bdev_io_queue));
|
|
|
|
ut_bdev_io_flush();
|
2018-07-03 13:02:19 +00:00
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
2018-07-03 13:21:56 +00:00
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
2017-05-12 20:24:15 +00:00
|
|
|
|
|
|
|
/* max transfer length plus one block (invalid) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], SPDK_WORK_BLOCK_SIZE / 512 + 1); /* transfer length */
|
|
|
|
task.transfer_len = SPDK_WORK_BLOCK_SIZE + 512;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-05-12 20:24:15 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
|
|
|
CU_ASSERT((task.sense_data[2] & 0xf) == SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
|
|
|
|
CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
|
2017-05-12 20:24:15 +00:00
|
|
|
|
2017-08-15 15:56:20 +00:00
|
|
|
/* zero transfer length (valid) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], 0); /* transfer length */
|
|
|
|
task.transfer_len = 0;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 0;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-08-15 15:56:20 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
|
|
|
CU_ASSERT(task.data_transferred == 0);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
|
2017-08-15 15:56:20 +00:00
|
|
|
|
|
|
|
/* zero transfer length past end of disk (invalid) */
|
|
|
|
to_be64(&cdb[2], g_test_bdev_num_blocks); /* LBA */
|
|
|
|
to_be32(&cdb[10], 0); /* transfer length */
|
|
|
|
task.transfer_len = 0;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 0;
|
2018-01-04 22:45:01 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
2017-08-15 15:56:20 +00:00
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_COMPLETE);
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
|
|
|
CU_ASSERT(task.sense_data[12] == SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);
|
2018-07-03 13:21:56 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&g_bdev_io_queue));
|
2017-08-15 15:56:20 +00:00
|
|
|
|
2018-07-03 08:18:07 +00:00
|
|
|
ut_put_task(&task);
|
2017-05-12 20:24:15 +00:00
|
|
|
}
|
|
|
|
|
2018-07-10 16:44:15 +00:00
|
|
|
static void
|
2018-07-05 07:32:48 +00:00
|
|
|
_xfer_test(bool bdev_io_pool_full)
|
2018-07-10 16:44:15 +00:00
|
|
|
{
|
2019-02-15 00:03:59 +00:00
|
|
|
struct spdk_bdev bdev = { .blocklen = 512 };
|
2018-07-10 16:44:15 +00:00
|
|
|
struct spdk_scsi_lun lun;
|
|
|
|
struct spdk_scsi_task task;
|
|
|
|
uint8_t cdb[16];
|
|
|
|
char data[4096];
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
lun.bdev = &bdev;
|
|
|
|
|
|
|
|
/* Test block device size of 512 MiB */
|
|
|
|
g_test_bdev_num_blocks = 512 * 1024 * 1024;
|
|
|
|
|
|
|
|
/* Read 1 block */
|
|
|
|
ut_init_task(&task);
|
|
|
|
task.lun = &lun;
|
2018-08-30 20:36:33 +00:00
|
|
|
task.lun->bdev_desc = NULL;
|
|
|
|
task.lun->io_channel = NULL;
|
2018-07-10 16:44:15 +00:00
|
|
|
task.cdb = cdb;
|
|
|
|
memset(cdb, 0, sizeof(cdb));
|
|
|
|
cdb[0] = 0x88; /* READ (16) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], 1); /* transfer length */
|
|
|
|
task.transfer_len = 1 * 512;
|
2019-02-15 00:03:59 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-07-05 07:32:48 +00:00
|
|
|
g_bdev_io_pool_full = bdev_io_pool_full;
|
2018-07-10 16:44:15 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
|
|
|
|
CU_ASSERT(task.status == 0xFF);
|
|
|
|
|
|
|
|
ut_bdev_io_flush();
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
|
|
|
ut_put_task(&task);
|
|
|
|
|
|
|
|
/* Write 1 block */
|
|
|
|
ut_init_task(&task);
|
|
|
|
task.lun = &lun;
|
|
|
|
task.cdb = cdb;
|
|
|
|
memset(cdb, 0, sizeof(cdb));
|
|
|
|
cdb[0] = 0x8a; /* WRITE (16) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], 1); /* transfer length */
|
|
|
|
task.transfer_len = 1 * 512;
|
2019-02-15 01:23:45 +00:00
|
|
|
task.offset = 0;
|
|
|
|
task.length = 1 * 512;
|
2018-07-05 07:32:48 +00:00
|
|
|
g_bdev_io_pool_full = bdev_io_pool_full;
|
2018-07-10 16:44:15 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
|
|
|
|
CU_ASSERT(task.status == 0xFF);
|
|
|
|
|
|
|
|
ut_bdev_io_flush();
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
|
|
|
ut_put_task(&task);
|
|
|
|
|
|
|
|
/* Unmap 5 blocks using 2 descriptors */
|
|
|
|
ut_init_task(&task);
|
|
|
|
task.lun = &lun;
|
|
|
|
task.cdb = cdb;
|
|
|
|
memset(cdb, 0, sizeof(cdb));
|
|
|
|
cdb[0] = 0x42; /* UNMAP */
|
|
|
|
to_be16(&data[7], 2); /* 2 parameters in list */
|
|
|
|
memset(data, 0, sizeof(data));
|
|
|
|
to_be16(&data[2], 32); /* 2 descriptors */
|
|
|
|
to_be64(&data[8], 1); /* LBA 1 */
|
|
|
|
to_be32(&data[16], 2); /* 2 blocks */
|
|
|
|
to_be64(&data[24], 10); /* LBA 10 */
|
|
|
|
to_be32(&data[32], 3); /* 3 blocks */
|
|
|
|
spdk_scsi_task_set_data(&task, data, sizeof(data));
|
|
|
|
task.status = SPDK_SCSI_STATUS_GOOD;
|
2018-07-05 07:32:48 +00:00
|
|
|
g_bdev_io_pool_full = bdev_io_pool_full;
|
2018-07-10 16:44:15 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
|
|
|
|
|
|
|
ut_bdev_io_flush();
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
|
|
|
ut_put_task(&task);
|
|
|
|
|
|
|
|
/* Flush 1 block */
|
|
|
|
ut_init_task(&task);
|
|
|
|
task.lun = &lun;
|
|
|
|
task.cdb = cdb;
|
|
|
|
memset(cdb, 0, sizeof(cdb));
|
|
|
|
cdb[0] = 0x91; /* SYNCHRONIZE CACHE (16) */
|
|
|
|
to_be64(&cdb[2], 0); /* LBA */
|
|
|
|
to_be32(&cdb[10], 1); /* 1 blocks */
|
2018-07-05 07:32:48 +00:00
|
|
|
g_bdev_io_pool_full = bdev_io_pool_full;
|
2018-07-10 16:44:15 +00:00
|
|
|
rc = spdk_bdev_scsi_execute(&task);
|
|
|
|
CU_ASSERT(rc == SPDK_SCSI_TASK_PENDING);
|
|
|
|
CU_ASSERT(task.status == 0xFF);
|
|
|
|
|
|
|
|
ut_bdev_io_flush();
|
|
|
|
CU_ASSERT(task.status == SPDK_SCSI_STATUS_GOOD);
|
|
|
|
CU_ASSERT(g_scsi_cb_called == 1);
|
|
|
|
g_scsi_cb_called = 0;
|
|
|
|
ut_put_task(&task);
|
|
|
|
}
|
|
|
|
|
2018-07-05 07:32:48 +00:00
|
|
|
static void
|
|
|
|
xfer_test(void)
|
|
|
|
{
|
|
|
|
_xfer_test(false);
|
|
|
|
_xfer_test(true);
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:53:10 +00:00
|
|
|
static void
|
|
|
|
get_dif_ctx_test(void)
|
|
|
|
{
|
|
|
|
struct spdk_bdev bdev = {};
|
|
|
|
struct spdk_dif_ctx dif_ctx = {};
|
|
|
|
uint8_t cdb[16];
|
|
|
|
uint32_t offset;
|
|
|
|
bool ret;
|
|
|
|
|
|
|
|
cdb[0] = SPDK_SBC_READ_6;
|
|
|
|
cdb[1] = 0x12;
|
|
|
|
cdb[2] = 0x34;
|
|
|
|
cdb[3] = 0x50;
|
|
|
|
offset = 0x6 * 512;
|
|
|
|
|
|
|
|
ret = spdk_scsi_bdev_get_dif_ctx(&bdev, cdb, offset, &dif_ctx);
|
|
|
|
CU_ASSERT(ret == true);
|
|
|
|
CU_ASSERT(dif_ctx.init_ref_tag == 0x123456);
|
|
|
|
|
|
|
|
cdb[0] = SPDK_SBC_WRITE_12;
|
|
|
|
to_be32(&cdb[2], 0x12345670);
|
|
|
|
offset = 0x8 * 512;
|
|
|
|
|
|
|
|
ret = spdk_scsi_bdev_get_dif_ctx(&bdev, cdb, offset, &dif_ctx);
|
|
|
|
CU_ASSERT(ret == true);
|
|
|
|
CU_ASSERT(dif_ctx.init_ref_tag == 0x12345678);
|
|
|
|
|
|
|
|
cdb[0] = SPDK_SBC_WRITE_16;
|
|
|
|
to_be64(&cdb[2], 0x0000000012345670);
|
|
|
|
offset = 0x8 * 512;
|
|
|
|
|
|
|
|
ret = spdk_scsi_bdev_get_dif_ctx(&bdev, cdb, offset, &dif_ctx);
|
|
|
|
CU_ASSERT(ret == true);
|
|
|
|
CU_ASSERT(dif_ctx.init_ref_tag == 0x12345678);
|
|
|
|
}
|
|
|
|
|
2016-07-27 16:32:00 +00:00
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
CU_pSuite suite = NULL;
|
|
|
|
unsigned int num_failures;
|
|
|
|
|
2018-07-03 13:21:56 +00:00
|
|
|
TAILQ_INIT(&g_bdev_io_queue);
|
2018-07-05 07:32:48 +00:00
|
|
|
TAILQ_INIT(&g_io_wait_queue);
|
2018-07-03 13:21:56 +00:00
|
|
|
|
2016-07-27 16:32:00 +00:00
|
|
|
if (CU_initialize_registry() != CUE_SUCCESS) {
|
|
|
|
return CU_get_error();
|
|
|
|
}
|
|
|
|
|
|
|
|
suite = CU_add_suite("translation_suite", NULL, NULL);
|
|
|
|
if (suite == NULL) {
|
|
|
|
CU_cleanup_registry();
|
|
|
|
return CU_get_error();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
CU_add_test(suite, "mode select 6 test", mode_select_6_test) == NULL
|
|
|
|
|| CU_add_test(suite, "mode select 6 test2", mode_select_6_test2) == NULL
|
|
|
|
|| CU_add_test(suite, "mode sense 6 test", mode_sense_6_test) == NULL
|
|
|
|
|| CU_add_test(suite, "mode sense 10 test", mode_sense_10_test) == NULL
|
|
|
|
|| CU_add_test(suite, "inquiry evpd test", inquiry_evpd_test) == NULL
|
|
|
|
|| CU_add_test(suite, "inquiry standard test", inquiry_standard_test) == NULL
|
2016-09-06 19:36:29 +00:00
|
|
|
|| CU_add_test(suite, "inquiry overflow test", inquiry_overflow_test) == NULL
|
2016-10-28 19:56:36 +00:00
|
|
|
|| CU_add_test(suite, "task complete test", task_complete_test) == NULL
|
2017-05-12 18:13:54 +00:00
|
|
|
|| CU_add_test(suite, "LBA range test", lba_range_test) == NULL
|
2017-05-12 20:24:15 +00:00
|
|
|
|| CU_add_test(suite, "transfer length test", xfer_len_test) == NULL
|
2018-07-10 16:44:15 +00:00
|
|
|
|| CU_add_test(suite, "transfer test", xfer_test) == NULL
|
2018-01-04 02:58:32 +00:00
|
|
|
|| CU_add_test(suite, "scsi name padding test", scsi_name_padding_test) == NULL
|
2019-02-26 06:53:10 +00:00
|
|
|
|| CU_add_test(suite, "get dif context test", get_dif_ctx_test) == NULL
|
2016-07-27 16:32:00 +00:00
|
|
|
) {
|
|
|
|
CU_cleanup_registry();
|
|
|
|
return CU_get_error();
|
|
|
|
}
|
|
|
|
|
|
|
|
CU_basic_set_mode(CU_BRM_VERBOSE);
|
|
|
|
CU_basic_run_tests();
|
|
|
|
num_failures = CU_get_number_of_failures();
|
|
|
|
CU_cleanup_registry();
|
|
|
|
return num_failures;
|
|
|
|
}
|