Skip to content

Commit aa03cfe

Browse files
committed
Merge tag 'nvme-7.1-2026-04-24' of git://git.infradead.org/nvme into block-7.1
Pull NVMe fixes from Keith: "- Target data transfer size confiruation (Aurelien) - Enable P2P for RDMA (Shivaji Kant) - TCP target updates (Maurizio, Alistair, Chaitanya, Shivam Kumar) - TCP host updates (Alistair, Chaitanya) - Authentication updates (Alistair, Daniel, Chris Leech) - Multipath fixes (John Garry) - New quirks (Alan Cui, Tao Jiang) - Apple driver fix (Fedor Pchelkin) - PCI admin doorbell update fix (Keith)" * tag 'nvme-7.1-2026-04-24' of git://git.infradead.org/nvme: (22 commits) nvme-auth: Hash DH shared secret to create session key nvme-pci: fix missed admin queue sq doorbell write nvme-auth: Include SC_C in RVAL controller hash nvme-tcp: teardown circular locking fixes nvmet-tcp: Don't clear tls_key when freeing sq Revert "nvmet-tcp: Don't free SQ on authentication success" nvme: skip trace completion for host path errors nvme-pci: add quirk for Memblaze Pblaze5 (0x1c5f:0x0555) nvme-multipath: put module reference when delayed removal work is canceled nvme: expose TLS mode nvme-apple: drop invalid put of admin queue reference count nvme-core: fix parameter name in comment nvmet: avoid recursive nvmet-wq flush in nvmet_ctrl_free nvme-multipath: drop head pointer check in nvme_mpath_clear_current_path() nvme: add quirk NVME_QUIRK_IGNORE_DEV_SUBNQN for 144d:a808 (Samsung PM981/983/970 EVO Plus ) nvmet-tcp: fix race between ICReq handling and queue teardown nvmet-tcp: remove redundant calls to nvmet_tcp_fatal_error() nvmet-tcp: propagate nvmet_tcp_build_pdu_iovec() errors to its callers nvme: enable PCI P2PDMA support for RDMA transport nvmet: introduce new mdts configuration entry ...
2 parents 254f496 + bd7b7ce commit aa03cfe

19 files changed

Lines changed: 285 additions & 131 deletions

File tree

drivers/nvme/common/auth.c

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -351,18 +351,29 @@ struct nvme_dhchap_key *nvme_auth_transform_key(
351351
}
352352
EXPORT_SYMBOL_GPL(nvme_auth_transform_key);
353353

354+
/**
355+
* nvme_auth_augmented_challenge() - Compute the augmented DH-HMAC-CHAP challenge
356+
* @hmac_id: Hash algorithm identifier
357+
* @skey: Session key
358+
* @skey_len: Length of @skey
359+
* @challenge: Challenge value
360+
* @aug: Output buffer for the augmented challenge
361+
* @hlen: Hash output length (length of @challenge and @aug)
362+
*
363+
* NVMe base specification 8.3.5.5.4: The augmented challenge is computed
364+
* applying the HMAC function using the hash function H() selected by the
365+
* HashID parameter ... with the hash of the ephemeral DH key ... as HMAC key
366+
* to the challenge C (i.e., Ca = HMAC(H(g^xy mod p), C)).
367+
*
368+
* As the session key skey is already H(g^xy mod p) per section 8.3.5.5.9, use
369+
* it directly as the HMAC key without additional hashing.
370+
*
371+
* Return: 0 on success, negative errno on failure.
372+
*/
354373
int nvme_auth_augmented_challenge(u8 hmac_id, const u8 *skey, size_t skey_len,
355374
const u8 *challenge, u8 *aug, size_t hlen)
356375
{
357-
u8 hashed_key[NVME_AUTH_MAX_DIGEST_SIZE];
358-
int ret;
359-
360-
ret = nvme_auth_hash(hmac_id, skey, skey_len, hashed_key);
361-
if (ret)
362-
return ret;
363-
ret = nvme_auth_hmac(hmac_id, hashed_key, hlen, challenge, hlen, aug);
364-
memzero_explicit(hashed_key, sizeof(hashed_key));
365-
return ret;
376+
return nvme_auth_hmac(hmac_id, skey, skey_len, challenge, hlen, aug);
366377
}
367378
EXPORT_SYMBOL_GPL(nvme_auth_augmented_challenge);
368379

