Skip to content

Commit d0c6cc6

Browse files
committed
Merge tag 'nvme-6.12-2024-10-31' of git://git.infradead.org/nvme into block-6.12
Pull NVMe fixes from Keith: "nvme fixes for Linux 6.12 - Spec compliant identification fix (Keith) - Module parameter to enable backward compatibility on unusual namespace formats (Keith) - Target double free fix when using keys (Vitaliy) - Passthrough command error handling fix (Keith)" * tag 'nvme-6.12-2024-10-31' of git://git.infradead.org/nvme: nvme: re-fix error-handling for io_uring nvme-passthrough nvmet-auth: assign dh_key to NULL after kfree_sensitive nvme: module parameter to disable pi with offsets nvme: enhance cns version checking
2 parents be0e822 + 5eed4fb commit d0c6cc6

File tree

3 files changed

+48
-16
lines changed

3 files changed

+48
-16
lines changed

drivers/nvme/host/core.c

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ module_param(apst_secondary_latency_tol_us, ulong, 0644);
9191
MODULE_PARM_DESC(apst_secondary_latency_tol_us,
9292
"secondary APST latency tolerance in us");
9393

94+
/*
95+
* Older kernels didn't enable protection information if it was at an offset.
96+
* Newer kernels do, so it breaks reads on the upgrade if such formats were
97+
* used in prior kernels since the metadata written did not contain a valid
98+
* checksum.
99+
*/
100+
static bool disable_pi_offsets = false;
101+
module_param(disable_pi_offsets, bool, 0444);
102+
MODULE_PARM_DESC(disable_pi_offsets,
103+
"disable protection information if it has an offset");
104+
94105
/*
95106
* nvme_wq - hosts nvme related works that are not reset or delete
96107
* nvme_reset_wq - hosts nvme reset works
@@ -1390,17 +1401,30 @@ static void nvme_update_keep_alive(struct nvme_ctrl *ctrl,
13901401
nvme_start_keep_alive(ctrl);
13911402
}
13921403

1393-
/*
1394-
* In NVMe 1.0 the CNS field was just a binary controller or namespace
1395-
* flag, thus sending any new CNS opcodes has a big chance of not working.
1396-
* Qemu unfortunately had that bug after reporting a 1.1 version compliance
1397-
* (but not for any later version).
1398-
*/
1399-
static bool nvme_ctrl_limited_cns(struct nvme_ctrl *ctrl)
1404+
static bool nvme_id_cns_ok(struct nvme_ctrl *ctrl, u8 cns)
14001405
{
1401-
if (ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)
1402-
return ctrl->vs < NVME_VS(1, 2, 0);
1403-
return ctrl->vs < NVME_VS(1, 1, 0);
1406+
/*
1407+
* The CNS field occupies a full byte starting with NVMe 1.2
1408+
*/
1409+
if (ctrl->vs >= NVME_VS(1, 2, 0))
1410+
return true;
1411+
1412+
/*
1413+
* NVMe 1.1 expanded the CNS value to two bits, which means values
1414+
* larger than that could get truncated and treated as an incorrect
1415+
* value.
1416+
*
1417+
* Qemu implemented 1.0 behavior for controllers claiming 1.1
1418+
* compliance, so they need to be quirked here.
1419+
*/
1420+
if (ctrl->vs >= NVME_VS(1, 1, 0) &&
1421+
!(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS))
1422+
return cns <= 3;
1423+
1424+
/*
1425+
* NVMe 1.0 used a single bit for the CNS value.
1426+
*/
1427+
return cns <= 1;
14041428
}
14051429

14061430
static int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
@@ -1913,8 +1937,12 @@ static void nvme_configure_metadata(struct nvme_ctrl *ctrl,
19131937

19141938
if (head->pi_size && head->ms >= head->pi_size)
19151939
head->pi_type = id->dps & NVME_NS_DPS_PI_MASK;
1916-
if (!(id->dps & NVME_NS_DPS_PI_FIRST))
1917-
info->pi_offset = head->ms - head->pi_size;
1940+
if (!(id->dps & NVME_NS_DPS_PI_FIRST)) {
1941+
if (disable_pi_offsets)
1942+
head->pi_type = 0;
1943+
else
1944+
info->pi_offset = head->ms - head->pi_size;
1945+
}
19181946

19191947
if (ctrl->ops->flags & NVME_F_FABRICS) {
19201948
/*
@@ -3104,7 +3132,7 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl)
31043132
ctrl->max_zeroes_sectors = 0;
31053133

31063134
if (ctrl->subsys->subtype != NVME_NQN_NVME ||
3107-
nvme_ctrl_limited_cns(ctrl) ||
3135+
!nvme_id_cns_ok(ctrl, NVME_ID_CNS_CS_CTRL) ||
31083136
test_bit(NVME_CTRL_SKIP_ID_CNS_CS, &ctrl->flags))
31093137
return 0;
31103138

@@ -4200,7 +4228,7 @@ static void nvme_scan_work(struct work_struct *work)
42004228
}
42014229

42024230
mutex_lock(&ctrl->scan_lock);
4203-
if (nvme_ctrl_limited_cns(ctrl)) {
4231+
if (!nvme_id_cns_ok(ctrl, NVME_ID_CNS_NS_ACTIVE_LIST)) {
42044232
nvme_scan_ns_sequential(ctrl);
42054233
} else {
42064234
/*

drivers/nvme/host/ioctl.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,13 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
421421
struct io_uring_cmd *ioucmd = req->end_io_data;
422422
struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
423423

424-
if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
424+
if (nvme_req(req)->flags & NVME_REQ_CANCELLED) {
425425
pdu->status = -EINTR;
426-
else
426+
} else {
427427
pdu->status = nvme_req(req)->status;
428+
if (!pdu->status)
429+
pdu->status = blk_status_to_errno(err);
430+
}
428431
pdu->result = le64_to_cpu(nvme_req(req)->result.u64);
429432

430433
/*

drivers/nvme/target/auth.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, u8 dhgroup_id)
115115
pr_debug("%s: ctrl %d failed to generate private key, err %d\n",
116116
__func__, ctrl->cntlid, ret);
117117
kfree_sensitive(ctrl->dh_key);
118+
ctrl->dh_key = NULL;
118119
return ret;
119120
}
120121
ctrl->dh_keysize = crypto_kpp_maxsize(ctrl->dh_tfm);

0 commit comments

Comments
 (0)