From c9874b91a7f78e9d208e4ee8ca944fd4bc3f99dc Mon Sep 17 00:00:00 2001 From: Michael Haeuptle Date: Tue, 7 Jan 2020 23:01:43 +0000 Subject: [PATCH] lib/nvmf: custom admin handler config This commit disables the custom identify handler by default. The user has to explictly enable this handler via the set_nvmf_config RPC or conf file. Change-Id: I767816ba7639ebe78683993408ce6db02c7620fe Signed-off-by: Michael Haeuptle Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/479603 Community-CI: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris Tested-by: SPDK CI Jenkins --- CHANGELOG.md | 5 ++--- doc/jsonrpc.md | 7 +++++++ module/event/subsystems/nvmf/conf.c | 4 ++++ module/event/subsystems/nvmf/event_nvmf.h | 5 +++++ module/event/subsystems/nvmf/nvmf_rpc.c | 20 ++++++++++++++++++++ module/event/subsystems/nvmf/nvmf_tgt.c | 10 +++++++++- scripts/rpc.py | 5 ++++- scripts/rpc/nvmf.py | 8 +++++++- 8 files changed, 58 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 875c3ca4e..b4cb30d06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,9 +33,8 @@ in `spdk_internal/nvmf.h` expose this functionality. There is an example custom for the NVMe IDENTIFY CTRLR in `lib/nvmf/custom_cmd_hdlr.c`. This handler gets the SN, MN, FR, IEEE, FGUID attributes from the first NVMe drive in the NVMF subsystem and returns it to the NVMF initiator (sn and mn attributes specified during NVMF subsystem creation RPC will be overwritten). - -This handler is enabled by default and can be disabled by adding -`spdk_nvmf_set_custom_admin_cmd_hdlr(SPDK_NVME_OPC_IDENTIFY, NULL);` to a target application. +This handler can be enabled via the `nvmf_set_config` RPC. +Note: In a future version of SPDK, this handler will be enabled by default. ### sock diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index a5fc8652d..cee57a5eb 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -4313,6 +4313,13 @@ have been initialized. Name | Optional | Type | Description ----------------------- | -------- | ----------- | ----------- acceptor_poll_rate | Optional | number | Polling interval of the acceptor for incoming connections (microseconds) +admin_cmd_passthru | Optional | object | Admin command passthru configuration + +### admin_cmd_passthru {#spdk_nvmf_admin_passthru_conf} + +Name | Optional | Type | Description +----------------------- | -------- | ----------- | ----------- +identify_ctrlr | Required | bool | If true, enables custom identify handler that reports some identify attributes from the underlying NVMe drive ### Example diff --git a/module/event/subsystems/nvmf/conf.c b/module/event/subsystems/nvmf/conf.c index d71302395..278ede8ef 100644 --- a/module/event/subsystems/nvmf/conf.c +++ b/module/event/subsystems/nvmf/conf.c @@ -136,6 +136,9 @@ spdk_nvmf_read_config_file_tgt_conf(struct spdk_conf_section *sp, "we will use RoundRobin as the default scheduler\n"); } + conf->admin_passthru.identify_ctrlr = spdk_conf_section_get_boolval(sp, + "AdminCmdPassthruIdentifyCtrlr", false); + return rc; } @@ -168,6 +171,7 @@ spdk_nvmf_parse_tgt_conf(void) conf->acceptor_poll_rate = ACCEPT_TIMEOUT_US; conf->conn_sched = DEFAULT_CONN_SCHED; + conf->admin_passthru.identify_ctrlr = false; sp = spdk_conf_find_section(NULL, "Nvmf"); if (sp != NULL) { diff --git a/module/event/subsystems/nvmf/event_nvmf.h b/module/event/subsystems/nvmf/event_nvmf.h index bb2c5c669..54d7f27a2 100644 --- a/module/event/subsystems/nvmf/event_nvmf.h +++ b/module/event/subsystems/nvmf/event_nvmf.h @@ -51,9 +51,14 @@ enum spdk_nvmf_connect_sched { CONNECT_SCHED_TRANSPORT_OPTIMAL_GROUP, }; +struct spdk_nvmf_admin_passthru_conf { + bool identify_ctrlr; +}; + struct spdk_nvmf_tgt_conf { uint32_t acceptor_poll_rate; enum spdk_nvmf_connect_sched conn_sched; + struct spdk_nvmf_admin_passthru_conf admin_passthru; }; extern struct spdk_nvmf_tgt_conf *g_spdk_nvmf_tgt_conf; diff --git a/module/event/subsystems/nvmf/nvmf_rpc.c b/module/event/subsystems/nvmf/nvmf_rpc.c index 77cb071ba..f5ae5a2dc 100644 --- a/module/event/subsystems/nvmf/nvmf_rpc.c +++ b/module/event/subsystems/nvmf/nvmf_rpc.c @@ -92,9 +92,28 @@ static int decode_conn_sched(const struct spdk_json_val *val, void *out) return 0; } +static const struct spdk_json_object_decoder admin_passthru_decoder[] = { + {"identify_ctrlr", offsetof(struct spdk_nvmf_admin_passthru_conf, identify_ctrlr), spdk_json_decode_bool} +}; + +static int decode_admin_passthru(const struct spdk_json_val *val, void *out) +{ + struct spdk_nvmf_admin_passthru_conf *req = (struct spdk_nvmf_admin_passthru_conf *)out; + + if (spdk_json_decode_object(val, admin_passthru_decoder, + SPDK_COUNTOF(admin_passthru_decoder), + req)) { + SPDK_ERRLOG("spdk_json_decode_object failed\n"); + return -1; + } + + return 0; +} + static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_conf_decoder[] = { {"acceptor_poll_rate", offsetof(struct spdk_nvmf_tgt_conf, acceptor_poll_rate), spdk_json_decode_uint32, true}, {"conn_sched", offsetof(struct spdk_nvmf_tgt_conf, conn_sched), decode_conn_sched, true}, + {"admin_cmd_passthru", offsetof(struct spdk_nvmf_tgt_conf, admin_passthru), decode_admin_passthru, true} }; static void @@ -121,6 +140,7 @@ spdk_rpc_nvmf_set_config(struct spdk_jsonrpc_request *request, conf->acceptor_poll_rate = ACCEPT_TIMEOUT_US; conf->conn_sched = DEFAULT_CONN_SCHED; + conf->admin_passthru.identify_ctrlr = false; if (params != NULL) { if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_conf_decoder, diff --git a/module/event/subsystems/nvmf/nvmf_tgt.c b/module/event/subsystems/nvmf/nvmf_tgt.c index 0a24a4a38..434c1248b 100644 --- a/module/event/subsystems/nvmf/nvmf_tgt.c +++ b/module/event/subsystems/nvmf/nvmf_tgt.c @@ -438,7 +438,6 @@ nvmf_tgt_advance_state(void) switch (g_tgt_state) { case NVMF_TGT_INIT_NONE: { - spdk_nvmf_set_custom_admin_cmd_hdlr(SPDK_NVME_OPC_IDENTIFY, spdk_nvmf_custom_identify_hdlr); g_tgt_state = NVMF_TGT_INIT_PARSE_CONFIG; break; } @@ -449,6 +448,11 @@ nvmf_tgt_advance_state(void) spdk_thread_send_msg(spdk_get_thread(), nvmf_tgt_parse_conf_start, NULL); break; case NVMF_TGT_INIT_CREATE_POLL_GROUPS: + /* Config parsed */ + if (g_spdk_nvmf_tgt_conf->admin_passthru.identify_ctrlr) { + SPDK_NOTICELOG("Custom identify ctrlr handler enabled\n"); + spdk_nvmf_set_custom_admin_cmd_hdlr(SPDK_NVME_OPC_IDENTIFY, spdk_nvmf_custom_identify_hdlr); + } /* Send a message to each thread and create a poll group */ spdk_for_each_thread(nvmf_tgt_create_poll_group, NULL, @@ -542,6 +546,10 @@ spdk_nvmf_subsystem_write_config_json(struct spdk_json_write_ctx *w) spdk_json_write_named_uint32(w, "acceptor_poll_rate", g_spdk_nvmf_tgt_conf->acceptor_poll_rate); spdk_json_write_named_string(w, "conn_sched", get_conn_sched_string(g_spdk_nvmf_tgt_conf->conn_sched)); + spdk_json_write_named_object_begin(w, "admin_cmd_passthru"); + spdk_json_write_named_bool(w, "identify_ctrlr", + g_spdk_nvmf_tgt_conf->admin_passthru.identify_ctrlr); + spdk_json_write_object_end(w); spdk_json_write_object_end(w); spdk_json_write_object_end(w); diff --git a/scripts/rpc.py b/scripts/rpc.py index 4421c4c92..d6f58c19f 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -1651,7 +1651,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse def nvmf_set_config(args): rpc.nvmf.nvmf_set_config(args.client, acceptor_poll_rate=args.acceptor_poll_rate, - conn_sched=args.conn_sched) + conn_sched=args.conn_sched, + passthru_identify_ctrlr=args.passthru_identify_ctrlr) p = subparsers.add_parser('nvmf_set_config', aliases=['set_nvmf_target_config'], help='Set NVMf target config') @@ -1660,6 +1661,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse on the cores in a round robin manner (Default). 'hostip' - Schedule all the incoming connections from a specific host IP on to the same core. Connections from different IP will be assigned to cores in a round robin manner. 'transport' - Schedule the connection according to the transport characteristics.""") + p.add_argument('-i', '--passthru-identify-ctrlr', help="""Passthrough fields like serial number and model number + when the controller has a single namespace that is an NVMe bdev""", action='store_true') p.set_defaults(func=nvmf_set_config) def nvmf_create_transport(args): diff --git a/scripts/rpc/nvmf.py b/scripts/rpc/nvmf.py index eecfb9b20..c471f6337 100644 --- a/scripts/rpc/nvmf.py +++ b/scripts/rpc/nvmf.py @@ -21,7 +21,8 @@ def nvmf_set_max_subsystems(client, @deprecated_alias('set_nvmf_target_config') def nvmf_set_config(client, acceptor_poll_rate=None, - conn_sched=None): + conn_sched=None, + passthru_identify_ctrlr=None): """Set NVMe-oF target subsystem configuration. Args: @@ -37,6 +38,11 @@ def nvmf_set_config(client, params['acceptor_poll_rate'] = acceptor_poll_rate if conn_sched: params['conn_sched'] = conn_sched + if passthru_identify_ctrlr: + admin_cmd_passthru = {} + admin_cmd_passthru['identify_ctrlr'] = passthru_identify_ctrlr + params['admin_cmd_passthru'] = admin_cmd_passthru + return client.call('nvmf_set_config', params)