@@ -403,33 +414,76 @@ int nvme_auth_gen_pubkey(struct crypto_kpp *dh_tfm,
403414
}
404415
EXPORT_SYMBOL_GPL(nvme_auth_gen_pubkey);
405416

406-
int nvme_auth_gen_shared_secret(struct crypto_kpp *dh_tfm,
407-
const u8 *ctrl_key, size_t ctrl_key_len,
408-
u8 *sess_key, size_t sess_key_len)
417+
/**
418+
* nvme_auth_gen_session_key() - Generate an ephemeral session key
419+
* @dh_tfm: Diffie-Hellman transform with local private key already set
420+
* @public_key: Peer's public key
421+
* @public_key_len: Length of @public_key
422+
* @sess_key: Output buffer for the session key
423+
* @sess_key_len: Size of @sess_key buffer
424+
* @hash_id: Hash algorithm identifier
425+
*
426+
* NVMe base specification 8.3.5.5.9: The session key Ks shall be computed from
427+
* the ephemeral DH key (i.e., g^xy mod p) ... by applying the hash function
428+
* H() selected by the HashID parameter ... (i.e., Ks = H(g^xy mod p)).
429+
*
430+
* Return: 0 on success, negative errno on failure.
431+
*/
432+
int nvme_auth_gen_session_key(struct crypto_kpp *dh_tfm,
433+
const u8 *public_key, size_t public_key_len,
434+
u8 *sess_key, size_t sess_key_len, u8 hash_id)
409435
{
410436
struct kpp_request *req;
411437
struct crypto_wait wait;
412438
struct scatterlist src, dst;
439+
u8 *dh_secret;
440+
size_t dh_secret_len, hash_len;
413441
int ret;
414442

415-
req = kpp_request_alloc(dh_tfm, GFP_KERNEL);
416-
if (!req)
443+
hash_len = nvme_auth_hmac_hash_len(hash_id);
444+
if (!hash_len) {
445+
pr_warn("%s: invalid hash algorithm %d\n", __func__, hash_id);
446+
return -EINVAL;
447+
}
448+
449+
if (sess_key_len != hash_len) {
450+
pr_warn("%s: sess_key buffer missized (%zu != %zu)\n",
451+
__func__, sess_key_len, hash_len);
452+
return -EINVAL;
453+
}
454+
455+
dh_secret_len = crypto_kpp_maxsize(dh_tfm);
456+
dh_secret = kzalloc(dh_secret_len, GFP_KERNEL);
457+
if (!dh_secret)
417458
return -ENOMEM;
418459

460+
req = kpp_request_alloc(dh_tfm, GFP_KERNEL);
461+
if (!req) {
462+
ret = -ENOMEM;
463+
goto out_free_secret;
464+
}
465+
419466
crypto_init_wait(&wait);
420-
sg_init_one(&src, ctrl_key, ctrl_key_len);
421-
kpp_request_set_input(req, &src, ctrl_key_len);
422-
sg_init_one(&dst, sess_key, sess_key_len);
423-
kpp_request_set_output(req, &dst, sess_key_len);
467+
sg_init_one(&src, public_key, public_key_len);
468+
kpp_request_set_input(req, &src, public_key_len);
469+
sg_init_one(&dst, dh_secret, dh_secret_len);
470+
kpp_request_set_output(req, &dst, dh_secret_len);
424471
kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
425472
crypto_req_done, &wait);
426473

427474
ret = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);
428-
429475
kpp_request_free(req);
476+
477+
if (ret)
478+
goto out_free_secret;
479+
480+
ret = nvme_auth_hash(hash_id, dh_secret, dh_secret_len, sess_key);
481+
482+
out_free_secret:
483+
kfree_sensitive(dh_secret);
430484
return ret;
431485
}
432-
EXPORT_SYMBOL_GPL(nvme_auth_gen_shared_secret);
486+
EXPORT_SYMBOL_GPL(nvme_auth_gen_session_key);
433487

