diff --git a/include/spdk/scsi.h b/include/spdk/scsi.h index 3e34601b7..ff8ac87dd 100644 --- a/include/spdk/scsi.h +++ b/include/spdk/scsi.h @@ -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); diff --git a/lib/iscsi/tgt_node.c b/lib/iscsi/tgt_node.c index 3268df04b..5aa1275d8 100644 --- a/lib/iscsi/tgt_node.c +++ b/lib/iscsi/tgt_node.c @@ -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; +} diff --git a/lib/iscsi/tgt_node.h b/lib/iscsi/tgt_node.h index 8f94f13bf..2bc3623ca 100644 --- a/lib/iscsi/tgt_node.h +++ b/lib/iscsi/tgt_node.h @@ -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_ */ diff --git a/lib/scsi/dev.c b/lib/scsi/dev.c index 1221d84a8..aa5f1d5dc 100644 --- a/lib/scsi/dev.c +++ b/lib/scsi/dev.c @@ -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 diff --git a/test/unit/lib/iscsi/tgt_node.c/tgt_node_ut.c b/test/unit/lib/iscsi/tgt_node.c/tgt_node_ut.c index 050a1d392..0f1793c7c 100644 --- a/test/unit/lib/iscsi/tgt_node.c/tgt_node_ut.c +++ b/test/unit/lib/iscsi/tgt_node.c/tgt_node_ut.c @@ -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 diff --git a/test/unit/lib/scsi/dev.c/dev_ut.c b/test/unit/lib/scsi/dev.c/dev_ut.c index 9a4264876..27eef447e 100644 --- a/test/unit/lib/scsi/dev.c/dev_ut.c +++ b/test/unit/lib/scsi/dev.c/dev_ut.c @@ -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();