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>
This commit is contained in:
Shuhei Matsumoto 2018-01-12 09:42:02 +09:00 committed by Jim Harris
parent 5c13f5ae6d
commit 3b3c6002c9
6 changed files with 226 additions and 27 deletions

View File

@ -192,7 +192,9 @@ struct spdk_scsi_dev *spdk_scsi_dev_construct(const char *name,
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);

View File

@ -1294,3 +1294,36 @@ void spdk_iscsi_tgt_node_delete_map(struct spdk_iscsi_portal_grp *portal_group,
}
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}
int
spdk_iscsi_tgt_node_add_lun(struct spdk_iscsi_tgt_node *target,
const char *bdev_name, int lun_id)
{
struct spdk_scsi_dev *dev;
int rc;
if (target->num_active_conns > 0) {
SPDK_ERRLOG("Target has active connections (count=%d)\n",
target->num_active_conns);
return -1;
}
if (lun_id < -1 || lun_id >= SPDK_SCSI_DEV_MAX_LUN) {
SPDK_ERRLOG("Specified LUN ID (%d) is invalid\n", lun_id);
return -1;
}
dev = target->dev;
if (dev == NULL) {
SPDK_ERRLOG("SCSI device is not found\n");
return -1;
}
rc = spdk_scsi_dev_add_lun(dev, bdev_name, lun_id, NULL, NULL);
if (rc != 0) {
SPDK_ERRLOG("spdk_scsi_dev_add_lun failed\n");
return -1;
}
return 0;
}

View File

@ -132,4 +132,6 @@ int spdk_iscsi_tgt_node_cleanup_luns(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_tgt_node *target);
void spdk_iscsi_tgt_node_delete_map(struct spdk_iscsi_portal_grp *portal_group,
struct spdk_iscsi_init_grp *initiator_group);
int spdk_iscsi_tgt_node_add_lun(struct spdk_iscsi_tgt_node *target,
const char *bdev_name, int lun_id);
#endif /* SPDK_ISCSI_TGT_NODE_H_ */

View File

