diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index a7433b1ca..2de252076 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -2678,11 +2678,10 @@ char *spdk_nvme_cuse_get_ns_name(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid); * for the CUSE device to function. * * \param ctrlr Opaque handle to the NVMe controller. - * \param dev_path The path at which the device should appear. Ex. /dev/spdk/nvme0n1 * * \return 0 on success. Negated errno on failure. */ -int spdk_nvme_cuse_register(struct spdk_nvme_ctrlr *ctrlr, const char *dev_path); +int spdk_nvme_cuse_register(struct spdk_nvme_ctrlr *ctrlr); /** * Remove a previously created character device (Experimental) diff --git a/lib/nvme/nvme_cuse.c b/lib/nvme/nvme_cuse.c index b06e2065c..56d6e828a 100644 --- a/lib/nvme/nvme_cuse.c +++ b/lib/nvme/nvme_cuse.c @@ -44,6 +44,7 @@ struct cuse_device { char dev_name[128]; + uint32_t index; struct spdk_nvme_ctrlr *ctrlr; /**< NVMe controller */ uint32_t nsid; /**< NVMe name space id, or 0 */ @@ -58,6 +59,7 @@ struct cuse_device { }; static TAILQ_HEAD(, cuse_device) g_ctrlr_ctx_head = TAILQ_HEAD_INITIALIZER(g_ctrlr_ctx_head); +static struct spdk_bit_array *g_ctrlr_started; struct cuse_io_ctx { struct spdk_nvme_cmd nvme_cmd; @@ -680,6 +682,7 @@ static int cuse_nvme_ns_start(struct cuse_device *ctrlr_device, uint32_t nsid, const char *dev_path) { struct cuse_device *ns_device; + int rv; ns_device = (struct cuse_device *)calloc(1, sizeof(struct cuse_device)); if (!ns_device) { @@ -690,8 +693,13 @@ cuse_nvme_ns_start(struct cuse_device *ctrlr_device, uint32_t nsid, const char * ns_device->ctrlr = ctrlr_device->ctrlr; ns_device->ctrlr_device = ctrlr_device; ns_device->nsid = nsid; - snprintf(ns_device->dev_name, sizeof(ns_device->dev_name), "%sn%d", - dev_path, ns_device->nsid); + rv = snprintf(ns_device->dev_name, sizeof(ns_device->dev_name), "%sn%d", + dev_path, ns_device->nsid); + if (rv < 0) { + SPDK_ERRLOG("Device name too long.\n"); + free(ns_device); + return -1; + } if (pthread_create(&ns_device->tid, NULL, cuse_thread, ns_device)) { SPDK_ERRLOG("pthread_create failed\n"); @@ -718,31 +726,53 @@ cuse_nvme_ctrlr_stop(struct cuse_device *ctrlr_device) fuse_session_exit(ctrlr_device->session); pthread_join(ctrlr_device->tid, NULL); TAILQ_REMOVE(&g_ctrlr_ctx_head, ctrlr_device, tailq); + spdk_bit_array_clear(g_ctrlr_started, ctrlr_device->index); + if (spdk_bit_array_count_set(g_ctrlr_started) == 0) { + spdk_bit_array_free(&g_ctrlr_started); + } free(ctrlr_device); } static int -nvme_cuse_start(struct spdk_nvme_ctrlr *ctrlr, const char *dev_path) +nvme_cuse_start(struct spdk_nvme_ctrlr *ctrlr) { uint32_t i, nsid; + int rv = 0; struct cuse_device *ctrlr_device; SPDK_NOTICELOG("Creating cuse device for controller\n"); + if (g_ctrlr_started == NULL) { + g_ctrlr_started = spdk_bit_array_create(128); + if (g_ctrlr_started == NULL) { + SPDK_ERRLOG("Cannot create bit array\n"); + return -1; + } + } + ctrlr_device = (struct cuse_device *)calloc(1, sizeof(struct cuse_device)); if (!ctrlr_device) { SPDK_ERRLOG("Cannot allocate memory for ctrlr_device."); - return -ENOMEM; + rv = -ENOMEM; + goto err2; } TAILQ_INIT(&ctrlr_device->ns_devices); ctrlr_device->ctrlr = ctrlr; - snprintf(ctrlr_device->dev_name, sizeof(ctrlr_device->dev_name), "%s", dev_path); + + ctrlr_device->index = spdk_bit_array_find_first_clear(g_ctrlr_started, 0); + if (ctrlr_device->index == UINT32_MAX) { + SPDK_ERRLOG("Too many registered controllers\n"); + goto err2; + } + spdk_bit_array_set(g_ctrlr_started, ctrlr_device->index); + snprintf(ctrlr_device->dev_name, sizeof(ctrlr_device->dev_name), "spdk/nvme%d", + ctrlr_device->index); if (pthread_create(&ctrlr_device->tid, NULL, cuse_thread, ctrlr_device)) { SPDK_ERRLOG("pthread_create failed\n"); - free(ctrlr_device); - return -1; + rv = -1; + goto err3; } TAILQ_INSERT_TAIL(&g_ctrlr_ctx_head, ctrlr_device, tailq); @@ -753,14 +783,24 @@ nvme_cuse_start(struct spdk_nvme_ctrlr *ctrlr, const char *dev_path) continue; } - if (cuse_nvme_ns_start(ctrlr_device, nsid, dev_path) < 0) { + if (cuse_nvme_ns_start(ctrlr_device, nsid, ctrlr_device->dev_name) < 0) { SPDK_ERRLOG("Cannot start CUSE namespace device."); cuse_nvme_ctrlr_stop(ctrlr_device); - return -1; + rv = -1; + goto err3; } } return 0; + +err3: + spdk_bit_array_clear(g_ctrlr_started, ctrlr_device->index); +err2: + free(ctrlr_device); + if (spdk_bit_array_count_set(g_ctrlr_started) == 0) { + spdk_bit_array_free(&g_ctrlr_started); + } + return rv; } static void @@ -788,20 +828,16 @@ static struct nvme_io_msg_producer cuse_nvme_io_msg_producer = { }; int -spdk_nvme_cuse_register(struct spdk_nvme_ctrlr *ctrlr, const char *dev_path) +spdk_nvme_cuse_register(struct spdk_nvme_ctrlr *ctrlr) { int rc; - if (dev_path == NULL) { - return -EINVAL; - } - rc = nvme_io_msg_ctrlr_register(ctrlr, &cuse_nvme_io_msg_producer); if (rc) { return rc; } - rc = nvme_cuse_start(ctrlr, dev_path); + rc = nvme_cuse_start(ctrlr); if (rc) { nvme_io_msg_ctrlr_unregister(ctrlr, &cuse_nvme_io_msg_producer); } diff --git a/module/bdev/nvme/bdev_nvme_cuse_rpc.c b/module/bdev/nvme/bdev_nvme_cuse_rpc.c index 69e2f64fc..a8765ec39 100644 --- a/module/bdev/nvme/bdev_nvme_cuse_rpc.c +++ b/module/bdev/nvme/bdev_nvme_cuse_rpc.c @@ -44,19 +44,16 @@ struct rpc_nvme_cuse_register { char *name; - char *dev_path; }; static void free_rpc_nvme_cuse_register(struct rpc_nvme_cuse_register *req) { free(req->name); - free(req->dev_path); } static const struct spdk_json_object_decoder rpc_nvme_cuse_register_decoders[] = { {"name", offsetof(struct rpc_nvme_cuse_register, name), spdk_json_decode_string}, - {"dev_path", offsetof(struct rpc_nvme_cuse_register, dev_path), spdk_json_decode_string}, }; static void @@ -84,7 +81,7 @@ spdk_rpc_nvme_cuse_register(struct spdk_jsonrpc_request *request, goto cleanup; } - rc = spdk_nvme_cuse_register(bdev_ctrlr->ctrlr, req.dev_path); + rc = spdk_nvme_cuse_register(bdev_ctrlr->ctrlr); if (rc) { SPDK_ERRLOG("Failed to register CUSE devices\n"); spdk_jsonrpc_send_error_response(request, -rc, spdk_strerror(rc)); diff --git a/scripts/rpc.py b/scripts/rpc.py index 49632bf60..702e22078 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -452,15 +452,12 @@ if __name__ == "__main__": def bdev_nvme_cuse_register(args): rpc.bdev.bdev_nvme_cuse_register(args.client, - name=args.name, - dev_path=args.dev_path) + name=args.name) p = subparsers.add_parser('bdev_nvme_cuse_register', help='Register CUSE devices on NVMe controller') p.add_argument('-n', '--name', help='Name of the NVMe controller. Example: Nvme0', required=True) - p.add_argument('-p', '--dev_path', - help='CUSE dev path including prefix: e.g. spdk/nvme0 will result: /dev/spdk/nvme0n1', required=True) p.set_defaults(func=bdev_nvme_cuse_register) def bdev_nvme_cuse_unregister(args): diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index 3377d968a..b2c54e0be 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -486,15 +486,13 @@ def bdev_nvme_detach_controller(client, name): return client.call('bdev_nvme_detach_controller', params) -def bdev_nvme_cuse_register(client, name, dev_path): +def bdev_nvme_cuse_register(client, name): """Register CUSE devices on NVMe controller. Args: name: Name of the operating NVMe controller - dev_path: CUSE dev path with dev prefix """ - params = {'name': name, - 'dev_path': dev_path} + params = {'name': name} return client.call('bdev_nvme_cuse_register', params) diff --git a/test/nvme/spdk_nvme_cli_cuse.sh b/test/nvme/spdk_nvme_cli_cuse.sh index dafc05038..60f4eec92 100755 --- a/test/nvme/spdk_nvme_cli_cuse.sh +++ b/test/nvme/spdk_nvme_cli_cuse.sh @@ -19,7 +19,7 @@ waitforlisten $spdk_tgt_pid bdf=$(iter_pci_class_code 01 08 02 | head -1) $rpc_py bdev_nvme_attach_controller -b Nvme0 -t PCIe -a ${bdf} -$rpc_py bdev_nvme_cuse_register -n Nvme0 -p spdk/nvme0 +$rpc_py bdev_nvme_cuse_register -n Nvme0 sleep 5 @@ -57,16 +57,16 @@ if [ -c /dev/spdk/nvme0 ]; then return 1 fi -$rpc_py bdev_nvme_cuse_register -n Nvme0 -p spdk/nvme1 +$rpc_py bdev_nvme_cuse_register -n Nvme0 sleep 1 -if [ ! -c /dev/spdk/nvme1 ]; then +if [ ! -c /dev/spdk/nvme0 ]; then return 1 fi $rpc_py bdev_nvme_cuse_unregister -n Nvme0 sleep 1 -if [ -c /dev/spdk/nvme1 ]; then +if [ -c /dev/spdk/nvme0 ]; then return 1 fi