diff --git a/CHANGELOG.md b/CHANGELOG.md index 05247badc..c8ea324ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,11 @@ Added `spdk_nvme_ctrlr_get_opts` to retrieve the current controller options. Updated DPDK submodule to DPDK 21.08. +### scsi + +New functions, `spdk_scsi_dev_get_first_lun` and `spdk_scsi_dev_get_next_lun` +have been added to iterate LUNs of a SCSI device. + ### util The `spdk_fd_group_add` API now takes a `name` parameter. diff --git a/include/spdk/scsi.h b/include/spdk/scsi.h index 0bafea47d..757a0aaa7 100644 --- a/include/spdk/scsi.h +++ b/include/spdk/scsi.h @@ -229,6 +229,24 @@ 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); +/** + * Get the first logical unit of the given SCSI device. + * + * \param dev SCSI device. + * + * \return the first logical unit on success, or NULL if there is no logical unit. + */ +struct spdk_scsi_lun *spdk_scsi_dev_get_first_lun(struct spdk_scsi_dev *dev); + +/** + * Get the next logical unit of a SCSI device. + * + * \param lun Previous logical unit. + * + * \return the next logical unit of a SCSI device, or NULL if the prev_lun was the last. + */ +struct spdk_scsi_lun *spdk_scsi_dev_get_next_lun(struct spdk_scsi_lun *prev_lun); + /** * Check whether the SCSI device has any pending task. * diff --git a/lib/scsi/Makefile b/lib/scsi/Makefile index eac71c0ec..6c4a4aec6 100644 --- a/lib/scsi/Makefile +++ b/lib/scsi/Makefile @@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk SO_VER := 4 -SO_MINOR := 0 +SO_MINOR := 1 C_SRCS = dev.c lun.c port.c scsi.c scsi_bdev.c scsi_pr.c scsi_rpc.c task.c LIBNAME = scsi diff --git a/lib/scsi/dev.c b/lib/scsi/dev.c index f0ec790a8..cc4248188 100644 --- a/lib/scsi/dev.c +++ b/lib/scsi/dev.c @@ -436,6 +436,45 @@ spdk_scsi_dev_get_lun(struct spdk_scsi_dev *dev, int lun_id) } } +struct spdk_scsi_lun * +spdk_scsi_dev_get_first_lun(struct spdk_scsi_dev *dev) +{ + struct spdk_scsi_lun *lun; + int lun_id; + + for (lun_id = 0; lun_id < SPDK_SCSI_DEV_MAX_LUN; lun_id++) { + lun = dev->lun[lun_id]; + if (lun != NULL && !spdk_scsi_lun_is_removing(lun)) { + return lun; + } + } + + return NULL; +} + +struct spdk_scsi_lun * +spdk_scsi_dev_get_next_lun(struct spdk_scsi_lun *prev_lun) +{ + struct spdk_scsi_dev *dev; + struct spdk_scsi_lun *lun; + int lun_id; + + if (prev_lun == NULL) { + return NULL; + } + + dev = prev_lun->dev; + + for (lun_id = prev_lun->id + 1; lun_id < SPDK_SCSI_DEV_MAX_LUN; lun_id++) { + lun = dev->lun[lun_id]; + if (lun != NULL && !spdk_scsi_lun_is_removing(lun)) { + return lun; + } + } + + return NULL; +} + bool spdk_scsi_dev_has_pending_tasks(const struct spdk_scsi_dev *dev, const struct spdk_scsi_port *initiator_port) diff --git a/lib/scsi/spdk_scsi.map b/lib/scsi/spdk_scsi.map index b4d081251..f19ed908a 100644 --- a/lib/scsi/spdk_scsi.map +++ b/lib/scsi/spdk_scsi.map @@ -11,6 +11,8 @@ spdk_scsi_dev_get_name; spdk_scsi_dev_get_id; spdk_scsi_dev_get_lun; + spdk_scsi_dev_get_first_lun; + spdk_scsi_dev_get_next_lun; spdk_scsi_dev_has_pending_tasks; spdk_scsi_dev_destruct; spdk_scsi_dev_queue_mgmt_task; diff --git a/test/unit/lib/scsi/dev.c/dev_ut.c b/test/unit/lib/scsi/dev.c/dev_ut.c index be9b46001..410d14eff 100644 --- a/test/unit/lib/scsi/dev.c/dev_ut.c +++ b/test/unit/lib/scsi/dev.c/dev_ut.c @@ -49,6 +49,8 @@ DEFINE_STUB(spdk_scsi_lun_is_removing, bool, static char *g_bdev_names[] = { "malloc0", "malloc1", + "malloc2", + "malloc4", }; static struct spdk_scsi_port *g_initiator_port_with_pending_tasks = NULL; @@ -543,7 +545,7 @@ dev_add_lun_bdev_not_found(void) int rc; struct spdk_scsi_dev dev = {0}; - rc = spdk_scsi_dev_add_lun(&dev, "malloc2", 0, NULL, NULL); + rc = spdk_scsi_dev_add_lun(&dev, "malloc3", 0, NULL, NULL); SPDK_CU_ASSERT_FATAL(dev.lun[0] == NULL); CU_ASSERT_NOT_EQUAL(rc, 0); @@ -619,6 +621,36 @@ dev_check_pending_tasks(void) CU_ASSERT(spdk_scsi_dev_has_pending_tasks(&dev, &initiator_port) == true); } +static void +dev_iterate_luns(void) +{ + struct spdk_scsi_dev *dev; + struct spdk_scsi_lun *lun; + const char *bdev_name_list[3] = {"malloc0", "malloc2", "malloc4"}; + int lun_id_list[3] = {0, 2, 4}; + + dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 3, + SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL); + + /* Successfully constructs and returns a dev */ + CU_ASSERT_TRUE(dev != NULL); + + lun = spdk_scsi_dev_get_first_lun(dev); + CU_ASSERT(lun != NULL); + CU_ASSERT(lun->id == 0); + lun = spdk_scsi_dev_get_next_lun(lun); + CU_ASSERT(lun != NULL); + CU_ASSERT(lun->id == 2); + lun = spdk_scsi_dev_get_next_lun(lun); + CU_ASSERT(lun != NULL); + CU_ASSERT(lun->id == 4); + lun = spdk_scsi_dev_get_next_lun(lun); + CU_ASSERT(lun == NULL); + + /* free the dev */ + spdk_scsi_dev_destruct(dev, NULL, NULL); +} + int main(int argc, char **argv) { @@ -657,6 +689,7 @@ main(int argc, char **argv) CU_ADD_TEST(suite, dev_add_lun_success1); CU_ADD_TEST(suite, dev_add_lun_success2); CU_ADD_TEST(suite, dev_check_pending_tasks); + CU_ADD_TEST(suite, dev_iterate_luns); CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests();