Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nvmet: Improve nvmet_alloc_ctrl() interface and implementation

Introduce struct nvmet_alloc_ctrl_args to define the arguments for
the function nvmet_alloc_ctrl() to avoid the need for passing a pointer
to a struct nvmet_req as an argument. This new data structure aggregates
together the arguments that were passed to nvmet_alloc_ctrl()
(subsysnqn, hostnqn and kato), together with the struct nvmet_req fields
used by nvmet_alloc_ctrl(), that is, the fields port, p2p_client, and
ops as input and the result and error_loc fields as output, as well as a
status field. nvmet_alloc_ctrl() is also changed to return a pointer
to the allocated and initialized controller structure instead of a
status code, as the status is now returned through the status field of
struct nvmet_alloc_ctrl_args.

The function nvmet_setup_p2p_ns_map() is changed to not take a pointer
to a struct nvmet_req as argument, instead, directly specify the
p2p_client device pointer needed as argument.

The code in nvmet_execute_admin_connect() that initializes a new target
controller after allocating it is moved into nvmet_alloc_ctrl().
The code that sets up an admin queue for the controller (and the call
to nvmet_install_queue()) remains in nvmet_execute_admin_connect().

Finally, nvmet_alloc_ctrl() is also exported to allow target drivers to
use this function directly to allocate and initialize a new controller
structure without the need to rely on a fabrics connect command request.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Tested-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>

authored by

Damien Le Moal and committed by
Keith Busch
62027831 200adac7

