diff --git a/module/bdev/nvme/bdev_nvme_rpc.c b/module/bdev/nvme/bdev_nvme_rpc.c index 5c7a6a80c..a5908f7b6 100644 --- a/module/bdev/nvme/bdev_nvme_rpc.c +++ b/module/bdev/nvme/bdev_nvme_rpc.c @@ -21,14 +21,6 @@ #include "spdk/log.h" #include "spdk/bdev_module.h" -struct open_descriptors { - void *desc; - struct spdk_bdev *bdev; - TAILQ_ENTRY(open_descriptors) tqlst; - struct spdk_thread *thread; -}; -typedef TAILQ_HEAD(, open_descriptors) open_descriptors_t; - static int rpc_decode_action_on_timeout(const struct spdk_json_val *val, void *out) { @@ -783,32 +775,21 @@ struct firmware_update_info { unsigned int size_remaining; unsigned int offset; unsigned int transfer; + bool success; - void *desc; + struct spdk_bdev_desc *desc; struct spdk_io_channel *ch; + struct spdk_thread *orig_thread; struct spdk_jsonrpc_request *request; struct spdk_nvme_ctrlr *ctrlr; - open_descriptors_t desc_head; struct rpc_apply_firmware req; }; static void -_apply_firmware_cleanup(void *ctx) +apply_firmware_cleanup(struct firmware_update_info *firm_ctx) { - struct spdk_bdev_desc *desc = ctx; - - spdk_bdev_close(desc); -} - -static void -apply_firmware_cleanup(void *cb_arg) -{ - struct open_descriptors *opt, *tmp; - struct firmware_update_info *firm_ctx = cb_arg; - - if (!firm_ctx) { - return; - } + assert(firm_ctx != NULL); + assert(firm_ctx->orig_thread == spdk_get_thread()); if (firm_ctx->fw_image) { spdk_free(firm_ctx->fw_image); @@ -820,28 +801,22 @@ apply_firmware_cleanup(void *cb_arg) spdk_put_io_channel(firm_ctx->ch); } - TAILQ_FOREACH_SAFE(opt, &firm_ctx->desc_head, tqlst, tmp) { - TAILQ_REMOVE(&firm_ctx->desc_head, opt, tqlst); - /* Close the underlying bdev on its same opened thread. */ - if (opt->thread && opt->thread != spdk_get_thread()) { - spdk_thread_send_msg(opt->thread, _apply_firmware_cleanup, opt->desc); - } else { - spdk_bdev_close(opt->desc); - } - free(opt); + if (firm_ctx->desc) { + spdk_bdev_close(firm_ctx->desc); } + free(firm_ctx); } static void -apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +_apply_firmware_complete_reset(void *ctx) { struct spdk_json_write_ctx *w; - struct firmware_update_info *firm_ctx = cb_arg; + struct firmware_update_info *firm_ctx = ctx; - spdk_bdev_free_io(bdev_io); + assert(firm_ctx->orig_thread == spdk_get_thread()); - if (!success) { + if (!firm_ctx->success) { spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "firmware commit failed."); apply_firmware_cleanup(firm_ctx); @@ -862,18 +837,32 @@ apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void * } static void -apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +apply_firmware_complete_reset(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +{ + struct firmware_update_info *firm_ctx = cb_arg; + + spdk_bdev_free_io(bdev_io); + + firm_ctx->success = success; + + spdk_thread_exec_msg(firm_ctx->orig_thread, _apply_firmware_complete_reset, firm_ctx); +} + +static void apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); + +static void +_apply_firmware_complete(void *ctx) { struct spdk_nvme_cmd cmd = {}; struct spdk_nvme_fw_commit fw_commit; int slot = 0; int rc; - struct firmware_update_info *firm_ctx = cb_arg; + struct firmware_update_info *firm_ctx = ctx; enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG; - spdk_bdev_free_io(bdev_io); + assert(firm_ctx->orig_thread == spdk_get_thread()); - if (!success) { + if (!firm_ctx->success) { spdk_jsonrpc_send_error_response(firm_ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "firmware download failed ."); apply_firmware_cleanup(firm_ctx); @@ -920,6 +909,18 @@ apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg } } +static void +apply_firmware_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +{ + struct firmware_update_info *firm_ctx = cb_arg; + + spdk_bdev_free_io(bdev_io); + + firm_ctx->success = success; + + spdk_thread_exec_msg(firm_ctx->orig_thread, _apply_firmware_complete, firm_ctx); +} + static void apply_firmware_open_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *event_ctx) { @@ -932,11 +933,7 @@ rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request, int rc; int fd = -1; struct stat fw_stat; - struct spdk_nvme_ctrlr *ctrlr; struct spdk_bdev *bdev; - struct spdk_bdev *bdev2; - struct open_descriptors *opt; - struct spdk_bdev_desc *desc; struct spdk_nvme_cmd cmd = {}; struct firmware_update_info *firm_ctx; @@ -947,8 +944,8 @@ rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request, return; } firm_ctx->fw_image = NULL; - TAILQ_INIT(&firm_ctx->desc_head); firm_ctx->request = request; + firm_ctx->orig_thread = spdk_get_thread(); if (spdk_json_decode_object(params, rpc_apply_firmware_decoders, SPDK_COUNTOF(rpc_apply_firmware_decoders), &firm_ctx->req)) { @@ -957,65 +954,21 @@ rpc_bdev_nvme_apply_firmware(struct spdk_jsonrpc_request *request, goto err; } - if ((bdev = spdk_bdev_get_by_name(firm_ctx->req.bdev_name)) == NULL) { + if (spdk_bdev_open_ext(firm_ctx->req.bdev_name, true, apply_firmware_open_cb, NULL, + &firm_ctx->desc) != 0) { spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, - "bdev %s were not found", + "bdev %s could not be opened", firm_ctx->req.bdev_name); goto err; } + bdev = spdk_bdev_desc_get_bdev(firm_ctx->desc); - if ((ctrlr = bdev_nvme_get_ctrlr(bdev)) == NULL) { + if ((firm_ctx->ctrlr = bdev_nvme_get_ctrlr(bdev)) == NULL) { spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Controller information for %s were not found.", firm_ctx->req.bdev_name); goto err; } - firm_ctx->ctrlr = ctrlr; - - for (bdev2 = spdk_bdev_first(); bdev2; bdev2 = spdk_bdev_next(bdev2)) { - - if (bdev_nvme_get_ctrlr(bdev2) != ctrlr) { - continue; - } - - if (!(opt = malloc(sizeof(struct open_descriptors)))) { - spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, - "Memory allocation error."); - goto err; - } - - if (spdk_bdev_open_ext(spdk_bdev_get_name(bdev2), true, apply_firmware_open_cb, NULL, &desc) != 0) { - spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, - "Device %s is in use.", - firm_ctx->req.bdev_name); - free(opt); - goto err; - } - - /* Save the thread where the base device is opened */ - opt->thread = spdk_get_thread(); - - opt->desc = desc; - opt->bdev = bdev; - TAILQ_INSERT_TAIL(&firm_ctx->desc_head, opt, tqlst); - } - - /* - * find a descriptor associated with our bdev - */ - firm_ctx->desc = NULL; - TAILQ_FOREACH(opt, &firm_ctx->desc_head, tqlst) { - if (opt->bdev == bdev) { - firm_ctx->desc = opt->desc; - break; - } - } - - if (!firm_ctx->desc) { - spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, - "No descriptor were found."); - goto err; - } firm_ctx->ch = spdk_bdev_get_io_channel(firm_ctx->desc); if (!firm_ctx->ch) {