434488
int nvme_auth_parse_key(const char *secret, struct nvme_dhchap_key **ret_key)
435489
{

drivers/nvme/host/apple.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,11 +1267,7 @@ static int apple_nvme_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
12671267

12681268
static void apple_nvme_free_ctrl(struct nvme_ctrl *ctrl)
12691269
{
1270-
struct apple_nvme *anv = ctrl_to_apple_nvme(ctrl);
1271-
1272-
if (anv->ctrl.admin_q)
1273-
blk_put_queue(anv->ctrl.admin_q);
1274-
put_device(anv->dev);
1270+
put_device(ctrl->dev);
12751271
}
12761272

12771273
static const struct nvme_ctrl_ops nvme_ctrl_ops = {

drivers/nvme/host/auth.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,12 @@ static int nvme_auth_dhchap_setup_ctrl_response(struct nvme_ctrl *ctrl,
535535
put_unaligned_le16(chap->transaction, buf);
536536
nvme_auth_hmac_update(&hmac, buf, 2);
537537

538-
memset(buf, 0, 4);
538+
*buf = chap->sc_c;
539539
nvme_auth_hmac_update(&hmac, buf, 1);
540540
nvme_auth_hmac_update(&hmac, "Controller", 10);
541541
nvme_auth_hmac_update(&hmac, ctrl->opts->subsysnqn,
542542
strlen(ctrl->opts->subsysnqn));
543+
memset(buf, 0, 4);
543544
nvme_auth_hmac_update(&hmac, buf, 1);
544545
nvme_auth_hmac_update(&hmac, ctrl->opts->host->nqn,
545546
strlen(ctrl->opts->host->nqn));
@@ -587,24 +588,25 @@ static int nvme_auth_dhchap_exponential(struct nvme_ctrl *ctrl,
587588
}
588589

589590
gen_sesskey:
590-
chap->sess_key_len = chap->host_key_len;
591+
chap->sess_key_len = chap->hash_len;
591592
chap->sess_key = kmalloc(chap->sess_key_len, GFP_KERNEL);
592593
if (!chap->sess_key) {
593594
chap->sess_key_len = 0;
594595
chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
595596
return -ENOMEM;
596597
}
597598

598-
ret = nvme_auth_gen_shared_secret(chap->dh_tfm,
599-
chap->ctrl_key, chap->ctrl_key_len,
600-
chap->sess_key, chap->sess_key_len);
599+
ret = nvme_auth_gen_session_key(chap->dh_tfm,
600+
chap->ctrl_key, chap->ctrl_key_len,
601+
chap->sess_key, chap->sess_key_len,
602+
chap->hash_id);
601603
if (ret) {
602604
dev_dbg(ctrl->device,
603-
"failed to generate shared secret, error %d\n", ret);
605+
"failed to generate session key, error %d\n", ret);
604606
chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
605607
return ret;
606608
}
607-
dev_dbg(ctrl->device, "shared secret %*ph\n",
609+
dev_dbg(ctrl->device, "session key %*ph\n",
608610
(int)chap->sess_key_len, chap->sess_key);
609611
return 0;
610612
}

drivers/nvme/host/core.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,10 @@ void nvme_end_req(struct request *req)
454454
blk_mq_end_request(req, status);
455455
}
456456

457-
void nvme_complete_rq(struct request *req)
457+
static void __nvme_complete_rq(struct request *req)
458458
{
459459
struct nvme_ctrl *ctrl = nvme_req(req)->ctrl;
460460

461-
trace_nvme_complete_rq(req);
462461
nvme_cleanup_cmd(req);
463462

464463
/*
@@ -493,6 +492,12 @@ void nvme_complete_rq(struct request *req)
493492
return;
494493
}
495494
}
495+
496+
void nvme_complete_rq(struct request *req)
497+
{
498+
trace_nvme_complete_rq(req);
499+
__nvme_complete_rq(req);
500+
}
496501
EXPORT_SYMBOL_GPL(nvme_complete_rq);
497502

498503
void nvme_complete_batch_req(struct request *req)
@@ -513,7 +518,7 @@ blk_status_t nvme_host_path_error(struct request *req)
513518
{
514519
nvme_req(req)->status = NVME_SC_HOST_PATH_ERROR;
515520
blk_mq_set_request_complete(req);
516-
nvme_complete_rq(req);
521+
__nvme_complete_rq(req);
517522
return BLK_STS_OK;
518523
}
519524
EXPORT_SYMBOL_GPL(nvme_host_path_error);
@@ -3044,7 +3049,7 @@ static const struct nvme_core_quirk_entry core_quirks[] = {
30443049
*
30453050
* The device is left in a state where it is also not possible
30463051
* to use "nvme set-feature" to disable APST, but booting with
3047-
* nvme_core.default_ps_max_latency=0 works.
3052+
* nvme_core.default_ps_max_latency_us=0 works.
30483053
*/
30493054
.vid = 0x1e0f,
30503055
.mn = "KCD6XVUL6T40",
@@ -4083,7 +4088,8 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
40834088
mutex_unlock(&ctrl->subsys->lock);
40844089

40854090
#ifdef CONFIG_NVME_MULTIPATH
4086-
cancel_delayed_work(&head->remove_work);
4091+
if (cancel_delayed_work(&head->remove_work))
4092+
module_put(THIS_MODULE);
40874093
#endif
40884094
return 0;
40894095

drivers/nvme/host/fc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3968,3 +3968,4 @@ module_exit(nvme_fc_exit_module);
39683968

39693969
MODULE_DESCRIPTION("NVMe host FC transport driver");
39703970
MODULE_LICENSE("GPL v2");
3971+
MODULE_ALIAS("nvme-fc");

drivers/nvme/host/multipath.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -231,16 +231,12 @@ bool nvme_mpath_clear_current_path(struct nvme_ns *ns)
231231
bool changed = false;
232232
int node;
233233

234-
if (!head)
235-
goto out;
236-
237234
for_each_node(node) {
238235
if (ns == rcu_access_pointer(head->current_path[node])) {
239236
rcu_assign_pointer(head->current_path[node], NULL);
240237
changed = true;
241238
}
242239
}
243-
out:
244240
return changed;
245241
}
246242

drivers/nvme/host/pci.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,6 +2241,7 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid, bool polled)
22412241
static const struct blk_mq_ops nvme_mq_admin_ops = {
22422242
.queue_rq = nvme_queue_rq,
22432243
.complete = nvme_pci_complete_rq,
2244+
.commit_rqs = nvme_commit_rqs,
22442245
.init_hctx = nvme_admin_init_hctx,
22452246
.init_request = nvme_pci_init_request,
22462247
.timeout = nvme_timeout,
@@ -4104,6 +4105,10 @@ static const struct pci_device_id nvme_id_table[] = {
41044105
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
41054106
{ PCI_DEVICE(0x1c5f, 0x0540), /* Memblaze Pblaze4 adapter */
41064107
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
4108+
{ PCI_DEVICE(0x1c5f, 0x0555), /* Memblaze Pblaze5 adapter */
4109+
.driver_data = NVME_QUIRK_NO_NS_DESC_LIST, },
4110+
{ PCI_DEVICE(0x144d, 0xa808), /* Samsung PM981/983 */
4111+
.driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
41074112
{ PCI_DEVICE(0x144d, 0xa821), /* Samsung PM1725 */
41084113
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
41094114
{ PCI_DEVICE(0x144d, 0xa822), /* Samsung PM1725a */

drivers/nvme/host/rdma.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,6 +2189,13 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
21892189
nvme_rdma_reconnect_or_remove(ctrl, ret);
21902190
}
21912191

2192+
static bool nvme_rdma_supports_pci_p2pdma(struct nvme_ctrl *ctrl)
2193+
{
2194+
struct nvme_rdma_ctrl *r_ctrl = to_rdma_ctrl(ctrl);
2195+
2196+
return ib_dma_pci_p2p_dma_supported(r_ctrl->device->dev);
2197+
}
2198+
21922199
static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
21932200
.name = "rdma",
21942201
.module = THIS_MODULE,
@@ -2203,6 +2210,7 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
22032210
.get_address = nvmf_get_address,
22042211
.stop_ctrl = nvme_rdma_stop_ctrl,
22052212
.get_virt_boundary = nvme_get_virt_boundary,
2213+
.supports_pci_p2pdma = nvme_rdma_supports_pci_p2pdma,
22062214
};
22072215

22082216
/*
@@ -2432,3 +2440,4 @@ module_exit(nvme_rdma_cleanup_module);
24322440

24332441
MODULE_DESCRIPTION("NVMe host RDMA transport driver");
24342442
MODULE_LICENSE("GPL v2");
2443+
MODULE_ALIAS("nvme-rdma");

drivers/nvme/host/sysfs.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,10 +883,26 @@ static ssize_t tls_keyring_show(struct device *dev,
883883
}
884884
static DEVICE_ATTR_RO(tls_keyring);
885885

886+
static ssize_t tls_mode_show(struct device *dev,
887+
struct device_attribute *attr, char *buf)
888+
{
889+
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
890+
const char *mode;
891+
892+
if (ctrl->opts->tls)
893+
mode = "tls";
894+
else
895+
mode = "concat";
896+
897+
return sysfs_emit(buf, "%s\n", mode);
898+
}
899+
static DEVICE_ATTR_RO(tls_mode);
900+
886901
static struct attribute *nvme_tls_attrs[] = {
887902
&dev_attr_tls_key.attr,
888903
&dev_attr_tls_configured_key.attr,
889904
&dev_attr_tls_keyring.attr,
905+
&dev_attr_tls_mode.attr,
890906
NULL,
891907
};
892908

@@ -908,6 +924,9 @@ static umode_t nvme_tls_attrs_are_visible(struct kobject *kobj,
908924
if (a == &dev_attr_tls_keyring.attr &&
909925
!ctrl->opts->keyring)
910926
return 0;
927+
if (a == &dev_attr_tls_mode.attr &&
928+
!ctrl->opts->tls && !ctrl->opts->concat)
929+
return 0;
911930

912931
return a->mode;
913932
}

drivers/nvme/host/tcp.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,18 +1438,32 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid)
14381438
{
14391439
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
14401440
struct nvme_tcp_queue *queue = &ctrl->queues[qid];
1441-
unsigned int noreclaim_flag;
1441+
unsigned int noio_flag;
14421442

14431443
if (!test_and_clear_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
14441444
return;
14451445

14461446
page_frag_cache_drain(&queue->pf_cache);
14471447

1448-
noreclaim_flag = memalloc_noreclaim_save();
1449-
/* ->sock will be released by fput() */
1450-
fput(queue->sock->file);
1448+
/**
1449+
* Prevent memory reclaim from triggering block I/O during socket
1450+
* teardown. The socket release path fput -> tcp_close ->
1451+
* tcp_disconnect -> tcp_send_active_reset may allocate memory, and
1452+
* allowing reclaim to issue I/O could deadlock if we're being called
1453+
* from block device teardown (e.g., del_gendisk -> elevator cleanup)
1454+
* which holds locks that the I/O completion path needs.
1455+
*/
1456+
noio_flag = memalloc_noio_save();
1457+
1458+
/**
1459+
* Release the socket synchronously. During reset in
1460+
* nvme_reset_ctrl_work(), queue teardown is immediately followed by
1461+
* re-allocation. fput() defers socket cleanup to delayed_fput_work
1462+
* in workqueue context, which can race with new queue setup.
1463+
*/
1464+
__fput_sync(queue->sock->file);
14511465
queue->sock = NULL;
1452-
memalloc_noreclaim_restore(noreclaim_flag);
1466+
memalloc_noio_restore(noio_flag);
14531467

14541468
kfree(queue->pdu);
14551469
mutex_destroy(&queue->send_mutex);
@@ -1901,8 +1915,8 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
19011915
err_rcv_pdu:
19021916
kfree(queue->pdu);
19031917
err_sock:
1904-
/* ->sock will be released by fput() */
1905-
fput(queue->sock->file);
1918+
/* Use sync variant - see nvme_tcp_free_queue() for explanation */
1919+
__fput_sync(queue->sock->file);
19061920
queue->sock = NULL;
19071921
err_destroy_mutex:
19081922
mutex_destroy(&queue->send_mutex);
@@ -3071,3 +3085,4 @@ module_exit(nvme_tcp_cleanup_module);
30713085

30723086
MODULE_DESCRIPTION("NVMe host TCP transport driver");
30733087
MODULE_LICENSE("GPL v2");
3088+
MODULE_ALIAS("nvme-tcp");

0 commit comments

Comments
 (0)