diff --git a/lib/nvmf/nvmf.c b/lib/nvmf/nvmf.c index 7f3a9730b..f29a93358 100644 --- a/lib/nvmf/nvmf.c +++ b/lib/nvmf/nvmf.c @@ -1033,12 +1033,23 @@ poll_group_update_subsystem(struct spdk_nvmf_poll_group *group, return -ENOMEM; } ns_info->channel = ch; + } else if (ns_info->num_blocks != spdk_bdev_get_num_blocks(ns->bdev)) { + /* Namespace is still there but size has changed */ + SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Namespace resized: subsystem_id %d," + " nsid %u, pg %p, old %lu, new %lu\n", + subsystem->id, + ns->nsid, + group, + ns_info->num_blocks, + spdk_bdev_get_num_blocks(ns->bdev)); + ns_changed = true; } if (ns == NULL) { memset(ns_info, 0, sizeof(*ns_info)); } else { ns_info->uuid = *spdk_bdev_get_uuid(ns->bdev); + ns_info->num_blocks = spdk_bdev_get_num_blocks(ns->bdev); ns_info->crkey = ns->crkey; ns_info->rtype = ns->rtype; if (ns->holder) { diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index 34ab71388..95d158897 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -149,6 +149,7 @@ struct spdk_nvmf_subsystem_pg_ns_info { struct spdk_uuid holder_id; /* Host ID for the registrants with the namespace */ struct spdk_uuid reg_hostid[SPDK_NVMF_MAX_NUM_REGISTRANTS]; + uint64_t num_blocks; }; typedef void(*spdk_nvmf_poll_group_mod_done)(void *cb_arg, int status); diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index f6f87592e..d93f11f08 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -959,6 +959,27 @@ spdk_nvmf_ns_hot_remove(void *remove_ctx) } } +static void +_spdk_nvmf_ns_resize(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status) +{ + struct spdk_nvmf_ns *ns = cb_arg; + + spdk_nvmf_subsystem_ns_changed(subsystem, ns->opts.nsid); + spdk_nvmf_subsystem_resume(subsystem, NULL, NULL); +} + +static void +spdk_nvmf_ns_resize(void *event_ctx) +{ + struct spdk_nvmf_ns *ns = event_ctx; + int rc; + + rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_resize, ns); + if (rc) { + SPDK_ERRLOG("Unable to pause subsystem to process namespace resize!\n"); + } +} + static void spdk_nvmf_ns_event(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, @@ -974,6 +995,9 @@ spdk_nvmf_ns_event(enum spdk_bdev_event_type type, case SPDK_BDEV_EVENT_REMOVE: spdk_nvmf_ns_hot_remove(event_ctx); break; + case SPDK_BDEV_EVENT_RESIZE: + spdk_nvmf_ns_resize(event_ctx); + break; default: SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type); break; diff --git a/test/unit/lib/nvmf/fc.c/fc_ut.c b/test/unit/lib/nvmf/fc.c/fc_ut.c index b6e4e4f40..72dbf4cec 100644 --- a/test/unit/lib/nvmf/fc.c/fc_ut.c +++ b/test/unit/lib/nvmf/fc.c/fc_ut.c @@ -122,6 +122,8 @@ DEFINE_STUB(spdk_bdev_module_claim_bdev, int, struct spdk_bdev_module *module), 0); DEFINE_STUB_V(spdk_bdev_module_release_bdev, (struct spdk_bdev *bdev)); DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, (const struct spdk_bdev *bdev), 512); +DEFINE_STUB(spdk_bdev_get_num_blocks, uint64_t, (const struct spdk_bdev *bdev), 1024); + DEFINE_STUB(spdk_nvmf_ctrlr_async_event_ns_notice, int, (struct spdk_nvmf_ctrlr *ctrlr), 0); const char * diff --git a/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c b/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c index 8235f0643..88e2def22 100644 --- a/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c +++ b/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c @@ -1268,6 +1268,18 @@ test_spdk_nvmf_ns_event(void) TAILQ_INIT(&subsystem.ctrlrs); TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link); + /* Namespace resize event */ + subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; + g_ns_changed_nsid = 0xFFFFFFFF; + g_ns_changed_ctrlr = NULL; + spdk_nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, &bdev1, subsystem.ns[0]); + CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state); + + poll_threads(); + CU_ASSERT(1 == g_ns_changed_nsid); + CU_ASSERT(&ctrlr == g_ns_changed_ctrlr); + CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state); + /* Namespace remove event */ subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; g_ns_changed_nsid = 0xFFFFFFFF;