Shuhei Matsumoto 3b3c6002c9 iscsi: Add LUN to an existing target (not runtime)
Removing an LUN from an existing iSCSI target is possible by
removing the corresponding BDEV. However adding an LUN to an
existing iSCSI target is not possible yet.

Add a new function spdk_iscsi_tgt_node_add_lun() and related
functions first toward supporting this function.

JSON-RPC for this operation will be submitted an another patch.

Informing the newly added LUN to the initiator is not included
in this patch. Hence this operation is possible only for any
inactive target.

Change-Id: I3a28f4d75a17126e49c9d12ce64c3ad68f231840
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/385180
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2018-01-17 12:41:29 -05:00

246 lines
8.3 KiB
C

/*-
* 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 bdev translation layer
*/
#ifndef SPDK_SCSI_H
#define SPDK_SCSI_H
#include "spdk/stdinc.h"
#include "spdk/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Defines for SPDK tracing framework */
#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)
#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
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,
};
/*
* 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
};
struct spdk_scsi_task;
typedef void (*spdk_scsi_task_cpl)(struct spdk_scsi_task *task);
typedef void (*spdk_scsi_task_free)(struct spdk_scsi_task *task);
struct spdk_scsi_task {
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_scsi_task_cpl cpl_fn;
spdk_scsi_task_free free_fn;
uint32_t ref;
uint32_t transfer_len;
uint32_t dxfer_dir;
uint32_t length;
/**
* Amount of data actually transferred. Can be less than requested
* transfer_len - i.e. SCSI INQUIRY.
*/
uint32_t data_transferred;
uint64_t offset;
uint8_t *cdb;
/**
* \internal
* Size of internal buffer or zero when iov.iov_base is not internally managed.
*/
uint32_t alloc_len;
/**
* \internal
* iov is internal buffer. Use iovs to access elements of IO.
*/
struct iovec iov;
struct iovec *iovs;
uint16_t iovcnt;
uint8_t sense_data[32];
size_t sense_data_len;
void *bdev_io;
TAILQ_ENTRY(spdk_scsi_task) scsi_link;
uint32_t abort_id;
};
struct spdk_scsi_port;
struct spdk_scsi_dev;
struct spdk_scsi_lun;
int spdk_scsi_init(void);
void spdk_scsi_fini(void);
int spdk_scsi_lun_get_id(const struct spdk_scsi_lun *lun);
const char *spdk_scsi_lun_get_bdev_name(const struct spdk_scsi_lun *lun);
const struct spdk_scsi_dev *spdk_scsi_lun_get_dev(const struct spdk_scsi_lun *lun);
const char *spdk_scsi_dev_get_name(const struct spdk_scsi_dev *dev);
int spdk_scsi_dev_get_id(const struct spdk_scsi_dev *dev);
struct spdk_scsi_lun *spdk_scsi_dev_get_lun(struct spdk_scsi_dev *dev, int lun_id);
bool spdk_scsi_dev_has_pending_tasks(const struct spdk_scsi_dev *dev);
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,
enum spdk_scsi_task_func func);
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);
int spdk_scsi_dev_delete_port(struct spdk_scsi_dev *dev, uint64_t id);
struct spdk_scsi_port *spdk_scsi_dev_find_port_by_id(struct spdk_scsi_dev *dev, uint64_t id);
int spdk_scsi_dev_allocate_io_channels(struct spdk_scsi_dev *dev);
void spdk_scsi_dev_free_io_channels(struct spdk_scsi_dev *dev);
/**
* \brief Constructs a SCSI device object using the given parameters.
*
* \param name Name for the SCSI device.
* \param bdev_name_list List of bdev names to attach to the LUNs for this SCSI
* device.
* \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.
* \param hotremove_cb Callback to lun hotremoval. Will be called
* once hotremove is first triggered.
* \param hotremove_ctx Additional argument to hotremove_cb
* \return The constructed spdk_scsi_dev object.
*/
struct spdk_scsi_dev *spdk_scsi_dev_construct(const char *name,
const char *bdev_name_list[],
int *lun_id_list,
int num_luns,
uint8_t protocol_id,
void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
void *hotremove_ctx);
void spdk_scsi_dev_delete_lun(struct spdk_scsi_dev *dev, struct spdk_scsi_lun *lun);
int spdk_scsi_dev_add_lun(struct spdk_scsi_dev *dev, const char *bdev_name, int lun_id,
void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
void *hotremove_ctx);
struct spdk_scsi_port *spdk_scsi_port_create(uint64_t id, uint16_t index, const char *name);
void spdk_scsi_port_free(struct spdk_scsi_port **pport);
const char *spdk_scsi_port_get_name(const struct spdk_scsi_port *port);
void spdk_scsi_task_construct(struct spdk_scsi_task *task,
spdk_scsi_task_cpl cpl_fn,
spdk_scsi_task_free free_fn);
void spdk_scsi_task_put(struct spdk_scsi_task *task);
void spdk_scsi_task_free_data(struct spdk_scsi_task *task);
/**
* Set internal buffer to given one. Caller is owner of that buffer.
*
* \param task Task struct
* \param data Pointer to buffer
* \param len Buffer length
*/
void spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len);
/**
* Allocate internal buffer of requested size. Caller is not owner of
* returned buffer and must not free it. Caller is permitted to call
* spdk_scsi_task_free_data() to free internal buffer if it is not required
* anymore, but must assert that task is done and not used by library.
*
* Allocated buffer is stored in iov field of task object.
*
* \param task Task struct
* \param alloc_len Size of allocated buffer.
* \return Pointer to buffer or NULL on error.
*/
void *spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len);
int spdk_scsi_task_scatter_data(struct spdk_scsi_task *task, const void *src, size_t len);
void *spdk_scsi_task_gather_data(struct spdk_scsi_task *task, int *len);
void spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc,
int ascq);
void spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk, int asc,
int ascq);
void spdk_scsi_task_process_null_lun(struct spdk_scsi_task *task);
#ifdef __cplusplus
}
#endif
#endif /* SPDK_SCSI_H */