+95 -66
+53 -30
drivers/nvme/target/core.c
··· 1350 1350 * Note: ctrl->subsys->lock should be held when calling this function 1351 1351 */ 1352 1352 static void nvmet_setup_p2p_ns_map(struct nvmet_ctrl *ctrl, 1353 - struct nvmet_req *req) 1353 + struct device *p2p_client) 1354 1354 { 1355 1355 struct nvmet_ns *ns; 1356 1356 unsigned long idx; 1357 1357 1358 - if (!req->p2p_client) 1358 + if (!p2p_client) 1359 1359 return; 1360 1360 1361 - ctrl->p2p_client = get_device(req->p2p_client); 1361 + ctrl->p2p_client = get_device(p2p_client); 1362 1362 1363 1363 xa_for_each(&ctrl->subsys->namespaces, idx, ns) 1364 1364 nvmet_p2pmem_ns_add_p2p(ctrl, ns); ··· 1387 1387 ctrl->ops->delete_ctrl(ctrl); 1388 1388 } 1389 1389 1390 - u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn, 1391 - struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp, 1392 - uuid_t *hostid) 1390 + struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_alloc_ctrl_args *args) 1393 1391 { 1394 1392 struct nvmet_subsys *subsys; 1395 1393 struct nvmet_ctrl *ctrl; 1394 + u32 kato = args->kato; 1395 + u8 dhchap_status; 1396 1396 int ret; 1397 - u16 status; 1398 1397 1399 - status = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR; 1400 - subsys = nvmet_find_get_subsys(req->port, subsysnqn); 1398 + args->status = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR; 1399 + subsys = nvmet_find_get_subsys(args->port, args->subsysnqn); 1401 1400 if (!subsys) { 1402 1401 pr_warn("connect request for invalid subsystem %s!\n", 1403 - subsysnqn); 1404 - req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(subsysnqn); 1405 - req->error_loc = offsetof(struct nvme_common_command, dptr); 1406 - goto out; 1402 + args->subsysnqn); 1403 + args->result = IPO_IATTR_CONNECT_DATA(subsysnqn); 1404 + args->error_loc = offsetof(struct nvme_common_command, dptr); 1405 + return NULL; 1407 1406 } 1408 1407 1409 1408 down_read(&nvmet_config_sem); 1410 - if (!nvmet_host_allowed(subsys, hostnqn)) { 1409 + if (!nvmet_host_allowed(subsys, args->hostnqn)) { 1411 1410 pr_info("connect by host %s for subsystem %s not allowed\n", 1412 - hostnqn, subsysnqn); 1413 - req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(hostnqn); 1411 + args->hostnqn, args->subsysnqn); 1412 + args->result = IPO_IATTR_CONNECT_DATA(hostnqn); 1414 1413 up_read(&nvmet_config_sem); 1415 - status = NVME_SC_CONNECT_INVALID_HOST | NVME_STATUS_DNR; 1416 - req->error_loc = offsetof(struct nvme_common_command, dptr); 1414 + args->status = NVME_SC_CONNECT_INVALID_HOST | NVME_STATUS_DNR; 1415 + args->error_loc = offsetof(struct nvme_common_command, dptr); 1417 1416 goto out_put_subsystem; 1418 1417 } 1419 1418 up_read(&nvmet_config_sem); 1420 1419 1421 - status = NVME_SC_INTERNAL; 1420 + args->status = NVME_SC_INTERNAL; 1422 1421 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 1423 1422 if (!ctrl) 1424 1423 goto out_put_subsystem; 1425 1424 mutex_init(&ctrl->lock); 1426 1425 1427 - ctrl->port = req->port; 1428 - ctrl->ops = req->ops; 1426 + ctrl->port = args->port; 1427 + ctrl->ops = args->ops; 1429 1428 1430 1429 #ifdef CONFIG_NVME_TARGET_PASSTHRU 1431 1430 /* By default, set loop targets to clear IDS by default */ ··· 1438 1439 INIT_WORK(&ctrl->fatal_err_work, nvmet_fatal_error_handler); 1439 1440 INIT_DELAYED_WORK(&ctrl->ka_work, nvmet_keep_alive_timer); 1440 1441 1441 - memcpy(ctrl->subsysnqn, subsysnqn, NVMF_NQN_SIZE); 1442 - memcpy(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE); 1442 + memcpy(ctrl->subsysnqn, args->subsysnqn, NVMF_NQN_SIZE); 1443 + memcpy(ctrl->hostnqn, args->hostnqn, NVMF_NQN_SIZE); 1443 1444 1444 1445 kref_init(&ctrl->ref); 1445 1446 ctrl->subsys = subsys; ··· 1462 1463 subsys->cntlid_min, subsys->cntlid_max, 1463 1464 GFP_KERNEL); 1464 1465 if (ret < 0) { 1465 - status = NVME_SC_CONNECT_CTRL_BUSY | NVME_STATUS_DNR; 1466 + args->status = NVME_SC_CONNECT_CTRL_BUSY | NVME_STATUS_DNR; 1466 1467 goto out_free_sqs; 1467 1468 } 1468 1469 ctrl->cntlid = ret; 1469 1470 1470 - uuid_copy(&ctrl->hostid, hostid); 1471 + uuid_copy(&ctrl->hostid, args->hostid); 1471 1472 1472 1473 /* 1473 1474 * Discovery controllers may use some arbitrary high value ··· 1489 1490 if (ret) 1490 1491 goto init_pr_fail; 1491 1492 list_add_tail(&ctrl->subsys_entry, &subsys->ctrls); 1492 - nvmet_setup_p2p_ns_map(ctrl, req); 1493 + nvmet_setup_p2p_ns_map(ctrl, args->p2p_client); 1493 1494 nvmet_debugfs_ctrl_setup(ctrl); 1494 1495 mutex_unlock(&subsys->lock); 1495 1496 1496 - *ctrlp = ctrl; 1497 - return 0; 1497 + if (args->hostid) 1498 + uuid_copy(&ctrl->hostid, args->hostid); 1499 + 1500 + dhchap_status = nvmet_setup_auth(ctrl); 1501 + if (dhchap_status) { 1502 + pr_err("Failed to setup authentication, dhchap status %u\n", 1503 + dhchap_status); 1504 + nvmet_ctrl_put(ctrl); 1505 + if (dhchap_status == NVME_AUTH_DHCHAP_FAILURE_FAILED) 1506 + args->status = 1507 + NVME_SC_CONNECT_INVALID_HOST | NVME_STATUS_DNR; 1508 + else 1509 + args->status = NVME_SC_INTERNAL; 1510 + return NULL; 1511 + } 1512 + 1513 + args->status = NVME_SC_SUCCESS; 1514 + 1515 + pr_info("Created %s controller %d for subsystem %s for NQN %s%s%s.\n", 1516 + nvmet_is_disc_subsys(ctrl->subsys) ? "discovery" : "nvm", 1517 + ctrl->cntlid, ctrl->subsys->subsysnqn, ctrl->hostnqn, 1518 + ctrl->pi_support ? " T10-PI is enabled" : "", 1519 + nvmet_has_auth(ctrl) ? " with DH-HMAC-CHAP" : ""); 1520 + 1521 + return ctrl; 1498 1522 1499 1523 init_pr_fail: 1500 1524 mutex_unlock(&subsys->lock); ··· 1531 1509 kfree(ctrl); 1532 1510 out_put_subsystem: 1533 1511 nvmet_subsys_put(subsys); 1534 - out: 1535 - return status; 1512 + return NULL; 1536 1513 } 1514 + EXPORT_SYMBOL_GPL(nvmet_alloc_ctrl); 1537 1515 1538 1516 static void nvmet_ctrl_free(struct kref *ref) 1539 1517 { ··· 1569 1547 { 1570 1548 kref_put(&ctrl->ref, nvmet_ctrl_free); 1571 1549 } 1550 + EXPORT_SYMBOL_GPL(nvmet_ctrl_put); 1572 1551 1573 1552 void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl) 1574 1553 {
+27 -33
drivers/nvme/target/fabrics-cmd.c
··· 213 213 struct nvmf_connect_command *c = &req->cmd->connect; 214 214 struct nvmf_connect_data *d; 215 215 struct nvmet_ctrl *ctrl = NULL; 216 - u16 status; 217 - u8 dhchap_status; 216 + struct nvmet_alloc_ctrl_args args = { 217 + .port = req->port, 218 + .ops = req->ops, 219 + .p2p_client = req->p2p_client, 220 + .kato = le32_to_cpu(c->kato), 221 + }; 218 222 219 223 if (!nvmet_check_transfer_len(req, sizeof(struct nvmf_connect_data))) 220 224 return; 221 225 222 226 d = kmalloc(sizeof(*d), GFP_KERNEL); 223 227 if (!d) { 224 - status = NVME_SC_INTERNAL; 228 + args.status = NVME_SC_INTERNAL; 225 229 goto complete; 226 230 } 227 231 228 - status = nvmet_copy_from_sgl(req, 0, d, sizeof(*d)); 229 - if (status) 232 + args.status = nvmet_copy_from_sgl(req, 0, d, sizeof(*d)); 233 + if (args.status) 230 234 goto out; 231 235 232 236 if (c->recfmt != 0) { 233 237 pr_warn("invalid connect version (%d).\n", 234 238 le16_to_cpu(c->recfmt)); 235 - req->error_loc = offsetof(struct nvmf_connect_command, recfmt); 236 - status = NVME_SC_CONNECT_FORMAT | NVME_STATUS_DNR; 239 + args.error_loc = offsetof(struct nvmf_connect_command, recfmt); 240 + args.status = NVME_SC_CONNECT_FORMAT | NVME_STATUS_DNR; 237 241 goto out; 238 242 } 239 243 240 244 if (unlikely(d->cntlid != cpu_to_le16(0xffff))) { 241 245 pr_warn("connect attempt for invalid controller ID %#x\n", 242 246 d->cntlid); 243 - status = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR; 244 - req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(cntlid); 247 + args.status = NVME_SC_CONNECT_INVALID_PARAM | NVME_STATUS_DNR; 248 + args.result = IPO_IATTR_CONNECT_DATA(cntlid); 245 249 goto out; 246 250 } 247 251 248 252 d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0'; 249 253 d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0'; 250 - status = nvmet_alloc_ctrl(d->subsysnqn, d->hostnqn, req, 251 - le32_to_cpu(c->kato), &ctrl, &d->hostid); 252 - if (status) 254 + 255 + args.subsysnqn = d->subsysnqn; 256 + args.hostnqn = d->hostnqn; 257 + args.hostid = &d->hostid; 258 + args.kato = c->kato; 259 + 260 + ctrl = nvmet_alloc_ctrl(&args); 261 + if (!ctrl) 253 262 goto out; 254 263 255 - dhchap_status = nvmet_setup_auth(ctrl); 256 - if (dhchap_status) { 257 - pr_err("Failed to setup authentication, dhchap status %u\n", 258 - dhchap_status); 259 - nvmet_ctrl_put(ctrl); 260 - if (dhchap_status == NVME_AUTH_DHCHAP_FAILURE_FAILED) 261 - status = (NVME_SC_CONNECT_INVALID_HOST | NVME_STATUS_DNR); 262 - else 263 - status = NVME_SC_INTERNAL; 264 - goto out; 265 - } 266 - 267 - status = nvmet_install_queue(ctrl, req); 268 - if (status) { 264 + args.status = nvmet_install_queue(ctrl, req); 265 + if (args.status) { 269 266 nvmet_ctrl_put(ctrl); 270 267 goto out; 271 268 } 272 269 273 - pr_info("creating %s controller %d for subsystem %s for NQN %s%s%s.\n", 274 - nvmet_is_disc_subsys(ctrl->subsys) ? "discovery" : "nvm", 275 - ctrl->cntlid, ctrl->subsys->subsysnqn, ctrl->hostnqn, 276 - ctrl->pi_support ? " T10-PI is enabled" : "", 277 - nvmet_has_auth(ctrl) ? " with DH-HMAC-CHAP" : ""); 278 - req->cqe->result.u32 = cpu_to_le32(nvmet_connect_result(ctrl)); 270 + args.result = cpu_to_le32(nvmet_connect_result(ctrl)); 279 271 out: 280 272 kfree(d); 281 273 complete: 282 - nvmet_req_complete(req, status); 274 + req->error_loc = args.error_loc; 275 + req->cqe->result.u32 = args.result; 276 + nvmet_req_complete(req, args.status); 283 277 } 284 278 285 279 static void nvmet_execute_io_connect(struct nvmet_req *req)
+15 -3
drivers/nvme/target/nvmet.h
··· 549 549 void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl); 550 550 551 551 void nvmet_update_cc(struct nvmet_ctrl *ctrl, u32 new); 552 - u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn, 553 - struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp, 554 - uuid_t *hostid); 552 + 553 + struct nvmet_alloc_ctrl_args { 554 + struct nvmet_port *port; 555 + char *subsysnqn; 556 + char *hostnqn; 557 + uuid_t *hostid; 558 + const struct nvmet_fabrics_ops *ops; 559 + struct device *p2p_client; 560 + u32 kato; 561 + u32 result; 562 + u16 error_loc; 563 + u16 status; 564 + }; 565 + 566 + struct nvmet_ctrl *nvmet_alloc_ctrl(struct nvmet_alloc_ctrl_args *args); 555 567 struct nvmet_ctrl *nvmet_ctrl_find_get(const char *subsysnqn, 556 568 const char *hostnqn, u16 cntlid, 557 569 struct nvmet_req *req);