scsi: import SCSI/blockdev translation layer
Change-Id: Ie96943f40ea8be4156d55bc5eeacc567743cf9d6 Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
parent
8779605323
commit
bd4ac74eaf
@ -63,6 +63,7 @@ time test/lib/ioat/ioat.sh
|
||||
time test/lib/json/json.sh
|
||||
time test/lib/jsonrpc/jsonrpc.sh
|
||||
time test/lib/log/log.sh
|
||||
time test/lib/scsi/scsi.sh
|
||||
|
||||
timing_exit lib
|
||||
|
||||
|
209
include/spdk/scsi.h
Normal file
209
include/spdk/scsi.h
Normal file
@ -0,0 +1,209 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* SCSI to blockdev translation layer
|
||||
*/
|
||||
|
||||
#ifndef SPDK_SCSI_H
|
||||
#define SPDK_SCSI_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "spdk/queue.h"
|
||||
#include "spdk/event.h"
|
||||
|
||||
#define SPDK_SCSI_MAX_DEVS 1024
|
||||
#define SPDK_SCSI_DEV_MAX_LUN 64
|
||||
#define SPDK_SCSI_DEV_MAX_PORTS 4
|
||||
#define SPDK_SCSI_DEV_MAX_NAME 255
|
||||
|
||||
#define SPDK_SCSI_PORT_MAX_NAME_LENGTH 255
|
||||
|
||||
#define SPDK_SCSI_LUN_MAX_NAME_LENGTH 16
|
||||
|
||||
enum spdk_scsi_data_dir {
|
||||
SPDK_SCSI_DIR_NONE = 0,
|
||||
SPDK_SCSI_DIR_TO_DEV = 1,
|
||||
SPDK_SCSI_DIR_FROM_DEV = 2,
|
||||
};
|
||||
|
||||
enum spdk_scsi_task_func {
|
||||
SPDK_SCSI_TASK_FUNC_ABORT_TASK = 0,
|
||||
SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET,
|
||||
SPDK_SCSI_TASK_FUNC_CLEAR_TASK_SET,
|
||||
SPDK_SCSI_TASK_FUNC_LUN_RESET,
|
||||
};
|
||||
|
||||
enum spdk_scsi_task_type {
|
||||
SPDK_SCSI_TASK_TYPE_CMD = 0,
|
||||
SPDK_SCSI_TASK_TYPE_MANAGE,
|
||||
};
|
||||
|
||||
struct spdk_scsi_task {
|
||||
uint8_t type;
|
||||
uint8_t status;
|
||||
uint8_t function; /* task mgmt function */
|
||||
uint8_t response; /* task mgmt response */
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_port *target_port;
|
||||
struct spdk_scsi_port *initiator_port;
|
||||
spdk_event_t cb_event;
|
||||
|
||||
uint32_t ref;
|
||||
uint32_t id;
|
||||
uint32_t transfer_len;
|
||||
uint32_t data_out_cnt;
|
||||
uint32_t dxfer_dir;
|
||||
uint32_t desired_data_transfer_length;
|
||||
/* Only valid for Read/Write */
|
||||
uint32_t bytes_completed;
|
||||
uint32_t length;
|
||||
|
||||
/**
|
||||
* Amount of data actually transferred. Can be less than requested
|
||||
* transfer_len - i.e. SCSI INQUIRY.
|
||||
*/
|
||||
uint32_t data_transferred;
|
||||
uint32_t alloc_len;
|
||||
|
||||
uint64_t offset;
|
||||
struct iovec iov;
|
||||
struct spdk_scsi_task *parent;
|
||||
|
||||
void (*free_fn)(struct spdk_scsi_task *);
|
||||
|
||||
uint8_t *cdb;
|
||||
uint8_t *iobuf;
|
||||
|
||||
uint8_t sense_data[32];
|
||||
size_t sense_data_len;
|
||||
|
||||
uint8_t *rbuf; /* read buffer */
|
||||
void *blockdev_io;
|
||||
|
||||
TAILQ_ENTRY(spdk_scsi_task) scsi_link;
|
||||
|
||||
/*
|
||||
* Pointer to scsi task owner's outstanding
|
||||
* task counter. Inc/Dec by get/put task functions.
|
||||
* Note: in the future, we could consider replacing this
|
||||
* with an owner-provided task management fuction that
|
||||
* could perform protocol specific task mangement
|
||||
* operations (such as tracking outstanding tasks).
|
||||
*/
|
||||
uint32_t *owner_task_ctr;
|
||||
|
||||
uint32_t abort_id;
|
||||
TAILQ_HEAD(subtask_list, spdk_scsi_task) subtask_list;
|
||||
};
|
||||
|
||||
struct spdk_scsi_port {
|
||||
struct spdk_scsi_dev *dev;
|
||||
uint64_t id;
|
||||
uint16_t index;
|
||||
char name[SPDK_SCSI_PORT_MAX_NAME_LENGTH];
|
||||
};
|
||||
|
||||
struct spdk_scsi_dev {
|
||||
int id;
|
||||
int is_allocated;
|
||||
|
||||
char name[SPDK_SCSI_DEV_MAX_NAME];
|
||||
|
||||
int maxlun;
|
||||
struct spdk_scsi_lun *lun[SPDK_SCSI_DEV_MAX_LUN];
|
||||
|
||||
int num_ports;
|
||||
struct spdk_scsi_port port[SPDK_SCSI_DEV_MAX_PORTS];
|
||||
};
|
||||
|
||||
void spdk_scsi_dev_destruct(struct spdk_scsi_dev *dev);
|
||||
void spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev, struct spdk_scsi_task *task);
|
||||
void spdk_scsi_dev_queue_task(struct spdk_scsi_dev *dev, struct spdk_scsi_task *task);
|
||||
int spdk_scsi_dev_add_port(struct spdk_scsi_dev *dev, uint64_t id, const char *name);
|
||||
struct spdk_scsi_port *spdk_scsi_dev_find_port_by_id(struct spdk_scsi_dev *dev, uint64_t id);
|
||||
void spdk_scsi_dev_print(struct spdk_scsi_dev *dev);
|
||||
|
||||
/**
|
||||
|
||||
\brief Constructs a SCSI device object using the given parameters.
|
||||
|
||||
\param name Name for the SCSI device.
|
||||
\param queue_depth Queue depth for the SCSI device. This queue depth is
|
||||
a combined queue depth for all LUNs in the device.
|
||||
\param lun_list List of LUN objects for the SCSI device. Caller is
|
||||
responsible for managing the memory containing this list.
|
||||
\param lun_id_list List of LUN IDs for the LUN in this SCSI device. Caller is
|
||||
responsible for managing the memory containing this list.
|
||||
lun_id_list[x] is the LUN ID for lun_list[x].
|
||||
\param num_luns Number of entries in lun_list and lun_id_list.
|
||||
\return The constructed spdk_scsi_dev object.
|
||||
|
||||
*/
|
||||
struct spdk_scsi_dev *spdk_scsi_dev_construct(const char *name,
|
||||
char *lun_name_list[],
|
||||
int *lun_id_list,
|
||||
int num_luns);
|
||||
|
||||
void spdk_scsi_dev_delete_lun(struct spdk_scsi_dev *dev, struct spdk_scsi_lun *lun);
|
||||
|
||||
|
||||
int spdk_scsi_port_construct(struct spdk_scsi_port *port, uint64_t id,
|
||||
uint16_t index, const char *name);
|
||||
|
||||
|
||||
void spdk_scsi_task_construct(struct spdk_scsi_task *task, uint32_t *owner_task_ctr,
|
||||
struct spdk_scsi_task *parent);
|
||||
void spdk_put_task(struct spdk_scsi_task *task);
|
||||
void spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
|
||||
uint8_t **data);
|
||||
int spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc,
|
||||
int ascq);
|
||||
void spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk,
|
||||
int asc, int ascq);
|
||||
|
||||
static inline struct spdk_scsi_task *
|
||||
spdk_scsi_task_get_primary(struct spdk_scsi_task *task)
|
||||
{
|
||||
if (task->parent) {
|
||||
return task->parent;
|
||||
} else {
|
||||
return task;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SPDK_SCSI_H */
|
@ -34,7 +34,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y += bdev conf copy cunit event json jsonrpc log memory rpc trace util nvme nvmf ioat
|
||||
DIRS-y += bdev conf copy cunit event json jsonrpc log memory rpc trace util nvme nvmf scsi ioat
|
||||
|
||||
.PHONY: all clean $(DIRS-y)
|
||||
|
||||
|
41
lib/scsi/Makefile
Normal file
41
lib/scsi/Makefile
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
CFLAGS += $(DPDK_INC)
|
||||
C_SRCS = dev.c lun.c lun_db.c port.c scsi.c scsi_bdev.c scsi_rpc.c task.c
|
||||
LIBNAME = scsi
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
|
258
lib/scsi/dev.c
Normal file
258
lib/scsi/dev.c
Normal file
@ -0,0 +1,258 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
|
||||
static struct spdk_scsi_dev g_devs[SPDK_SCSI_MAX_DEVS];
|
||||
|
||||
struct spdk_scsi_dev *
|
||||
spdk_scsi_dev_get_list(void)
|
||||
{
|
||||
return g_devs;
|
||||
}
|
||||
|
||||
static struct spdk_scsi_dev *
|
||||
allocate_dev(void)
|
||||
{
|
||||
struct spdk_scsi_dev *dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SPDK_SCSI_MAX_DEVS; i++) {
|
||||
dev = &g_devs[i];
|
||||
if (!dev->is_allocated) {
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->id = i;
|
||||
dev->is_allocated = 1;
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
free_dev(struct spdk_scsi_dev *dev)
|
||||
{
|
||||
dev->is_allocated = 0;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_dev_destruct(struct spdk_scsi_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dev == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->maxlun; i++) {
|
||||
if (dev->lun[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spdk_scsi_lun_unclaim(dev->lun[i]);
|
||||
dev->lun[i] = NULL;
|
||||
}
|
||||
|
||||
free_dev(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
spdk_scsi_dev_add_lun(struct spdk_scsi_dev *dev,
|
||||
struct spdk_scsi_lun *lun, int id)
|
||||
{
|
||||
spdk_scsi_lun_claim(lun);
|
||||
lun->id = id;
|
||||
lun->dev = dev;
|
||||
dev->lun[id] = lun;
|
||||
if (dev->maxlun <= id) {
|
||||
dev->maxlun = id + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_dev_delete_lun(struct spdk_scsi_dev *dev,
|
||||
struct spdk_scsi_lun *lun)
|
||||
{
|
||||
int i;
|
||||
int maxlun = 0;
|
||||
|
||||
for (i = 0; i < dev->maxlun; i++) {
|
||||
if (dev->lun[i] && dev->lun[i] == lun)
|
||||
dev->lun[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->maxlun; i++) {
|
||||
if (dev->lun[i]) {
|
||||
if (maxlun <= dev->lun[i]->id) {
|
||||
maxlun = dev->lun[i]->id + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
dev->maxlun = maxlun;
|
||||
}
|
||||
|
||||
/* This typedef exists to work around an astyle 2.05 bug.
|
||||
* Remove it when astyle is fixed.
|
||||
*/
|
||||
typedef struct spdk_scsi_dev _spdk_scsi_dev;
|
||||
|
||||
_spdk_scsi_dev *
|
||||
spdk_scsi_dev_construct(const char *name, char *lun_name_list[], int *lun_id_list, int num_luns)
|
||||
{
|
||||
struct spdk_scsi_dev *dev;
|
||||
struct spdk_bdev *bdev;
|
||||
struct spdk_scsi_lun *lun;
|
||||
int i;
|
||||
|
||||
if (num_luns == 0) {
|
||||
SPDK_ERRLOG("device %s: no LUNs specified\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lun_id_list[0] != 0) {
|
||||
SPDK_ERRLOG("device %s: no LUN 0 specified\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_luns; i++) {
|
||||
if (lun_name_list[i] == NULL) {
|
||||
SPDK_ERRLOG("NULL spdk_scsi_lun for LUN %d\n",
|
||||
lun_id_list[i]);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dev = allocate_dev();
|
||||
if (dev == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(dev->name, name, SPDK_SCSI_DEV_MAX_NAME);
|
||||
|
||||
dev->num_ports = 0;
|
||||
dev->maxlun = 0;
|
||||
|
||||
for (i = 0; i < num_luns; i++) {
|
||||
bdev = spdk_bdev_db_get_by_name(lun_name_list[i]);
|
||||
if (bdev == NULL) {
|
||||
free_dev(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lun = spdk_scsi_lun_construct(bdev->name, bdev);
|
||||
if (lun == NULL) {
|
||||
free_dev(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spdk_scsi_dev_add_lun(dev, lun, lun_id_list[i]);
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev,
|
||||
struct spdk_scsi_task *task)
|
||||
{
|
||||
assert(task != NULL);
|
||||
|
||||
spdk_scsi_lun_task_mgmt_execute(task);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_dev_queue_task(struct spdk_scsi_dev *dev,
|
||||
struct spdk_scsi_task *task)
|
||||
{
|
||||
assert(task != NULL);
|
||||
|
||||
/* ready to enqueue, disk is valid for LUN access */
|
||||
spdk_scsi_lun_append_task(task->lun, task);
|
||||
spdk_scsi_lun_execute_tasks(task->lun);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_dev_add_port(struct spdk_scsi_dev *dev, uint64_t id, const char *name)
|
||||
{
|
||||
struct spdk_scsi_port *port;
|
||||
int rc;
|
||||
|
||||
if (dev->num_ports == SPDK_SCSI_DEV_MAX_PORTS) {
|
||||
SPDK_ERRLOG("device already has %d ports\n", SPDK_SCSI_DEV_MAX_PORTS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
port = &dev->port[dev->num_ports];
|
||||
|
||||
rc = spdk_scsi_port_construct(port, id, dev->num_ports, name);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
dev->num_ports++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct spdk_scsi_port *
|
||||
spdk_scsi_dev_find_port_by_id(struct spdk_scsi_dev *dev, uint64_t id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->num_ports; i++) {
|
||||
if (dev->port[i].id == id) {
|
||||
return &dev->port[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* No matching port found. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_dev_print(struct spdk_scsi_dev *dev)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
int i;
|
||||
|
||||
printf("device %d HDD UNIT\n", dev->id);
|
||||
|
||||
for (i = 0; i < dev->maxlun; i++) {
|
||||
lun = dev->lun[i];
|
||||
if (lun == NULL)
|
||||
continue;
|
||||
printf("device %d: LUN%d %s\n", dev->id, i, lun->name);
|
||||
}
|
||||
}
|
||||
|
392
lib/scsi/lun.c
Normal file
392
lib/scsi/lun.c
Normal file
@ -0,0 +1,392 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
|
||||
void
|
||||
spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
||||
{
|
||||
if (lun) {
|
||||
spdk_trace_record(TRACE_SCSI_TASK_DONE, lun->dev->id, 0, (uintptr_t)task, 0);
|
||||
}
|
||||
spdk_event_call(task->cb_event);
|
||||
|
||||
if (lun && !TAILQ_EMPTY(&lun->pending_tasks)) {
|
||||
spdk_scsi_lun_execute_tasks(lun);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_lun_clear_all(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
struct spdk_scsi_task *task, *task_tmp;
|
||||
|
||||
/*
|
||||
* This function is called from one location, after the backend LUN
|
||||
* device was reset. Can assume are no active tasks in the
|
||||
* backend that need to be terminated. Just need to queue all tasks
|
||||
* back to frontend for any final processing and cleanup.
|
||||
*
|
||||
* Queue the tasks back roughly in the order they were received
|
||||
* ('cleanup' = oldest, 'tasks' = current, and 'pending' = newest)
|
||||
*/
|
||||
|
||||
TAILQ_FOREACH_SAFE(task, &lun->tasks, scsi_link, task_tmp) {
|
||||
TAILQ_REMOVE(&lun->tasks, task, scsi_link);
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_ABORTED_COMMAND, 0, 0);
|
||||
spdk_scsi_lun_complete_task(lun, task);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) {
|
||||
TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link);
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_ABORTED_COMMAND,
|
||||
0, 0);
|
||||
spdk_scsi_lun_complete_task(lun, task);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_scsi_lun_abort_all(struct spdk_scsi_task *mtask,
|
||||
struct spdk_scsi_lun *lun,
|
||||
struct spdk_scsi_port *initiator_port)
|
||||
{
|
||||
if (!lun) {
|
||||
mtask->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mtask->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_scsi_lun_abort_task(struct spdk_scsi_task *mtask,
|
||||
struct spdk_scsi_lun *lun,
|
||||
struct spdk_scsi_port *initiator_port,
|
||||
uint32_t task_tag)
|
||||
{
|
||||
if (!lun) {
|
||||
/* LUN does not exist */
|
||||
mtask->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mtask->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_scsi_lun_reset(struct spdk_scsi_task *mtask, struct spdk_scsi_lun *lun)
|
||||
{
|
||||
if (!lun) {
|
||||
/* LUN does not exist */
|
||||
mtask->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
|
||||
spdk_scsi_lun_complete_task(NULL, mtask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
spdk_bdev_scsi_reset(lun->bdev, mtask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!task) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (task->function) {
|
||||
case SPDK_SCSI_TASK_FUNC_ABORT_TASK:
|
||||
rc = spdk_scsi_lun_abort_task(task, task->lun,
|
||||
task->initiator_port,
|
||||
task->abort_id);
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("ABORT_TASK failed\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET:
|
||||
rc = spdk_scsi_lun_abort_all(task, task->lun,
|
||||
task->initiator_port);
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("ABORT_TASK_SET failed\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SPDK_SCSI_TASK_FUNC_LUN_RESET:
|
||||
rc = spdk_scsi_lun_reset(task, task->lun);
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("LUN_RESET failed\n");
|
||||
}
|
||||
return rc;
|
||||
|
||||
default:
|
||||
SPDK_ERRLOG("Unknown Task Management Function!\n");
|
||||
/*
|
||||
* Task management functions other than those above should never
|
||||
* reach this point having been filtered by the frontend. Reject
|
||||
* the task as being unsupported.
|
||||
*/
|
||||
task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
spdk_scsi_lun_complete_task(task->lun, task);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
complete_task_with_no_lun(struct spdk_scsi_task *task)
|
||||
{
|
||||
uint8_t *data;
|
||||
uint32_t allocation_len;
|
||||
int data_len;
|
||||
|
||||
if (task->cdb[0] == SPDK_SPC_INQUIRY) {
|
||||
/*
|
||||
* SPC-4 states that INQUIRY commands to an unsupported LUN
|
||||
* must be served with PERIPHERAL QUALIFIER = 0x3 and
|
||||
* PERIPHERAL DEVICE TYPE = 0x1F.
|
||||
*/
|
||||
allocation_len = from_be16(&task->cdb[3]);
|
||||
spdk_scsi_task_alloc_data(task, allocation_len, &data);
|
||||
data_len = 36;
|
||||
memset(data, 0, data_len);
|
||||
/* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
|
||||
data[0] = 0x03 << 5 | 0x1f;
|
||||
/* ADDITIONAL LENGTH */
|
||||
data[4] = data_len - 5;
|
||||
task->data_transferred = (uint64_t)data_len;
|
||||
task->status = SPDK_SCSI_STATUS_GOOD;
|
||||
} else {
|
||||
/* LOGICAL UNIT NOT SUPPORTED */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 0x25, 0x00);
|
||||
task->data_transferred = 0;
|
||||
}
|
||||
spdk_scsi_lun_complete_task(NULL, task);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
||||
{
|
||||
if (lun == NULL) {
|
||||
complete_task_with_no_lun(task);
|
||||
return;
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&lun->pending_tasks, task, scsi_link);
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_lun_execute_tasks(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
struct spdk_scsi_task *task, *task_tmp;
|
||||
int rc;
|
||||
|
||||
TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) {
|
||||
task->status = SPDK_SCSI_STATUS_GOOD;
|
||||
spdk_trace_record(TRACE_SCSI_TASK_START, lun->dev->id, task->length, (uintptr_t)task, 0);
|
||||
rc = spdk_bdev_scsi_execute(lun->bdev, task);
|
||||
|
||||
/* Task is removed from the pending list if it gets the slot. */
|
||||
if (task->status == SPDK_SCSI_STATUS_TASK_SET_FULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link);
|
||||
|
||||
switch (rc) {
|
||||
case SPDK_SCSI_TASK_PENDING:
|
||||
TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
|
||||
break;
|
||||
|
||||
case SPDK_SCSI_TASK_COMPLETE:
|
||||
spdk_scsi_lun_complete_task(lun, task);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
\brief Constructs a new spdk_scsi_lun object based on the provided parameters.
|
||||
|
||||
\param name Name for the SCSI LUN.
|
||||
\param blockdev Blockdev associated with this LUN
|
||||
|
||||
\return NULL if blockdev == NULL
|
||||
\return pointer to the new spdk_scsi_lun object otherwise
|
||||
|
||||
*/
|
||||
_spdk_scsi_lun *
|
||||
spdk_scsi_lun_construct(const char *name, struct spdk_bdev *bdev)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
int rc;
|
||||
|
||||
if (bdev == NULL) {
|
||||
SPDK_ERRLOG("blockdev must be non-NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lun = spdk_lun_db_get_lun(name, 0);
|
||||
if (lun) {
|
||||
return lun;
|
||||
}
|
||||
|
||||
lun = calloc(1, sizeof(*lun));
|
||||
if (lun == NULL) {
|
||||
SPDK_ERRLOG("could not allocate lun\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&lun->tasks);
|
||||
TAILQ_INIT(&lun->pending_tasks);
|
||||
|
||||
lun->bdev = bdev;
|
||||
strncpy(lun->name, name, sizeof(lun->name));
|
||||
|
||||
rc = spdk_scsi_lun_db_add(lun);
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("Unable to add LUN %s to DB\n", lun->name);
|
||||
free(lun);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return lun;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_scsi_lun_destruct(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
spdk_scsi_lun_db_delete(lun);
|
||||
|
||||
free(lun);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_lun_claim(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
struct spdk_scsi_lun *tmp = spdk_lun_db_get_lun(lun->name, 1);
|
||||
|
||||
if (tmp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_lun_unclaim(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
spdk_lun_db_put_lun(lun->name);
|
||||
lun->dev = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_lun_deletable(const char *name)
|
||||
{
|
||||
int ret = 0;
|
||||
struct spdk_scsi_lun *lun;
|
||||
|
||||
pthread_mutex_lock(&g_spdk_scsi.mutex);
|
||||
lun = spdk_lun_db_get_lun(name, 0);
|
||||
if (lun == NULL) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lun->dev == NULL) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
pthread_mutex_unlock(&g_spdk_scsi.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_lun_delete(const char *lun_name)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_dev *dev;
|
||||
struct spdk_lun_db_entry *current;
|
||||
|
||||
pthread_mutex_lock(&g_spdk_scsi.mutex);
|
||||
current = spdk_scsi_lun_list_head;
|
||||
while (current != NULL) {
|
||||
lun = current->lun;
|
||||
if (strncmp(lun->name, lun_name, sizeof(lun->name)) == 0) {
|
||||
break;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (current == NULL) {
|
||||
pthread_mutex_unlock(&g_spdk_scsi.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
dev = lun->dev;
|
||||
|
||||
/* Remove the LUN from the device */
|
||||
if (dev != NULL) {
|
||||
spdk_scsi_dev_delete_lun(dev, lun);
|
||||
}
|
||||
|
||||
/* LUNs are always created in a pair with a blockdev.
|
||||
* Delete the blockdev associated with this lun.
|
||||
*/
|
||||
spdk_bdev_unregister(lun->bdev);
|
||||
|
||||
/* Destroy this lun */
|
||||
spdk_scsi_lun_destruct(lun);
|
||||
pthread_mutex_unlock(&g_spdk_scsi.mutex);
|
||||
}
|
120
lib/scsi/lun_db.c
Normal file
120
lib/scsi/lun_db.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
|
||||
struct spdk_lun_db_entry *spdk_scsi_lun_list_head = NULL;
|
||||
|
||||
int
|
||||
spdk_scsi_lun_db_add(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
struct spdk_lun_db_entry *new_entry = calloc(1, sizeof(struct spdk_lun_db_entry));
|
||||
|
||||
if (!new_entry) {
|
||||
SPDK_ERRLOG("Failed to allocate DB entry\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
new_entry->lun = lun;
|
||||
new_entry->next = spdk_scsi_lun_list_head;
|
||||
spdk_scsi_lun_list_head = new_entry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_lun_db_delete(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
struct spdk_lun_db_entry *prev = NULL;
|
||||
struct spdk_lun_db_entry *node = spdk_scsi_lun_list_head;
|
||||
|
||||
while (node != NULL) {
|
||||
if (node->lun == lun) {
|
||||
if (prev != NULL) {
|
||||
prev->next = node->next;
|
||||
} else {
|
||||
spdk_scsi_lun_list_head = node->next;
|
||||
}
|
||||
free(node);
|
||||
break;
|
||||
}
|
||||
prev = node;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct spdk_scsi_lun *
|
||||
spdk_lun_db_get_lun(const char *lun_name, int claim_flag)
|
||||
{
|
||||
struct spdk_lun_db_entry *current = spdk_scsi_lun_list_head;
|
||||
|
||||
while (current != NULL) {
|
||||
struct spdk_scsi_lun *lun = current->lun;
|
||||
|
||||
if (strncmp(lun_name, lun->name, sizeof(lun->name)) == 0) {
|
||||
if (claim_flag) {
|
||||
if (current->claimed == 1)
|
||||
return NULL;
|
||||
else {
|
||||
current->claimed = 1;
|
||||
return lun;
|
||||
}
|
||||
}
|
||||
return lun;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_lun_db_put_lun(const char *lun_name)
|
||||
{
|
||||
struct spdk_lun_db_entry *current = spdk_scsi_lun_list_head;
|
||||
|
||||
while (current != NULL) {
|
||||
struct spdk_scsi_lun *lun = current->lun;
|
||||
|
||||
if (strncmp(lun_name, lun->name, sizeof(lun->name)) == 0) {
|
||||
current->claimed = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
}
|
50
lib/scsi/port.c
Normal file
50
lib/scsi/port.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
|
||||
int
|
||||
spdk_scsi_port_construct(struct spdk_scsi_port *port, uint64_t id, uint16_t index,
|
||||
const char *name)
|
||||
{
|
||||
if (strlen(name) > sizeof(port->name)) {
|
||||
SPDK_ERRLOG("port name too long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
port->id = id;
|
||||
port->index = index;
|
||||
strncpy(port->name, name, sizeof(port->name));
|
||||
return 0;
|
||||
}
|
149
lib/scsi/scsi.c
Normal file
149
lib/scsi/scsi.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
|
||||
#include "spdk/event.h"
|
||||
#include "spdk/conf.h"
|
||||
|
||||
#define DEFAULT_MAX_UNMAP_LBA_COUNT 4194304
|
||||
#define DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT 1
|
||||
#define DEFAULT_OPTIMAL_UNMAP_GRANULARITY 0
|
||||
#define DEFAULT_UNMAP_GRANULARITY_ALIGNMENT 0
|
||||
#define DEFAULT_UGAVALID 0
|
||||
#define DEFAULT_MAX_WRITE_SAME_LENGTH 512
|
||||
|
||||
struct spdk_scsi_globals g_spdk_scsi;
|
||||
|
||||
static void
|
||||
spdk_set_default_scsi_parameters(void)
|
||||
{
|
||||
g_spdk_scsi.scsi_params.max_unmap_lba_count = DEFAULT_MAX_UNMAP_LBA_COUNT;
|
||||
g_spdk_scsi.scsi_params.max_unmap_block_descriptor_count =
|
||||
DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT;
|
||||
g_spdk_scsi.scsi_params.optimal_unmap_granularity =
|
||||
DEFAULT_OPTIMAL_UNMAP_GRANULARITY;
|
||||
g_spdk_scsi.scsi_params.unmap_granularity_alignment =
|
||||
DEFAULT_UNMAP_GRANULARITY_ALIGNMENT;
|
||||
g_spdk_scsi.scsi_params.ugavalid = DEFAULT_UGAVALID;
|
||||
g_spdk_scsi.scsi_params.max_write_same_length = DEFAULT_MAX_WRITE_SAME_LENGTH;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_read_config_scsi_parameters(void)
|
||||
{
|
||||
struct spdk_conf_section *sp;
|
||||
const char *val;
|
||||
|
||||
sp = spdk_conf_find_section(NULL, "Scsi");
|
||||
if (sp == NULL) {
|
||||
spdk_set_default_scsi_parameters();
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = spdk_conf_section_get_val(sp, "MaxUnmapLbaCount");
|
||||
g_spdk_scsi.scsi_params.max_unmap_lba_count = (val == NULL) ?
|
||||
DEFAULT_MAX_UNMAP_LBA_COUNT : strtoul(val, NULL, 10);
|
||||
|
||||
val = spdk_conf_section_get_val(sp, "MaxUnmapBlockDescriptorCount");
|
||||
g_spdk_scsi.scsi_params.max_unmap_block_descriptor_count = (val == NULL) ?
|
||||
DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT : strtoul(val, NULL, 10);
|
||||
val = spdk_conf_section_get_val(sp, "OptimalUnmapGranularity");
|
||||
g_spdk_scsi.scsi_params.optimal_unmap_granularity = (val == NULL) ?
|
||||
DEFAULT_OPTIMAL_UNMAP_GRANULARITY : strtoul(val, NULL, 10);
|
||||
|
||||
val = spdk_conf_section_get_val(sp, "UnmapGranularityAlignment");
|
||||
g_spdk_scsi.scsi_params.unmap_granularity_alignment = (val == NULL) ?
|
||||
DEFAULT_UNMAP_GRANULARITY_ALIGNMENT : strtoul(val, NULL, 10);
|
||||
|
||||
val = spdk_conf_section_get_val(sp, "Ugavalid");
|
||||
if (val == NULL) {
|
||||
g_spdk_scsi.scsi_params.ugavalid = DEFAULT_UGAVALID;
|
||||
} else if (strcasecmp(val, "Yes") == 0) {
|
||||
g_spdk_scsi.scsi_params.ugavalid = 1;
|
||||
} else if (strcasecmp(val, "No") == 0) {
|
||||
g_spdk_scsi.scsi_params.ugavalid = 0;
|
||||
} else {
|
||||
SPDK_ERRLOG("unknown value %s\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = spdk_conf_section_get_val(sp, "MaxWriteSameLength");
|
||||
g_spdk_scsi.scsi_params.max_write_same_length = (val == NULL) ?
|
||||
DEFAULT_MAX_WRITE_SAME_LENGTH : strtoul(val, NULL, 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_scsi_subsystem_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pthread_mutex_init(&g_spdk_scsi.mutex, NULL);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("mutex_init() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = spdk_read_config_scsi_parameters();
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("spdk_scsi_parameters() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_scsi_subsystem_fini(void)
|
||||
{
|
||||
pthread_mutex_destroy(&g_spdk_scsi.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPDK_TRACE_REGISTER_FN(scsi_trace)
|
||||
{
|
||||
spdk_trace_register_owner(OWNER_SCSI_DEV, 'd');
|
||||
spdk_trace_register_object(OBJECT_SCSI_TASK, 't');
|
||||
spdk_trace_register_description("SCSI TASK DONE", "", TRACE_SCSI_TASK_DONE,
|
||||
OWNER_SCSI_DEV, OBJECT_SCSI_TASK, 0, 0, 0, "");
|
||||
spdk_trace_register_description("SCSI TASK START", "", TRACE_SCSI_TASK_START,
|
||||
OWNER_SCSI_DEV, OBJECT_SCSI_TASK, 0, 0, 0, "");
|
||||
}
|
||||
|
||||
SPDK_SUBSYSTEM_REGISTER(scsi, spdk_scsi_subsystem_init, spdk_scsi_subsystem_fini, NULL)
|
||||
SPDK_SUBSYSTEM_DEPEND(scsi, bdev)
|
||||
|
||||
SPDK_LOG_REGISTER_TRACE_FLAG("scsi", SPDK_TRACE_SCSI)
|
1851
lib/scsi/scsi_bdev.c
Normal file
1851
lib/scsi/scsi_bdev.c
Normal file
File diff suppressed because it is too large
Load Diff
230
lib/scsi/scsi_internal.h
Normal file
230
lib/scsi/scsi_internal.h
Normal file
@ -0,0 +1,230 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SPDK_SCSI_INTERNAL_H
|
||||
#define SPDK_SCSI_INTERNAL_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "spdk/bdev.h"
|
||||
#include "spdk/bdev_db.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/scsi.h"
|
||||
#include "spdk/scsi_spec.h"
|
||||
#include "spdk/trace.h"
|
||||
|
||||
enum {
|
||||
SPDK_SCSI_TASK_UNKNOWN = -1,
|
||||
SPDK_SCSI_TASK_COMPLETE,
|
||||
SPDK_SCSI_TASK_PENDING,
|
||||
};
|
||||
|
||||
/*
|
||||
* SAM does not define the value for these service responses. Each transport
|
||||
* (i.e. SAS, FC, iSCSI) will map these value to transport-specific codes,
|
||||
* and may add their own.
|
||||
*/
|
||||
enum spdk_scsi_task_mgmt_resp {
|
||||
SPDK_SCSI_TASK_MGMT_RESP_COMPLETE,
|
||||
SPDK_SCSI_TASK_MGMT_RESP_SUCCESS,
|
||||
SPDK_SCSI_TASK_MGMT_RESP_REJECT,
|
||||
SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN,
|
||||
SPDK_SCSI_TASK_MGMT_RESP_TARGET_FAILURE,
|
||||
SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED
|
||||
};
|
||||
|
||||
#define OWNER_SCSI_DEV 0x10
|
||||
|
||||
#define OBJECT_SCSI_TASK 0x10
|
||||
|
||||
#define TRACE_GROUP_SCSI 0x2
|
||||
#define TRACE_SCSI_TASK_DONE SPDK_TPOINT_ID(TRACE_GROUP_SCSI, 0x0)
|
||||
#define TRACE_SCSI_TASK_START SPDK_TPOINT_ID(TRACE_GROUP_SCSI, 0x1)
|
||||
|
||||
/**
|
||||
|
||||
\brief Represents a SCSI LUN.
|
||||
|
||||
LUN modules will implement the function pointers specifically for the LUN
|
||||
type. For example, NVMe LUNs will implement scsi_execute to translate
|
||||
the SCSI task to an NVMe command and post it to the NVMe controller.
|
||||
malloc LUNs will implement scsi_execute to translate the SCSI task and
|
||||
copy the task's data into or out of the allocated memory buffer.
|
||||
|
||||
*/
|
||||
struct spdk_scsi_lun {
|
||||
/** LUN id for this logical unit. */
|
||||
int id;
|
||||
|
||||
/** Pointer to the SCSI device containing this LUN. */
|
||||
struct spdk_scsi_dev *dev;
|
||||
|
||||
/** The blockdev associated with this LUN. */
|
||||
struct spdk_bdev *bdev;
|
||||
|
||||
/** Name for this LUN. */
|
||||
char name[SPDK_SCSI_LUN_MAX_NAME_LENGTH];
|
||||
|
||||
TAILQ_HEAD(tasks, spdk_scsi_task) tasks; /* submitted tasks */
|
||||
TAILQ_HEAD(pending_tasks, spdk_scsi_task) pending_tasks; /* pending tasks */
|
||||
};
|
||||
|
||||
struct spdk_lun_db_entry {
|
||||
struct spdk_scsi_lun *lun;
|
||||
int claimed;
|
||||
struct spdk_lun_db_entry *next;
|
||||
};
|
||||
|
||||
extern struct spdk_lun_db_entry *spdk_scsi_lun_list_head;
|
||||
|
||||
/* This typedef exists to work around an astyle 2.05 bug.
|
||||
* Remove it when astyle is fixed.
|
||||
*/
|
||||
typedef struct spdk_scsi_lun _spdk_scsi_lun;
|
||||
|
||||
_spdk_scsi_lun *spdk_scsi_lun_construct(const char *name, struct spdk_bdev *bdev);
|
||||
|
||||
void spdk_scsi_lun_clear_all(struct spdk_scsi_lun *lun);
|
||||
void spdk_scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task);
|
||||
void spdk_scsi_lun_execute_tasks(struct spdk_scsi_lun *lun);
|
||||
int spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task);
|
||||
void spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task);
|
||||
int spdk_scsi_lun_claim(struct spdk_scsi_lun *lun);
|
||||
int spdk_scsi_lun_unclaim(struct spdk_scsi_lun *lun);
|
||||
int spdk_scsi_lun_deletable(const char *name);
|
||||
void spdk_scsi_lun_delete(const char *lun_name);
|
||||
|
||||
int spdk_scsi_lun_db_add(struct spdk_scsi_lun *lun);
|
||||
int spdk_scsi_lun_db_delete(struct spdk_scsi_lun *lun);
|
||||
|
||||
struct spdk_scsi_lun *spdk_lun_db_get_lun(const char *lun_name, int claim_flag);
|
||||
void spdk_lun_db_put_lun(const char *lun_name);
|
||||
|
||||
struct spdk_scsi_dev *spdk_scsi_dev_get_list(void);
|
||||
|
||||
int spdk_bdev_scsi_execute(struct spdk_bdev *bdev, struct spdk_scsi_task *task);
|
||||
int spdk_bdev_scsi_reset(struct spdk_bdev *bdev, struct spdk_scsi_task *task);
|
||||
|
||||
static inline uint16_t
|
||||
from_be16(void *ptr)
|
||||
{
|
||||
uint8_t *tmp = (uint8_t *)ptr;
|
||||
return (((uint16_t)tmp[0] << 8) | tmp[1]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
to_be16(void *out, uint16_t in)
|
||||
{
|
||||
uint8_t *tmp = (uint8_t *)out;
|
||||
tmp[0] = (in >> 8) & 0xFF;
|
||||
tmp[1] = in & 0xFF;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
from_be32(void *ptr)
|
||||
{
|
||||
uint8_t *tmp = (uint8_t *)ptr;
|
||||
return (((uint32_t)tmp[0] << 24) |
|
||||
((uint32_t)tmp[1] << 16) |
|
||||
((uint32_t)tmp[2] << 8) |
|
||||
((uint32_t)tmp[3]));
|
||||
}
|
||||
|
||||
static inline void
|
||||
to_be32(void *out, uint32_t in)
|
||||
{
|
||||
uint8_t *tmp = (uint8_t *)out;
|
||||
tmp[0] = (in >> 24) & 0xFF;
|
||||
tmp[1] = (in >> 16) & 0xFF;
|
||||
tmp[2] = (in >> 8) & 0xFF;
|
||||
tmp[3] = in & 0xFF;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
from_be64(void *ptr)
|
||||
{
|
||||
uint8_t *tmp = (uint8_t *)ptr;
|
||||
return (((uint64_t)tmp[0] << 56) |
|
||||
((uint64_t)tmp[1] << 48) |
|
||||
((uint64_t)tmp[2] << 40) |
|
||||
((uint64_t)tmp[3] << 32) |
|
||||
((uint64_t)tmp[4] << 24) |
|
||||
((uint64_t)tmp[5] << 16) |
|
||||
((uint64_t)tmp[6] << 8) |
|
||||
((uint64_t)tmp[7]));
|
||||
}
|
||||
|
||||
static inline void
|
||||
to_be64(void *out, uint64_t in)
|
||||
{
|
||||
uint8_t *tmp = (uint8_t *)out;
|
||||
tmp[0] = (in >> 56) & 0xFF;
|
||||
tmp[1] = (in >> 48) & 0xFF;
|
||||
tmp[2] = (in >> 40) & 0xFF;
|
||||
tmp[3] = (in >> 32) & 0xFF;
|
||||
tmp[4] = (in >> 24) & 0xFF;
|
||||
tmp[5] = (in >> 16) & 0xFF;
|
||||
tmp[6] = (in >> 8) & 0xFF;
|
||||
tmp[7] = in & 0xFF;
|
||||
};
|
||||
|
||||
struct spdk_scsi_parameters {
|
||||
uint32_t max_unmap_lba_count;
|
||||
uint32_t max_unmap_block_descriptor_count;
|
||||
uint32_t optimal_unmap_granularity;
|
||||
uint32_t unmap_granularity_alignment;
|
||||
uint32_t ugavalid;
|
||||
uint64_t max_write_same_length;
|
||||
};
|
||||
|
||||
struct spdk_scsi_globals {
|
||||
pthread_mutex_t mutex;
|
||||
struct spdk_scsi_parameters scsi_params;
|
||||
};
|
||||
|
||||
extern struct spdk_scsi_globals g_spdk_scsi;
|
||||
|
||||
#endif /* SPDK_SCSI_INTERNAL_H */
|
174
lib/scsi/scsi_rpc.c
Normal file
174
lib/scsi/scsi_rpc.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
|
||||
#include "spdk/rpc.h"
|
||||
|
||||
static void
|
||||
spdk_rpc_get_luns(struct spdk_jsonrpc_server_conn *conn,
|
||||
const struct spdk_json_val *params,
|
||||
const struct spdk_json_val *id)
|
||||
{
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_lun_db_entry *current;
|
||||
|
||||
if (params != NULL) {
|
||||
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"get_luns requires no parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(conn, id);
|
||||
spdk_json_write_array_begin(w);
|
||||
|
||||
current = spdk_scsi_lun_list_head;
|
||||
while (current != NULL) {
|
||||
struct spdk_scsi_lun *lun = current->lun;
|
||||
|
||||
spdk_json_write_object_begin(w);
|
||||
spdk_json_write_name(w, "claimed");
|
||||
spdk_json_write_bool(w, current->claimed);
|
||||
spdk_json_write_name(w, "name");
|
||||
spdk_json_write_string(w, lun->name);
|
||||
spdk_json_write_object_end(w);
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
spdk_json_write_array_end(w);
|
||||
|
||||
spdk_jsonrpc_end_result(conn, w);
|
||||
}
|
||||
SPDK_RPC_REGISTER("get_luns", spdk_rpc_get_luns)
|
||||
|
||||
struct rpc_delete_lun {
|
||||
char *name;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_delete_lun(struct rpc_delete_lun *r)
|
||||
{
|
||||
free(r->name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_delete_lun_decoders[] = {
|
||||
{"name", offsetof(struct rpc_delete_lun, name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
spdk_rpc_delete_lun(struct spdk_jsonrpc_server_conn *conn,
|
||||
const struct spdk_json_val *params,
|
||||
const struct spdk_json_val *id)
|
||||
{
|
||||
struct rpc_delete_lun req = {};
|
||||
struct spdk_json_write_ctx *w;
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_delete_lun_decoders,
|
||||
sizeof(rpc_delete_lun_decoders) / sizeof(*rpc_delete_lun_decoders),
|
||||
&req)) {
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n");
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (spdk_scsi_lun_deletable(req.name)) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
spdk_scsi_lun_delete(req.name);
|
||||
free_rpc_delete_lun(&req);
|
||||
|
||||
if (id == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(conn, id);
|
||||
spdk_json_write_bool(w, true);
|
||||
spdk_jsonrpc_end_result(conn, w);
|
||||
return;
|
||||
|
||||
invalid:
|
||||
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
||||
free_rpc_delete_lun(&req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("delete_lun", spdk_rpc_delete_lun)
|
||||
|
||||
static void
|
||||
spdk_rpc_get_scsi_devices(struct spdk_jsonrpc_server_conn *conn,
|
||||
const struct spdk_json_val *params,
|
||||
const struct spdk_json_val *id)
|
||||
{
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_scsi_dev *devs = spdk_scsi_dev_get_list();
|
||||
int i;
|
||||
|
||||
if (params != NULL) {
|
||||
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"get_scsi_devices requires no parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(conn, id);
|
||||
spdk_json_write_array_begin(w);
|
||||
|
||||
for (i = 0; i < SPDK_SCSI_MAX_DEVS; i++) {
|
||||
struct spdk_scsi_dev *dev = &devs[i];
|
||||
|
||||
if (!dev->is_allocated) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spdk_json_write_object_begin(w);
|
||||
|
||||
spdk_json_write_name(w, "id");
|
||||
spdk_json_write_int32(w, dev->id);
|
||||
|
||||
spdk_json_write_name(w, "device_name");
|
||||
spdk_json_write_string(w, dev->name);
|
||||
|
||||
spdk_json_write_object_end(w);
|
||||
}
|
||||
spdk_json_write_array_end(w);
|
||||
|
||||
spdk_jsonrpc_end_result(conn, w);
|
||||
}
|
||||
SPDK_RPC_REGISTER("get_scsi_devices", spdk_rpc_get_scsi_devices)
|
194
lib/scsi/task.c
Normal file
194
lib/scsi/task.c
Normal file
@ -0,0 +1,194 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
|
||||
#include <rte_config.h>
|
||||
#include <rte_debug.h>
|
||||
#include <rte_malloc.h>
|
||||
|
||||
void
|
||||
spdk_put_task(struct spdk_scsi_task *task)
|
||||
{
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
|
||||
task->ref--;
|
||||
|
||||
if (task->ref == 0) {
|
||||
struct spdk_bdev_io *bdev_io = task->blockdev_io;
|
||||
|
||||
if (task->parent) {
|
||||
spdk_put_task(task->parent);
|
||||
task->parent = NULL;
|
||||
}
|
||||
|
||||
if (bdev_io) {
|
||||
/* due to lun reset, the bdev_io status could be pending */
|
||||
if (bdev_io->status == SPDK_BDEV_IO_STATUS_PENDING) {
|
||||
bdev_io->status = SPDK_BDEV_IO_STATUS_FAILED;
|
||||
}
|
||||
spdk_bdev_free_io(bdev_io);
|
||||
} else {
|
||||
rte_free(task->rbuf);
|
||||
}
|
||||
|
||||
task->rbuf = NULL;
|
||||
|
||||
RTE_VERIFY(task->owner_task_ctr != NULL);
|
||||
if (*(task->owner_task_ctr) > 0) {
|
||||
*(task->owner_task_ctr) -= 1;
|
||||
} else {
|
||||
SPDK_ERRLOG("task counter already 0\n");
|
||||
}
|
||||
|
||||
task->free_fn(task);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_construct(struct spdk_scsi_task *task, uint32_t *owner_task_ctr,
|
||||
struct spdk_scsi_task *parent)
|
||||
{
|
||||
task->ref++;
|
||||
|
||||
RTE_VERIFY(owner_task_ctr != NULL);
|
||||
task->owner_task_ctr = owner_task_ctr;
|
||||
*owner_task_ctr += 1;
|
||||
|
||||
if (parent != NULL) {
|
||||
parent->ref++;
|
||||
task->parent = parent;
|
||||
task->type = parent->type;
|
||||
task->dxfer_dir = parent->dxfer_dir;
|
||||
task->transfer_len = parent->transfer_len;
|
||||
task->lun = parent->lun;
|
||||
task->cdb = parent->cdb;
|
||||
task->target_port = parent->target_port;
|
||||
task->initiator_port = parent->initiator_port;
|
||||
task->id = parent->id;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
|
||||
uint8_t **data)
|
||||
{
|
||||
/*
|
||||
* SPDK iSCSI target depends on allocating at least 4096 bytes, even if
|
||||
* the command requested less. The individual command code (for
|
||||
* example, INQUIRY) will fill out up to 4096 bytes of data, ignoring
|
||||
* the allocation length specified in the command. After the individual
|
||||
* command functions are done, spdk_scsi_lun_execute_tasks() takes
|
||||
* care of only sending back the amount of data specified in the
|
||||
* allocation length.
|
||||
*/
|
||||
if (alloc_len < 4096) {
|
||||
alloc_len = 4096;
|
||||
}
|
||||
|
||||
task->alloc_len = alloc_len;
|
||||
if (task->rbuf == NULL) {
|
||||
task->rbuf = rte_malloc(NULL, alloc_len, 0);
|
||||
}
|
||||
*data = task->rbuf;
|
||||
memset(task->rbuf, 0, task->alloc_len);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc, int ascq)
|
||||
{
|
||||
uint8_t *data;
|
||||
uint8_t *cp;
|
||||
int resp_code;
|
||||
int hlen = 0, len, plen;
|
||||
int total;
|
||||
|
||||
data = task->sense_data;
|
||||
resp_code = 0x70; /* Current + Fixed format */
|
||||
|
||||
/* SenseLength */
|
||||
memset(data, 0, 2);
|
||||
hlen = 2;
|
||||
|
||||
/* Sense Data */
|
||||
cp = &data[hlen];
|
||||
|
||||
/* 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] = 0;
|
||||
len = 8;
|
||||
|
||||
/* 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;
|
||||
/* Additional sense bytes */
|
||||
plen = 18 - len;
|
||||
|
||||
/* ADDITIONAL SENSE LENGTH */
|
||||
cp[7] = plen;
|
||||
|
||||
total = hlen + len + plen;
|
||||
|
||||
/* SenseLength */
|
||||
to_be16(data, total - 2);
|
||||
task->sense_data_len = total;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk, int asc, int ascq)
|
||||
{
|
||||
spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
|
||||
task->status = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
@ -34,7 +34,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y = bdev event log json jsonrpc nvme nvmf memory ioat
|
||||
DIRS-y = bdev event log json jsonrpc nvme nvmf memory scsi ioat
|
||||
|
||||
.PHONY: all clean $(DIRS-y)
|
||||
|
||||
|
44
test/lib/scsi/Makefile
Normal file
44
test/lib/scsi/Makefile
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y = dev lun scsi_bdev
|
||||
|
||||
.PHONY: all clean $(DIRS-y)
|
||||
|
||||
all: $(DIRS-y)
|
||||
clean: $(DIRS-y)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.subdirs.mk
|
1
test/lib/scsi/dev/.gitignore
vendored
Normal file
1
test/lib/scsi/dev/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dev_ut
|
54
test/lib/scsi/dev/Makefile
Normal file
54
test/lib/scsi/dev/Makefile
Normal file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
SPDK_LIBS += $(SPDK_ROOT_DIR)/lib/log/libspdk_log.a
|
||||
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib/scsi
|
||||
LIBS += $(SPDK_LIBS)
|
||||
LIBS += -lcunit
|
||||
|
||||
APP = dev_ut
|
||||
C_SRCS = dev_ut.c
|
||||
|
||||
all: $(APP)
|
||||
|
||||
$(APP): $(OBJS) $(SPDK_LIBS)
|
||||
$(LINK_C)
|
||||
|
||||
clean:
|
||||
$(CLEAN_C) $(APP)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk
|
494
test/lib/scsi/dev/dev_ut.c
Normal file
494
test/lib/scsi/dev/dev_ut.c
Normal file
@ -0,0 +1,494 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "CUnit/Basic.h"
|
||||
|
||||
#include "dev.c"
|
||||
#include "port.c"
|
||||
|
||||
static uint32_t g_task_count = 0;
|
||||
static struct spdk_scsi_lun g_lun = {};
|
||||
static struct spdk_bdev g_bdev = {};
|
||||
|
||||
void
|
||||
spdk_bdev_unregister(struct spdk_bdev *bdev)
|
||||
{
|
||||
}
|
||||
|
||||
static struct spdk_scsi_task *
|
||||
spdk_get_task(uint32_t *owner_task_ctr)
|
||||
{
|
||||
struct spdk_scsi_task *task;
|
||||
|
||||
task = calloc(1, sizeof(*task));
|
||||
if (!task) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
task->id = g_task_count;
|
||||
|
||||
g_task_count++;
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_put_task(struct spdk_scsi_task *task)
|
||||
{
|
||||
g_task_count--;
|
||||
|
||||
free(task);
|
||||
}
|
||||
|
||||
_spdk_scsi_lun *
|
||||
spdk_scsi_lun_construct(const char *name, struct spdk_bdev *bdev)
|
||||
{
|
||||
snprintf(g_lun.name, sizeof(g_lun.name), "%s", name);
|
||||
g_lun.bdev = bdev;
|
||||
return &g_lun;
|
||||
}
|
||||
|
||||
struct spdk_bdev *
|
||||
spdk_bdev_db_get_by_name(const char *bdev_name)
|
||||
{
|
||||
snprintf(g_bdev.name, sizeof(g_bdev.name), "%s", bdev_name);
|
||||
return &g_bdev;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_lun_claim(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_lun_unclaim(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_lun_execute_tasks(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dev_destruct_null_dev(void)
|
||||
{
|
||||
/* pass null for the dev */
|
||||
spdk_scsi_dev_destruct(NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_destruct_zero_luns(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
|
||||
/* pass maxlun as 0.
|
||||
* No luns attached to the dev */
|
||||
dev.maxlun = 0;
|
||||
|
||||
/* free the dev */
|
||||
spdk_scsi_dev_destruct(&dev);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_destruct_null_lun(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
|
||||
dev.maxlun = 1;
|
||||
/* pass null for the lun */
|
||||
dev.lun[0] = NULL;
|
||||
|
||||
/* free the dev */
|
||||
spdk_scsi_dev_destruct(&dev);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_destruct_success(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
struct spdk_scsi_lun lun = { 0 };
|
||||
|
||||
/* dev with a single lun */
|
||||
dev.maxlun = 1;
|
||||
dev.lun[0] = &lun;
|
||||
|
||||
/* free the dev */
|
||||
spdk_scsi_dev_destruct(&dev);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_construct_num_luns_zero(void)
|
||||
{
|
||||
struct spdk_scsi_dev *dev;
|
||||
char *lun_name_list[1] = {};
|
||||
int lun_id_list[1] = { 0 };
|
||||
|
||||
dev = spdk_scsi_dev_construct("Name", lun_name_list, lun_id_list, 0);
|
||||
|
||||
/* dev should be null since we passed num_luns = 0 */
|
||||
CU_ASSERT_TRUE(dev == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_construct_no_lun_zero(void)
|
||||
{
|
||||
struct spdk_scsi_dev *dev;
|
||||
char *lun_name_list[1] = {};
|
||||
int lun_id_list[1] = { 0 };
|
||||
|
||||
lun_id_list[0] = 1;
|
||||
|
||||
dev = spdk_scsi_dev_construct("Name", lun_name_list, lun_id_list, 1);
|
||||
|
||||
/* dev should be null since no LUN0 was specified (lun_id_list[0] = 1) */
|
||||
CU_ASSERT_TRUE(dev == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_construct_null_lun(void)
|
||||
{
|
||||
struct spdk_scsi_dev *dev;
|
||||
char *lun_name_list[1] = {};
|
||||
int lun_id_list[1] = { 0 };
|
||||
|
||||
dev = spdk_scsi_dev_construct("Name", lun_name_list, lun_id_list, 1);
|
||||
|
||||
/* dev should be null since no LUN0 was specified (lun_list[0] = NULL) */
|
||||
CU_ASSERT_TRUE(dev == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_construct_success(void)
|
||||
{
|
||||
struct spdk_scsi_dev *dev;
|
||||
char *lun_name_list[1] = {"malloc0"};
|
||||
int lun_id_list[1] = { 0 };
|
||||
|
||||
dev = spdk_scsi_dev_construct("Name", lun_name_list, lun_id_list, 1);
|
||||
|
||||
/* Successfully constructs and returns a dev */
|
||||
CU_ASSERT_TRUE(dev != NULL);
|
||||
|
||||
/* free the dev */
|
||||
spdk_scsi_dev_destruct(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_queue_mgmt_task_success(void)
|
||||
{
|
||||
struct spdk_scsi_dev *dev;
|
||||
char *lun_name_list[1] = {"malloc0"};
|
||||
int lun_id_list[1] = { 0 };
|
||||
struct spdk_scsi_task *task;
|
||||
|
||||
dev = spdk_scsi_dev_construct("Name", lun_name_list, lun_id_list, 1);
|
||||
|
||||
/* Successfully constructs and returns a dev */
|
||||
CU_ASSERT_TRUE(dev != NULL);
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
|
||||
spdk_scsi_dev_queue_mgmt_task(dev, task);
|
||||
|
||||
spdk_put_task(task);
|
||||
|
||||
spdk_scsi_dev_destruct(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_queue_task_success(void)
|
||||
{
|
||||
struct spdk_scsi_dev *dev;
|
||||
char *lun_name_list[1] = {"malloc0"};
|
||||
int lun_id_list[1] = { 0 };
|
||||
struct spdk_scsi_task *task;
|
||||
|
||||
dev = spdk_scsi_dev_construct("Name", lun_name_list, lun_id_list, 1);
|
||||
|
||||
/* Successfully constructs and returns a dev */
|
||||
CU_ASSERT_TRUE(dev != NULL);
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
|
||||
spdk_scsi_dev_queue_task(dev, task);
|
||||
|
||||
spdk_put_task(task);
|
||||
|
||||
spdk_scsi_dev_destruct(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_stop_success(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
struct spdk_scsi_task *task;
|
||||
struct spdk_scsi_task *task_mgmt;
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
|
||||
spdk_scsi_dev_queue_task(&dev, task);
|
||||
|
||||
task_mgmt = spdk_get_task(NULL);
|
||||
|
||||
/* Enqueue the tasks into dev->task_mgmt_submit_queue*/
|
||||
spdk_scsi_dev_queue_mgmt_task(&dev, task_mgmt);
|
||||
|
||||
spdk_put_task(task);
|
||||
spdk_put_task(task_mgmt);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_add_port_max_ports(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
const char *name;
|
||||
int id, rc;
|
||||
|
||||
/* dev is set to SPDK_SCSI_DEV_MAX_PORTS */
|
||||
dev.num_ports = SPDK_SCSI_DEV_MAX_PORTS;
|
||||
name = "Name of Port";
|
||||
id = 1;
|
||||
|
||||
rc = spdk_scsi_dev_add_port(&dev, id, name);
|
||||
|
||||
/* returns -1; since the dev already has maximum
|
||||
* number of ports (SPDK_SCSI_DEV_MAX_PORTS) */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_add_port_construct_failure(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
const int port_name_length = SPDK_SCSI_PORT_MAX_NAME_LENGTH + 2;
|
||||
char name[port_name_length];
|
||||
int id, rc;
|
||||
|
||||
dev.num_ports = 1;
|
||||
/* Set the name such that the length exceeds SPDK_SCSI_PORT_MAX_NAME_LENGTH
|
||||
* SPDK_SCSI_PORT_MAX_NAME_LENGTH = 256 */
|
||||
memset(name, 'a', port_name_length - 1);
|
||||
name[port_name_length - 1] = '\0';
|
||||
id = 1;
|
||||
|
||||
rc = spdk_scsi_dev_add_port(&dev, id, name);
|
||||
|
||||
/* returns -1; since the length of the name exceeds
|
||||
* SPDK_SCSI_PORT_MAX_NAME_LENGTH */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_add_port_success(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
const char *name;
|
||||
int id, rc;
|
||||
|
||||
dev.num_ports = 1;
|
||||
name = "Name of Port";
|
||||
id = 1;
|
||||
|
||||
rc = spdk_scsi_dev_add_port(&dev, id, name);
|
||||
|
||||
/* successfully adds a port */
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
/* Assert num_ports has been incremented to 2 */
|
||||
CU_ASSERT_EQUAL(dev.num_ports, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_find_port_by_id_num_ports_zero(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
struct spdk_scsi_port *rp_port;
|
||||
uint64_t id;
|
||||
|
||||
dev.num_ports = 0;
|
||||
id = 1;
|
||||
|
||||
rp_port = spdk_scsi_dev_find_port_by_id(&dev, id);
|
||||
|
||||
/* returns null; since dev's num_ports is 0 */
|
||||
CU_ASSERT_TRUE(rp_port == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_find_port_by_id_id_not_found_failure(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
struct spdk_scsi_port *rp_port;
|
||||
const char *name;
|
||||
int rc;
|
||||
uint64_t id, find_id;
|
||||
|
||||
id = 1;
|
||||
dev.num_ports = 1;
|
||||
name = "Name of Port";
|
||||
find_id = 2;
|
||||
|
||||
/* Add a port with id = 1 */
|
||||
rc = spdk_scsi_dev_add_port(&dev, id, name);
|
||||
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
/* Find port with id = 2 */
|
||||
rp_port = spdk_scsi_dev_find_port_by_id(&dev, find_id);
|
||||
|
||||
/* returns null; failed to find port specified by id = 2 */
|
||||
CU_ASSERT_TRUE(rp_port == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_find_port_by_id_success(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
struct spdk_scsi_port *rp_port;
|
||||
const char *name;
|
||||
int rc;
|
||||
uint64_t id;
|
||||
|
||||
id = 1;
|
||||
dev.num_ports = 1;
|
||||
name = "Name of Port";
|
||||
|
||||
/* Add a port */
|
||||
rc = spdk_scsi_dev_add_port(&dev, id, name);
|
||||
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
/* Find port by the same id as the one added above */
|
||||
rp_port = spdk_scsi_dev_find_port_by_id(&dev, id);
|
||||
|
||||
/* Successfully found port specified by id */
|
||||
CU_ASSERT_TRUE(rp_port != NULL);
|
||||
if (rp_port != NULL) {
|
||||
/* Assert the found port's id and name are same as
|
||||
* the port added. */
|
||||
CU_ASSERT_EQUAL(rp_port->id, 1);
|
||||
CU_ASSERT_STRING_EQUAL(rp_port->name, "Name of Port");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dev_print_success(void)
|
||||
{
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
struct spdk_scsi_lun lun = { 0 };
|
||||
|
||||
dev.maxlun = 1;
|
||||
dev.lun[0] = &lun;
|
||||
|
||||
/* Prints the dev and a list of the LUNs associated with
|
||||
* the dev */
|
||||
spdk_scsi_dev_print(&dev);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
unsigned int num_failures;
|
||||
|
||||
if (CU_initialize_registry() != CUE_SUCCESS) {
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
suite = CU_add_suite("dev_suite", NULL, NULL);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "destruct - null dev",
|
||||
dev_destruct_null_dev) == NULL
|
||||
|| CU_add_test(suite, "destruct - zero luns", dev_destruct_zero_luns) == NULL
|
||||
|| CU_add_test(suite, "destruct - null lun", dev_destruct_null_lun) == NULL
|
||||
|| CU_add_test(suite, "destruct - success", dev_destruct_success) == NULL
|
||||
|| CU_add_test(suite, "construct - queue depth gt max depth",
|
||||
dev_construct_num_luns_zero) == NULL
|
||||
|| CU_add_test(suite, "construct - no lun0",
|
||||
dev_construct_no_lun_zero) == NULL
|
||||
|| CU_add_test(suite, "construct - null lun",
|
||||
dev_construct_null_lun) == NULL
|
||||
|| CU_add_test(suite, "construct - success", dev_construct_success) == NULL
|
||||
|| CU_add_test(suite, "dev queue task mgmt - success",
|
||||
dev_queue_mgmt_task_success) == NULL
|
||||
|| CU_add_test(suite, "dev queue task - success",
|
||||
dev_queue_task_success) == NULL
|
||||
|| CU_add_test(suite, "dev stop - success", dev_stop_success) == NULL
|
||||
|| CU_add_test(suite, "dev add port - max ports",
|
||||
dev_add_port_max_ports) == NULL
|
||||
|| CU_add_test(suite, "dev add port - construct port failure",
|
||||
dev_add_port_construct_failure) == NULL
|
||||
|| CU_add_test(suite, "dev add port - success",
|
||||
dev_add_port_success) == NULL
|
||||
|| CU_add_test(suite, "dev find port by id - num ports zero",
|
||||
dev_find_port_by_id_num_ports_zero) == NULL
|
||||
|| CU_add_test(suite, "dev find port by id - different port id failure",
|
||||
dev_find_port_by_id_id_not_found_failure) == NULL
|
||||
|| CU_add_test(suite, "dev find port by id - success",
|
||||
dev_find_port_by_id_success) == NULL
|
||||
|| CU_add_test(suite, "dev print - success", dev_print_success) == NULL
|
||||
) {
|
||||
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;
|
||||
}
|
1
test/lib/scsi/lun/.gitignore
vendored
Normal file
1
test/lib/scsi/lun/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
lun_ut
|
56
test/lib/scsi/lun/Makefile
Normal file
56
test/lib/scsi/lun/Makefile
Normal file
@ -0,0 +1,56 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
SPDK_LIBS += $(SPDK_ROOT_DIR)/lib/log/libspdk_log.a \
|
||||
$(SPDK_ROOT_DIR)/lib/cunit/libspdk_cunit.a
|
||||
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/test
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib/scsi
|
||||
LIBS += $(SPDK_LIBS)
|
||||
LIBS += -lcunit
|
||||
|
||||
APP = lun_ut
|
||||
C_SRCS = lun_ut.c
|
||||
|
||||
all: $(APP)
|
||||
|
||||
$(APP): $(OBJS) $(SPDK_LIBS)
|
||||
$(LINK_C)
|
||||
|
||||
clean:
|
||||
$(CLEAN_C) $(APP)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk
|
693
test/lib/scsi/lun/lun_ut.c
Normal file
693
test/lib/scsi/lun/lun_ut.c
Normal file
@ -0,0 +1,693 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "spdk_cunit.h"
|
||||
|
||||
#include "lun.c"
|
||||
#include "lun_db.c"
|
||||
|
||||
SPDK_LOG_REGISTER_TRACE_FLAG("scsi", SPDK_TRACE_SCSI)
|
||||
|
||||
struct spdk_scsi_globals g_spdk_scsi;
|
||||
|
||||
static bool g_lun_execute_fail = false;
|
||||
static bool g_lun_task_set_full_flag = false;
|
||||
static int g_lun_execute_status = SPDK_SCSI_TASK_PENDING;
|
||||
static uint32_t g_task_count = 0;
|
||||
|
||||
void spdk_trace_record(uint16_t tpoint_id, uint16_t poller_id, uint32_t size,
|
||||
uint64_t object_id, uint64_t arg1)
|
||||
{
|
||||
}
|
||||
|
||||
static struct spdk_scsi_task *
|
||||
spdk_get_task(uint32_t *owner_task_ctr)
|
||||
{
|
||||
struct spdk_scsi_task *task;
|
||||
|
||||
task = calloc(1, sizeof(*task));
|
||||
if (!task) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
task->id = g_task_count;
|
||||
|
||||
g_task_count++;
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_put_task(struct spdk_scsi_task *task)
|
||||
{
|
||||
g_task_count--;
|
||||
|
||||
if (task->rbuf) {
|
||||
free(task->rbuf);
|
||||
}
|
||||
|
||||
free(task);
|
||||
}
|
||||
|
||||
void spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk,
|
||||
int asc, int ascq)
|
||||
{
|
||||
task->status = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
|
||||
uint8_t **data)
|
||||
{
|
||||
if (alloc_len < 4096)
|
||||
alloc_len = 4096;
|
||||
|
||||
task->alloc_len = alloc_len;
|
||||
*data = task->rbuf;
|
||||
}
|
||||
|
||||
void spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev,
|
||||
struct spdk_scsi_task *task)
|
||||
{
|
||||
}
|
||||
|
||||
void spdk_scsi_dev_delete_lun(struct spdk_scsi_dev *dev,
|
||||
struct spdk_scsi_lun *lun)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bdev_scsi_reset(struct spdk_bdev *bdev, struct spdk_scsi_task *task)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bdev_scsi_execute(struct spdk_bdev *bdev, struct spdk_scsi_task *task)
|
||||
{
|
||||
if (g_lun_execute_fail)
|
||||
return -EINVAL;
|
||||
else {
|
||||
if (g_lun_task_set_full_flag)
|
||||
task->status = SPDK_SCSI_STATUS_TASK_SET_FULL;
|
||||
else
|
||||
task->status = SPDK_SCSI_STATUS_GOOD;
|
||||
|
||||
if (g_lun_execute_status == SPDK_SCSI_TASK_PENDING)
|
||||
return g_lun_execute_status;
|
||||
else if (g_lun_execute_status == SPDK_SCSI_TASK_COMPLETE)
|
||||
return g_lun_execute_status;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void spdk_bdev_unregister(struct spdk_bdev *bdev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void spdk_event_call(spdk_event_t event)
|
||||
{
|
||||
}
|
||||
|
||||
static _spdk_scsi_lun *
|
||||
lun_construct(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_bdev bdev;
|
||||
|
||||
lun = spdk_scsi_lun_construct("lun0", &bdev);
|
||||
|
||||
SPDK_CU_ASSERT_FATAL(lun != NULL);
|
||||
if (lun != NULL) {
|
||||
SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&lun->pending_tasks));
|
||||
}
|
||||
|
||||
return lun;
|
||||
}
|
||||
|
||||
static void
|
||||
lun_destruct(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
spdk_scsi_lun_destruct(lun);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_task_mgmt_execute_null_task(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = spdk_scsi_lun_task_mgmt_execute(NULL);
|
||||
|
||||
/* returns -1 since we passed NULL for the task */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_task_mgmt_execute_abort_task_null_lun_failure(void)
|
||||
{
|
||||
struct spdk_scsi_task *mgmt_task;
|
||||
struct spdk_scsi_port initiator_port = { 0 };
|
||||
int rc;
|
||||
|
||||
mgmt_task = spdk_get_task(NULL);
|
||||
mgmt_task->function = SPDK_SCSI_TASK_FUNC_ABORT_TASK;
|
||||
mgmt_task->lun = NULL;
|
||||
mgmt_task->initiator_port = &initiator_port;
|
||||
|
||||
rc = spdk_scsi_lun_task_mgmt_execute(mgmt_task);
|
||||
|
||||
spdk_put_task(mgmt_task);
|
||||
|
||||
/* returns -1 since we passed NULL for LUN */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_task_mgmt_execute_abort_task_not_supported(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_task *task;
|
||||
struct spdk_scsi_task *mgmt_task;
|
||||
struct spdk_scsi_port initiator_port = { 0 };
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
uint8_t cdb[6] = { 0 };
|
||||
int rc;
|
||||
|
||||
lun = lun_construct();
|
||||
lun->dev = &dev;
|
||||
|
||||
mgmt_task = spdk_get_task(NULL);
|
||||
mgmt_task->function = SPDK_SCSI_TASK_FUNC_ABORT_TASK;
|
||||
mgmt_task->lun = lun;
|
||||
mgmt_task->initiator_port = &initiator_port;
|
||||
|
||||
/* Params to add regular task to the lun->tasks */
|
||||
task = spdk_get_task(NULL);
|
||||
task->lun = lun;
|
||||
task->cdb = cdb;
|
||||
|
||||
/* Set the task's id and abort_id to the same value */
|
||||
mgmt_task->abort_id = task->id;
|
||||
|
||||
spdk_scsi_lun_append_task(lun, task);
|
||||
|
||||
/* task should now be on the pending_task list */
|
||||
CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));
|
||||
|
||||
spdk_scsi_lun_execute_tasks(lun);
|
||||
|
||||
/*task should now be on the tasks list */
|
||||
CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
|
||||
|
||||
rc = spdk_scsi_lun_task_mgmt_execute(mgmt_task);
|
||||
|
||||
/* returns -1 since task abort is not supported */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
CU_ASSERT(mgmt_task->response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED);
|
||||
|
||||
spdk_put_task(mgmt_task);
|
||||
spdk_put_task(task);
|
||||
|
||||
lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_task_mgmt_execute_abort_task_all_null_lun_failure(void)
|
||||
{
|
||||
struct spdk_scsi_task *mgmt_task;
|
||||
struct spdk_scsi_port initiator_port = { 0 };
|
||||
int rc;
|
||||
|
||||
mgmt_task = spdk_get_task(NULL);
|
||||
mgmt_task->function = SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET;
|
||||
mgmt_task->lun = NULL;
|
||||
mgmt_task->initiator_port = &initiator_port;
|
||||
|
||||
rc = spdk_scsi_lun_task_mgmt_execute(mgmt_task);
|
||||
|
||||
/* Returns -1 since we passed NULL for lun */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
|
||||
spdk_put_task(mgmt_task);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_task_mgmt_execute_abort_task_all_not_supported(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_task *task;
|
||||
struct spdk_scsi_task *mgmt_task;
|
||||
struct spdk_scsi_port initiator_port = { 0 };
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
int rc;
|
||||
uint8_t cdb[6] = { 0 };
|
||||
|
||||
lun = lun_construct();
|
||||
lun->dev = &dev;
|
||||
|
||||
mgmt_task = spdk_get_task(NULL);
|
||||
mgmt_task->function = SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET;
|
||||
mgmt_task->lun = lun;
|
||||
mgmt_task->initiator_port = &initiator_port;
|
||||
|
||||
/* Params to add regular task to the lun->tasks */
|
||||
task = spdk_get_task(NULL);
|
||||
task->initiator_port = &initiator_port;
|
||||
task->lun = lun;
|
||||
task->cdb = cdb;
|
||||
|
||||
spdk_scsi_lun_append_task(lun, task);
|
||||
|
||||
/* task should now be on the pending_task list */
|
||||
CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));
|
||||
|
||||
spdk_scsi_lun_execute_tasks(lun);
|
||||
|
||||
/*task should now be on the tasks list */
|
||||
CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
|
||||
|
||||
rc = spdk_scsi_lun_task_mgmt_execute(mgmt_task);
|
||||
|
||||
/* returns -1 since task abort is not supported */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
CU_ASSERT(mgmt_task->response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED);
|
||||
|
||||
spdk_put_task(mgmt_task);
|
||||
spdk_put_task(task);
|
||||
|
||||
lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_task_mgmt_execute_lun_reset_failure(void)
|
||||
{
|
||||
struct spdk_scsi_task *mgmt_task;
|
||||
int rc;
|
||||
|
||||
mgmt_task = spdk_get_task(NULL);
|
||||
mgmt_task->lun = NULL;
|
||||
mgmt_task->function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
|
||||
|
||||
rc = spdk_scsi_lun_task_mgmt_execute(mgmt_task);
|
||||
|
||||
/* Returns -1 since we passed NULL for lun */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
|
||||
spdk_put_task(mgmt_task);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_task_mgmt_execute_lun_reset(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_task *mgmt_task;
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
int rc;
|
||||
|
||||
lun = lun_construct();
|
||||
lun->dev = &dev;
|
||||
|
||||
mgmt_task = spdk_get_task(NULL);
|
||||
mgmt_task->lun = lun;
|
||||
mgmt_task->function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
|
||||
|
||||
rc = spdk_scsi_lun_task_mgmt_execute(mgmt_task);
|
||||
|
||||
/* Returns success */
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
spdk_put_task(mgmt_task);
|
||||
|
||||
lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_task_mgmt_execute_invalid_case(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_task *mgmt_task;
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
int rc;
|
||||
|
||||
lun = lun_construct();
|
||||
lun->dev = &dev;
|
||||
|
||||
mgmt_task = spdk_get_task(NULL);
|
||||
/* Pass an invalid value to the switch statement */
|
||||
mgmt_task->function = 5;
|
||||
|
||||
rc = spdk_scsi_lun_task_mgmt_execute(mgmt_task);
|
||||
|
||||
/* Returns -1 on passing an invalid value to the switch case */
|
||||
CU_ASSERT_TRUE(rc < 0);
|
||||
|
||||
spdk_put_task(mgmt_task);
|
||||
|
||||
lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_append_task_null_lun_task_cdb_spc_inquiry(void)
|
||||
{
|
||||
struct spdk_scsi_task *task;
|
||||
uint8_t cdb[6] = { 0 };
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
task->cdb = cdb;
|
||||
task->cdb[0] = SPDK_SPC_INQUIRY;
|
||||
/* alloc_len >= 4096 */
|
||||
task->cdb[3] = 0xFF;
|
||||
task->cdb[4] = 0xFF;
|
||||
task->rbuf = malloc(65536);
|
||||
task->lun = NULL;
|
||||
|
||||
spdk_scsi_lun_append_task(NULL, task);
|
||||
|
||||
CU_ASSERT_EQUAL(task->status, SPDK_SCSI_STATUS_GOOD);
|
||||
|
||||
spdk_put_task(task);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_append_task_null_lun_alloc_len_lt_4096(void)
|
||||
{
|
||||
struct spdk_scsi_task *task;
|
||||
uint8_t cdb[6] = { 0 };
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
task->cdb = cdb;
|
||||
task->cdb[0] = SPDK_SPC_INQUIRY;
|
||||
/* alloc_len < 4096 */
|
||||
task->cdb[3] = 0;
|
||||
task->cdb[4] = 0;
|
||||
/* alloc_len is set to a minimal value of 4096
|
||||
* Hence, rbuf of size 4096 is allocated*/
|
||||
task->rbuf = malloc(4096);
|
||||
|
||||
spdk_scsi_lun_append_task(NULL, task);
|
||||
|
||||
CU_ASSERT_EQUAL(task->status, SPDK_SCSI_STATUS_GOOD);
|
||||
|
||||
spdk_put_task(task);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_append_task_null_lun_not_supported(void)
|
||||
{
|
||||
struct spdk_scsi_task *task;
|
||||
uint8_t cdb[6] = { 0 };
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
task->cdb = cdb;
|
||||
task->lun = NULL;
|
||||
|
||||
spdk_scsi_lun_append_task(NULL, task);
|
||||
|
||||
CU_ASSERT_EQUAL(task->status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
/* LUN not supported; task's data transferred should be 0 */
|
||||
CU_ASSERT_EQUAL(task->data_transferred, 0);
|
||||
|
||||
spdk_put_task(task);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_execute_task_set_full(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_task *task;
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
|
||||
lun = lun_construct();
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
task->lun = lun;
|
||||
lun->dev = &dev;
|
||||
|
||||
g_lun_execute_fail = false;
|
||||
g_lun_task_set_full_flag = true;
|
||||
|
||||
spdk_scsi_lun_append_task(lun, task);
|
||||
|
||||
/* task should now be on the pending_task list */
|
||||
CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));
|
||||
|
||||
/* but the tasks list should still be empty since it has not been
|
||||
executed yet
|
||||
*/
|
||||
CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
|
||||
|
||||
spdk_scsi_lun_execute_tasks(lun);
|
||||
|
||||
/* Assert the lun's task set is full; hence the function
|
||||
has failed to add another task to the tasks queue */
|
||||
CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
|
||||
CU_ASSERT(task->status == SPDK_SCSI_STATUS_TASK_SET_FULL);
|
||||
|
||||
spdk_put_task(task);
|
||||
|
||||
lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_execute_scsi_task_pending(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_task *task;
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
|
||||
lun = lun_construct();
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
task->lun = lun;
|
||||
lun->dev = &dev;
|
||||
|
||||
g_lun_execute_fail = false;
|
||||
g_lun_task_set_full_flag = false;
|
||||
g_lun_execute_status = SPDK_SCSI_TASK_PENDING;
|
||||
|
||||
spdk_scsi_lun_append_task(lun, task);
|
||||
|
||||
/* task should now be on the pending_task list */
|
||||
CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));
|
||||
|
||||
/* but the tasks list should still be empty since it has not been
|
||||
executed yet
|
||||
*/
|
||||
CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
|
||||
|
||||
spdk_scsi_lun_execute_tasks(lun);
|
||||
|
||||
/* Assert the task has been successfully added to the tasks queue */
|
||||
CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
|
||||
|
||||
spdk_put_task(task);
|
||||
|
||||
lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_execute_scsi_task_complete(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_task *task;
|
||||
struct spdk_scsi_dev dev = { 0 };
|
||||
|
||||
lun = lun_construct();
|
||||
|
||||
task = spdk_get_task(NULL);
|
||||
task->lun = lun;
|
||||
lun->dev = &dev;
|
||||
|
||||
g_lun_execute_fail = false;
|
||||
g_lun_task_set_full_flag = false;
|
||||
g_lun_execute_status = SPDK_SCSI_TASK_COMPLETE;
|
||||
|
||||
spdk_scsi_lun_append_task(lun, task);
|
||||
|
||||
/* task should now be on the pending_task list */
|
||||
CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));
|
||||
|
||||
/* but the tasks list should still be empty since it has not been
|
||||
executed yet
|
||||
*/
|
||||
CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
|
||||
|
||||
spdk_scsi_lun_execute_tasks(lun);
|
||||
|
||||
/* Assert the task has not been added to the tasks queue */
|
||||
CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
|
||||
|
||||
spdk_put_task(task);
|
||||
|
||||
lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_destruct_success(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
int rc;
|
||||
|
||||
lun = lun_construct();
|
||||
|
||||
rc = spdk_scsi_lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_construct_null_ctx(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun;
|
||||
|
||||
lun = spdk_scsi_lun_construct("lun0", NULL);
|
||||
|
||||
/* lun should be NULL since we passed NULL for the ctx pointer. */
|
||||
CU_ASSERT(lun == NULL);
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
lun_construct_success(void)
|
||||
{
|
||||
struct spdk_scsi_lun *lun = lun_construct();
|
||||
|
||||
lun_destruct(lun);
|
||||
|
||||
CU_ASSERT_EQUAL(g_task_count, 0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
unsigned int num_failures;
|
||||
int rc;
|
||||
|
||||
if (CU_initialize_registry() != CUE_SUCCESS) {
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
suite = CU_add_suite("lun_suite", NULL, NULL);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "task management - null task failure",
|
||||
lun_task_mgmt_execute_null_task) == NULL
|
||||
|| CU_add_test(suite, "task management abort task - null lun failure",
|
||||
lun_task_mgmt_execute_abort_task_null_lun_failure) == NULL
|
||||
|| CU_add_test(suite, "task management abort task - not supported",
|
||||
lun_task_mgmt_execute_abort_task_not_supported) == NULL
|
||||
|| CU_add_test(suite, "task management abort task set - null lun failure",
|
||||
lun_task_mgmt_execute_abort_task_all_null_lun_failure) == NULL
|
||||
|| CU_add_test(suite, "task management abort task set - success",
|
||||
lun_task_mgmt_execute_abort_task_all_not_supported) == NULL
|
||||
|| CU_add_test(suite, "task management - lun reset failure",
|
||||
lun_task_mgmt_execute_lun_reset_failure) == NULL
|
||||
|| CU_add_test(suite, "task management - lun reset success",
|
||||
lun_task_mgmt_execute_lun_reset) == NULL
|
||||
|| CU_add_test(suite, "task management - invalid option",
|
||||
lun_task_mgmt_execute_invalid_case) == NULL
|
||||
|| CU_add_test(suite, "append task - null lun SPDK_SPC_INQUIRY",
|
||||
lun_append_task_null_lun_task_cdb_spc_inquiry) == NULL
|
||||
|| CU_add_test(suite, "append task - allocated length less than 4096",
|
||||
lun_append_task_null_lun_alloc_len_lt_4096) == NULL
|
||||
|| CU_add_test(suite, "append task - unsupported lun",
|
||||
lun_append_task_null_lun_not_supported) == NULL
|
||||
|| CU_add_test(suite, "execute task - task set full",
|
||||
lun_execute_task_set_full) == NULL
|
||||
|| CU_add_test(suite, "execute task - scsi task pending",
|
||||
lun_execute_scsi_task_pending) == NULL
|
||||
|| CU_add_test(suite, "execute task - scsi task complete",
|
||||
lun_execute_scsi_task_complete) == NULL
|
||||
|| CU_add_test(suite, "destruct task - success", lun_destruct_success) == NULL
|
||||
|| CU_add_test(suite, "construct - null ctx", lun_construct_null_ctx) == NULL
|
||||
|| CU_add_test(suite, "construct - success", lun_construct_success) == NULL
|
||||
) {
|
||||
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();
|
||||
|
||||
if (argc > 1) {
|
||||
rc = spdk_cunit_print_results(argv[1]);
|
||||
if (rc != 0) {
|
||||
CU_cleanup_registry();
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
CU_cleanup_registry();
|
||||
return num_failures;
|
||||
}
|
15
test/lib/scsi/scsi.sh
Executable file
15
test/lib/scsi/scsi.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -xe
|
||||
|
||||
testdir=$(readlink -f $(dirname $0))
|
||||
rootdir=$testdir/../../..
|
||||
source $rootdir/scripts/autotest_common.sh
|
||||
|
||||
timing_enter scsi
|
||||
|
||||
$testdir/dev/dev_ut
|
||||
$testdir/lun/lun_ut
|
||||
$testdir/scsi_bdev/scsi_bdev_ut
|
||||
|
||||
timing_exit scsi
|
1
test/lib/scsi/scsi_bdev/.gitignore
vendored
Normal file
1
test/lib/scsi/scsi_bdev/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
scsi_bdev_ut
|
56
test/lib/scsi/scsi_bdev/Makefile
Normal file
56
test/lib/scsi/scsi_bdev/Makefile
Normal file
@ -0,0 +1,56 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
SPDK_LIBS += $(SPDK_ROOT_DIR)/lib/log/libspdk_log.a \
|
||||
$(SPDK_ROOT_DIR)/lib/cunit/libspdk_cunit.a
|
||||
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/test
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib/scsi
|
||||
LIBS += $(SPDK_LIBS)
|
||||
LIBS += -lcunit
|
||||
|
||||
APP = scsi_bdev_ut
|
||||
C_SRCS = scsi_bdev_ut.c
|
||||
|
||||
all: $(APP)
|
||||
|
||||
$(APP): $(OBJS) $(SPDK_LIBS)
|
||||
$(LINK_C)
|
||||
|
||||
clean:
|
||||
$(CLEAN_C) $(APP)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk
|
452
test/lib/scsi/scsi_bdev/scsi_bdev_ut.c
Normal file
452
test/lib/scsi/scsi_bdev/scsi_bdev_ut.c
Normal file
@ -0,0 +1,452 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "scsi_bdev.c"
|
||||
|
||||
#include "CUnit/Basic.h"
|
||||
|
||||
SPDK_LOG_REGISTER_TRACE_FLAG("scsi", SPDK_TRACE_SCSI)
|
||||
|
||||
struct spdk_scsi_globals g_spdk_scsi;
|
||||
|
||||
void
|
||||
spdk_scsi_lun_clear_all(struct spdk_scsi_lun *lun)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk, int asc, int ascq)
|
||||
{
|
||||
spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
|
||||
task->status = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
|
||||
uint8_t **data)
|
||||
{
|
||||
if (alloc_len < 4096) {
|
||||
alloc_len = 4096;
|
||||
}
|
||||
|
||||
task->alloc_len = alloc_len;
|
||||
*data = task->rbuf;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc, int ascq)
|
||||
{
|
||||
uint8_t *data;
|
||||
uint8_t *cp;
|
||||
int resp_code;
|
||||
int hlen = 0, len, plen;
|
||||
int total;
|
||||
|
||||
data = task->sense_data;
|
||||
resp_code = 0x70; /* Current + Fixed format */
|
||||
|
||||
/* SenseLength */
|
||||
memset(data, 0, 2);
|
||||
hlen = 2;
|
||||
|
||||
/* Sense Data */
|
||||
cp = &data[hlen];
|
||||
|
||||
/* 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] = 0;
|
||||
len = 8;
|
||||
|
||||
/* 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;
|
||||
/* Additional sense bytes */
|
||||
plen = 18 - len;
|
||||
|
||||
/* ADDITIONAL SENSE LENGTH */
|
||||
cp[7] = plen;
|
||||
|
||||
total = hlen + len + plen;
|
||||
|
||||
/* SenseLength */
|
||||
to_be16(data, total - 2);
|
||||
task->sense_data_len = total;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
struct spdk_bdev_io *
|
||||
spdk_bdev_read(struct spdk_bdev *bdev,
|
||||
void *buf, uint64_t nbytes, uint64_t offset,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct spdk_bdev_io *
|
||||
spdk_bdev_writev(struct spdk_bdev *bdev,
|
||||
struct iovec *iov, int iovcnt,
|
||||
uint64_t len, uint64_t offset,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct spdk_bdev_io *
|
||||
spdk_bdev_unmap(struct spdk_bdev *bdev,
|
||||
struct spdk_scsi_unmap_bdesc *unmap_d,
|
||||
uint16_t bdesc_count,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_bdev_reset(struct spdk_bdev *bdev, int reset_type,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct spdk_bdev_io *
|
||||
spdk_bdev_flush(struct spdk_bdev *bdev,
|
||||
uint64_t offset, uint64_t length,
|
||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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");
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
data[4] = 0x08;
|
||||
data[5] = 0x02;
|
||||
task.iobuf = data;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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");
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
task.iobuf = NULL;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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];
|
||||
unsigned char data[4096];
|
||||
int rc = 0;
|
||||
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));
|
||||
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");
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
task.rbuf = data;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
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);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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];
|
||||
unsigned char data[4096];
|
||||
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;
|
||||
|
||||
memset(&bdev, 0 , sizeof(struct spdk_bdev));
|
||||
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");
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
task.rbuf = data;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
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);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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];
|
||||
char data[4096];
|
||||
int rc;
|
||||
|
||||
cdb[0] = 0x12;
|
||||
cdb[1] = 0x00; // EVPD = 0
|
||||
cdb[2] = 0xff; // PageCode non-zero
|
||||
cdb[3] = 0x00;
|
||||
cdb[4] = 0xff;
|
||||
cdb[5] = 0x00;
|
||||
task.cdb = cdb;
|
||||
|
||||
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
memset(data, 0, 4096);
|
||||
task.rbuf = data;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
|
||||
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
CU_ASSERT_EQUAL(task.sense_data[4], (SPDK_SCSI_SENSE_ILLEGAL_REQUEST & 0xf));
|
||||
CU_ASSERT_EQUAL(task.sense_data[14], 0x24);
|
||||
CU_ASSERT_EQUAL(task.sense_data[15], 0x0);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This test is to verify specific return data for a standard scsi inquiry
|
||||
* command: Version
|
||||
*/
|
||||
static void
|
||||
inquiry_standard_test(void)
|
||||
{
|
||||
struct spdk_bdev bdev;
|
||||
struct spdk_scsi_task task;
|
||||
struct spdk_scsi_lun lun;
|
||||
struct spdk_scsi_dev dev;
|
||||
struct spdk_bdev_fn_table fn_table;
|
||||
char cdb[6];
|
||||
/* expects a 4K internal data buffer */
|
||||
char data[4096];
|
||||
struct spdk_scsi_cdb_inquiry_data *inq_data;
|
||||
int rc;
|
||||
|
||||
bdev.fn_table = &fn_table;
|
||||
|
||||
cdb[0] = 0x12;
|
||||
cdb[1] = 0x00; // EVPD = 0
|
||||
cdb[2] = 0x00; // PageCode zero - requesting standard inquiry
|
||||
cdb[3] = 0x00;
|
||||
cdb[4] = 0xff; // Indicate data size used by conformance test
|
||||
cdb[5] = 0x00;
|
||||
task.cdb = cdb;
|
||||
|
||||
snprintf(&dev.name[0], sizeof(dev.name), "spdk_iscsi_translation_test");
|
||||
lun.dev = &dev;
|
||||
task.lun = &lun;
|
||||
|
||||
memset(data, 0, 4096);
|
||||
task.rbuf = data;
|
||||
|
||||
rc = spdk_bdev_scsi_execute(&bdev, &task);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
unsigned int num_failures;
|
||||
|
||||
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
|
||||
) {
|
||||
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;
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
set -xe
|
||||
|
||||
make config.h CONFIG_WERROR=y
|
||||
make -C lib/cunit CONFIG_WERROR=y
|
||||
|
||||
make -C test/lib/nvme/unit CONFIG_WERROR=y
|
||||
|
||||
@ -37,3 +38,9 @@ make -C test/lib/nvmf CONFIG_WERROR=y
|
||||
test/lib/nvmf/request/request_ut
|
||||
test/lib/nvmf/session/session_ut
|
||||
test/lib/nvmf/subsystem/subsystem_ut
|
||||
|
||||
make -C test/lib/scsi CONFIG_WERROR=y
|
||||
|
||||
test/lib/scsi/dev/dev_ut
|
||||
test/lib/scsi/lun/lun_ut
|
||||
test/lib/scsi/scsi_bdev/scsi_bdev_ut
|
||||
|
Loading…
Reference in New Issue
Block a user