@ -102,13 +102,53 @@ spdk_scsi_dev_destruct(struct spdk_scsi_dev *dev)
}
}
static void
spdk_scsi_dev_add_lun(struct spdk_scsi_dev *dev,
struct spdk_scsi_lun *lun, int id)
static int
spdk_scsi_dev_find_lowest_free_lun_id(struct spdk_scsi_dev *dev)
{
lun->id = id;
int i;
for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) {
if (dev->lun[i] == NULL) {
return i;
}
}
return -1;
}
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_bdev *bdev;
struct spdk_scsi_lun *lun;
bdev = spdk_bdev_get_by_name(bdev_name);
if (bdev == NULL) {
SPDK_ERRLOG("device %s: cannot find bdev '%s' (target %d)\n",
dev->name, bdev_name, lun_id);
return -1;
}
/* Search the lowest free LUN ID if LUN ID is default */
if (lun_id == -1) {
lun_id = spdk_scsi_dev_find_lowest_free_lun_id(dev);
if (lun_id == -1) {
SPDK_ERRLOG("Free LUN ID is not found\n");
return -1;
}
}
lun = spdk_scsi_lun_construct(bdev, hotremove_cb, hotremove_ctx);
if (lun == NULL) {
return -1;
}
lun->id = lun_id;
lun->dev = dev;
dev->lun[id] = lun;
dev->lun[lun_id] = lun;
return 0;
}
void
@ -145,10 +185,8 @@ spdk_scsi_dev_construct(const char *name, const char *bdev_name_list[],
void *hotremove_ctx)
{
struct spdk_scsi_dev *dev;
struct spdk_bdev *bdev;
struct spdk_scsi_lun *lun = NULL;
bool found_lun_0;
int i;
int i, rc;
if (num_luns == 0) {
SPDK_ERRLOG("device %s: no LUNs specified\n", name);
@ -187,27 +225,15 @@ spdk_scsi_dev_construct(const char *name, const char *bdev_name_list[],
dev->protocol_id = protocol_id;
for (i = 0; i < num_luns; i++) {
bdev = spdk_bdev_get_by_name(bdev_name_list[i]);
if (bdev == NULL) {
SPDK_ERRLOG("device %s: cannot find bdev '%s' (target %d)\n",
name, bdev_name_list[i], i);
goto error;
rc = spdk_scsi_dev_add_lun(dev, bdev_name_list[i], lun_id_list[i],
hotremove_cb, hotremove_ctx);
if (rc < 0) {
spdk_scsi_dev_destruct(dev);
return NULL;
}
lun = spdk_scsi_lun_construct(bdev, hotremove_cb, hotremove_ctx);
if (lun == NULL) {
goto error;
}
spdk_scsi_dev_add_lun(dev, lun, lun_id_list[i]);
}
return dev;
error:
spdk_scsi_dev_destruct(dev);
return NULL;
}
void

View File

@ -95,6 +95,69 @@ spdk_scsi_dev_get_lun(struct spdk_scsi_dev *dev, int lun_id)
return dev->lun[lun_id];
}
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)
{
if (bdev_name == NULL) {
return -1;
} else {
return 0;
}
}
static void
add_lun_test_cases(void)
{
struct spdk_iscsi_tgt_node tgtnode;
int lun_id = 0;
char *bdev_name = NULL;
struct spdk_scsi_dev scsi_dev;
int rc;
memset(&tgtnode, 0, sizeof(struct spdk_iscsi_tgt_node));
memset(&scsi_dev, 0, sizeof(struct spdk_scsi_dev));
/* case 1 */
tgtnode.num_active_conns = 1;
rc = spdk_iscsi_tgt_node_add_lun(&tgtnode, bdev_name, lun_id);
CU_ASSERT(rc != 0);
/* case 2 */
tgtnode.num_active_conns = 0;
lun_id = -2;
rc = spdk_iscsi_tgt_node_add_lun(&tgtnode, bdev_name, lun_id);
CU_ASSERT(rc != 0);
/* case 3 */
lun_id = SPDK_SCSI_DEV_MAX_LUN;
rc = spdk_iscsi_tgt_node_add_lun(&tgtnode, bdev_name, lun_id);
CU_ASSERT(rc != 0);
/* case 4 */
lun_id = -1;
tgtnode.dev = NULL;
rc = spdk_iscsi_tgt_node_add_lun(&tgtnode, bdev_name, lun_id);
CU_ASSERT(rc != 0);
/* case 5 */
tgtnode.dev = &scsi_dev;
rc = spdk_iscsi_tgt_node_add_lun(&tgtnode, bdev_name, lun_id);
CU_ASSERT(rc != 0);
/* case 6 */
bdev_name = "LUN0";
rc = spdk_iscsi_tgt_node_add_lun(&tgtnode, bdev_name, lun_id);
CU_ASSERT(rc == 0);
}
static void
config_file_fail_cases(void)
{
@ -755,7 +818,8 @@ main(int argc, char **argv)
}
if (
CU_add_test(suite, "config file fail cases", config_file_fail_cases) == NULL
CU_add_test(suite, "add lun test cases", add_lun_test_cases) == NULL
|| CU_add_test(suite, "config file fail cases", config_file_fail_cases) == NULL
|| CU_add_test(suite, "allow any allowed case", allow_any_allowed) == NULL
|| CU_add_test(suite, "allow ipv6 allowed case", allow_ipv6_allowed) == NULL
|| CU_add_test(suite, "allow ipv6 denied case", allow_ipv6_denied) == NULL

View File

@ -531,6 +531,70 @@ dev_find_port_by_id_success(void)
}
}
static void
dev_add_lun_bdev_not_found(void)
{
int rc;
struct spdk_scsi_dev dev = {0};
rc = spdk_scsi_dev_add_lun(&dev, "malloc2", -1, NULL, NULL);
CU_ASSERT_NOT_EQUAL(rc, 0);
}
static void
dev_add_lun_no_free_lun_id(void)
{
int rc;
int i;
struct spdk_scsi_dev dev = {0};
struct spdk_scsi_lun lun;
for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) {
dev.lun[i] = &lun;
}
rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL);
CU_ASSERT_NOT_EQUAL(rc, 0);
}
static void
dev_add_lun_success1(void)
{
int rc;
int i;
struct spdk_scsi_dev dev;
for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) {
dev.lun[i] = NULL;
}
rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL);
CU_ASSERT_EQUAL(rc, 0);
spdk_scsi_dev_destruct(&dev);
}
static void
dev_add_lun_success2(void)
{
int rc;
int i;
struct spdk_scsi_dev dev;
for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) {
dev.lun[i] = NULL;
}
rc = spdk_scsi_dev_add_lun(&dev, "malloc0", 0, NULL, NULL);
CU_ASSERT_EQUAL(rc, 0);
spdk_scsi_dev_destruct(&dev);
}
int
main(int argc, char **argv)
{
@ -585,6 +649,14 @@ main(int argc, char **argv)
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 add lun - bdev not found",
dev_add_lun_bdev_not_found) == NULL
|| CU_add_test(suite, "dev add lun - no free lun id",
dev_add_lun_no_free_lun_id) == NULL
|| CU_add_test(suite, "dev add lun - success 1",
dev_add_lun_success1) == NULL
|| CU_add_test(suite, "dev add lun - success 2",
dev_add_lun_success2) == NULL
) {
CU_cleanup_registry();
return CU_get_error();