mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 04:23:03 +02:00
nvme fixes for Linux 7.3
- Harden the tcp host and target against malformed PDUs: reject C2HData
for a non-read command, bound an over-long PDU before copying it, and
reject unsolicited H2CData (Yehyeong, Shivam)
- Fix circular locking on TLS queues (Xixin)
- Fix a soft lockup when scanning sparse namespace ID space (Mohamed)
- Fix racy access to the FDP placement id array (Kanchan)
- RDMA host and target fixes for a double cleanup on the queue_rq
error path and a queue leak when the connect backlog is exceeded
(Xixin)
- Authentication fixes: drain the target's expiry work before the SQ
is freed, and release the DH-CHAP secret when parsing fails (Kazuki,
Xu Rao)
- Fix nvme-fc options double free when nvme_add_ctrl() fails (Niklas)
- Add missing SRCU grace period to nvme_alloc_ns() error path (Tristan)
- Skip zoned limits update when the zone info query failed (Chao)
- Reject enabling a target namespace with no device path (Seokgyu)
- Add opcode filtering for fault injection (Mohamed)
- Drop the kernel-doc comments from nvme-tcp.h (Randy)
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEE3Fbyvv+648XNRdHTPe3zGtjzRgkFAmqZ46MACgkQPe3zGtjz
RglHuRAAhB+37HZ4wsYuwIud6IwF4rrXMv/EU1C87Nt6ORXiTG892ECT+4G4ruZo
GTxFl6UB+i8GRw+RivMpZAWoLtEclU1GZ/ijPpgQ4+QKva60q29/2oQQiqT+x5us
Nhez9uuC1hywxY+HfVDfvx44ISXwPG/8ZTrGMfuEO8kbmiczY8X5LxnSicgWLTc8
PTdXvSDw5mtinzCPozRDVuFRTcDwUhM3NzVIv7MVXgEyY1sCwcPbmj8GdCkFco1G
WnIpWP3WplnO7yNcwMN+sSFvq8PjBFfW+LJ/25WRLQFvTpF5zwejPXNWPt90USU4
hA9kXua1CRHuApKUeNSLMQ3PG2pbB+NjIN31ZpBnveXplmIudoQuT+wLwltBg3te
9doRCqCGLMCNu+qPFquUOOr9+6+36pBlFTynNy5WGqen0YwY4/UEG4PEU649J3Ve
N10KY+ttHgi3bY6JdcCVlDhdzGW/rSobNz1GL4IpqPcYdZsvMqSyLrQpZfdKfp5m
4KWYyiVmydq6ixHpZF1yEM9y2+RZGi9AtOi6CCY5pNDt7lS257htsNSTX9T3pWcH
IeknLIuseNEW1IgUa7RPUrEkQJsiQx7eb6wI13otJULA60T40rISshuC8yGZblni
4zu5PQiaecjqXSWQfenEi6tvPuu9jV7YsuvK5x5qs21DnFy7pUo=
=YJ4v
-----END PGP SIGNATURE-----
Merge tag 'nvme-7.3-2026-09-03' of git://git.infradead.org/nvme into block-7.3
Pull NVMe fixes from Keith:
"- Harden the tcp host and target against malformed PDUs: reject C2HData
for a non-read command, bound an over-long PDU before copying it, and
reject unsolicited H2CData (Yehyeong, Shivam)
- Fix circular locking on TLS queues (Xixin)
- Fix a soft lockup when scanning sparse namespace ID space (Mohamed)
- Fix racy access to the FDP placement id array (Kanchan)
- RDMA host and target fixes for a double cleanup on the queue_rq
error path and a queue leak when the connect backlog is exceeded
(Xixin)
- Authentication fixes: drain the target's expiry work before the SQ
is freed, and release the DH-CHAP secret when parsing fails (Kazuki,
Xu Rao)
- Fix nvme-fc options double free when nvme_add_ctrl() fails (Niklas)
- Add missing SRCU grace period to nvme_alloc_ns() error path (Tristan)
- Skip zoned limits update when the zone info query failed (Chao)
- Reject enabling a target namespace with no device path (Seokgyu)
- Add opcode filtering for fault injection (Mohamed)
- Drop the kernel-doc comments from nvme-tcp.h (Randy)"
* tag 'nvme-7.3-2026-09-03' of git://git.infradead.org/nvme: (21 commits)
nvme-tcp.h: drop kernel-doc comments, fix a few descriptions
nvme-fc: fix double free of fabrics options when nvme_add_ctrl() fails
nvmet: reject namespace enable without device path
nvmet-auth: Synchronize timeout work during SQ teardown
MAINTAINERS: update nvme entry
nvmet-tcp: reject unsolicited H2CData PDUs
nvme-tcp: defer TLS inline send to io_work
nvmet-tcp: fix out-of-bounds write when receiving an over-long PDU
nvme-tcp: return -EPROTO for a C2HData on a write
nvmet: print namespace IDs as unsigned 32bit value
nvme: print namespace IDs as unsigned 32bit value
nvme: remove stale namespaces by NSID range during scan
nvme: add missing SRCU grace period in error path
nvme-fabrics: fix DHCHAP secret leak on parse failure
nvmet-rdma: fix queue leak when connect backlog is exceeded
nvme: add opcode filtering for fault injection
nvme: fix racy access to FDP placement id array
nvme: set ns->head in nvme_alloc_ns_head
nvme-rdma: fix -EIO cleanup order in queue_rq
nvme: skip the zoned limits update if the zone info query failed
...
This commit is contained in:
commit
00ef2248c5
|
|
@ -176,3 +176,68 @@ Message from dmesg::
|
|||
secondary_startup_64+0xa4/0xb0
|
||||
nvme nvme0: Could not set queue count (16385)
|
||||
nvme nvme0: IO queues not created
|
||||
|
||||
Example 4: Inject an error into the first write command
|
||||
-------------------------------------------------------
|
||||
|
||||
::
|
||||
|
||||
echo 0x01 > /sys/kernel/debug/nvme0n1/fault_inject/opcode
|
||||
echo 1 > /sys/kernel/debug/nvme0n1/fault_inject/times
|
||||
echo 100 > /sys/kernel/debug/nvme0n1/fault_inject/probability
|
||||
dd if=/dev/zero of=/dev/nvme0n1 oflag=direct bs=512 count=1
|
||||
|
||||
Expected Result::
|
||||
|
||||
The first write command sent to nvme0n1 fails
|
||||
|
||||
Message from dmesg::
|
||||
|
||||
FAULT_INJECTION: forcing a failure.
|
||||
name fault_inject, interval 1, probability 100, space 0, times 1
|
||||
CPU: 4 UID: 0 PID: 0 Comm: swapper/4 Not tainted 7.1.0+ #5 PREEMPT(full)
|
||||
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-20240910_120124-localhost 04/01/2014
|
||||
Call Trace:
|
||||
<IRQ>
|
||||
dump_stack_lvl+0x6e/0xa0
|
||||
dump_stack+0x10/0x16
|
||||
should_fail_ex+0x461/0x510
|
||||
should_fail+0xb/0x20
|
||||
nvme_should_fail+0x11b/0x240 [nvme_core]
|
||||
nvme_poll_cq+0x6ad/0xb30 [nvme]
|
||||
nvme_irq+0x84/0xe0 [nvme]
|
||||
? __pfx_nvme_irq+0x10/0x10 [nvme]
|
||||
? rcu_core+0xa40/0xa90
|
||||
? __pfx_sched_balance_softirq+0x10/0x10
|
||||
? debug_smp_processor_id+0x17/0x20
|
||||
? rcu_is_watching+0x13/0xa0
|
||||
__handle_irq_event_percpu+0x396/0x610
|
||||
handle_irq_event_percpu+0xf/0x90
|
||||
handle_irq_event+0xab/0x110
|
||||
handle_edge_irq+0x1a3/0x210
|
||||
__common_interrupt+0xff/0x170
|
||||
common_interrupt+0x90/0xc0
|
||||
</IRQ>
|
||||
<TASK>
|
||||
asm_common_interrupt+0x27/0x40
|
||||
RIP: 0010:pv_native_safe_halt+0x13/0x20
|
||||
Code: 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 8b 05 0a 2a 58 01 85 c0 7e 07 0f 00 2d ff cc 0d 00 fb f4 <c3> cc 0
|
||||
RSP: 0018:ffff888100a67e40 EFLAGS: 00000242
|
||||
RAX: 0000000000000001 RBX: ffff888100a49c40 RCX: ffffed102b6c645b
|
||||
RDX: ffffed102b6c645b RSI: ffffffff82a0d3c0 RDI: ffffffff81428b9b
|
||||
RBP: ffff888100a67e48 R08: ffffed102b6c645b R09: 0000000000000004
|
||||
R10: ffffed102b6c645a R11: 0000000000000001 R12: 0000000000000000
|
||||
R13: 0000000000000000 R14: ffffed1020149388 R15: dffffc0000000000
|
||||
? do_idle+0x19b/0x2c0
|
||||
? default_idle+0x9/0x20
|
||||
arch_cpu_idle+0x9/0x10
|
||||
default_idle_call+0x6b/0xa0
|
||||
do_idle+0x19b/0x2c0
|
||||
? __pfx_do_idle+0x10/0x10
|
||||
? complete_with_flags+0x63/0x70
|
||||
cpu_startup_entry+0x55/0x60
|
||||
start_secondary+0x1df/0x1e0
|
||||
common_startup_64+0x13e/0x158
|
||||
</TASK>
|
||||
nvme0n1: Write(0x1) @ LBA 0, 1 blocks, Invalid Command Opcode (sct 0x0 / sc 0x1) DNR
|
||||
operation not supported error, dev nvme0n1, sector 0 op 0x1:(WRITE) flags 0x8800 phys_seg 1 prio class 2
|
||||
|
|
|
|||
|
|
@ -19569,7 +19569,7 @@ F: include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h
|
|||
|
||||
NVM EXPRESS DRIVER
|
||||
M: Keith Busch <kbusch@kernel.org>
|
||||
M: Jens Axboe <axboe@fb.com>
|
||||
M: Jens Axboe <axboe@kernel.dk>
|
||||
M: Christoph Hellwig <hch@lst.de>
|
||||
M: Sagi Grimberg <sagi@grimberg.me>
|
||||
L: linux-nvme@lists.infradead.org
|
||||
|
|
|
|||
|
|
@ -155,8 +155,6 @@ static const struct class nvme_ns_chr_class = {
|
|||
};
|
||||
|
||||
static void nvme_put_subsystem(struct nvme_subsystem *subsys);
|
||||
static void nvme_remove_invalid_namespaces(struct nvme_ctrl *ctrl,
|
||||
unsigned nsid);
|
||||
static void nvme_update_keep_alive(struct nvme_ctrl *ctrl,
|
||||
struct nvme_command *cmd);
|
||||
static int nvme_get_log_lsi(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page,
|
||||
|
|
@ -1612,7 +1610,7 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl,
|
|||
}
|
||||
|
||||
if (nvme_multi_css(ctrl) && !csi_seen) {
|
||||
dev_warn(ctrl->device, "Command set not reported for nsid:%d\n",
|
||||
dev_warn(ctrl->device, "Command set not reported for nsid:%u\n",
|
||||
info->nsid);
|
||||
status = -EINVAL;
|
||||
}
|
||||
|
|
@ -2341,14 +2339,6 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info)
|
|||
size_t size;
|
||||
int i, ret;
|
||||
|
||||
/*
|
||||
* The FDP configuration is static for the lifetime of the namespace,
|
||||
* so return immediately if we've already registered this namespace's
|
||||
* streams.
|
||||
*/
|
||||
if (head->nr_plids)
|
||||
return 0;
|
||||
|
||||
ret = nvme_get_features(ctrl, NVME_FEAT_FDP, info->endgid, NULL, 0,
|
||||
&fdp);
|
||||
if (ret) {
|
||||
|
|
@ -2395,6 +2385,7 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info)
|
|||
|
||||
for (i = 0; i < head->nr_plids; i++)
|
||||
head->plids[i] = le16_to_cpu(ruhs->ruhsd[i].pid);
|
||||
head->write_stream_granularity = min(info->runs, U32_MAX);
|
||||
free:
|
||||
kfree(ruhs);
|
||||
return ret;
|
||||
|
|
@ -2442,12 +2433,6 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (ns->ctrl->ctratt & NVME_CTRL_ATTR_FDPS) {
|
||||
ret = nvme_query_fdp_info(ns, info);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nvme_invalid_lba_sz(le64_to_cpu(id->nsze),
|
||||
id->lbaf[lbaf].ds - SECTOR_SHIFT, &capacity)) {
|
||||
dev_warn_once(ns->ctrl->device,
|
||||
|
|
@ -2468,9 +2453,26 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
|
|||
if (!nvme_update_disk_info(ns, id, nvm, &lim))
|
||||
capacity = 0;
|
||||
|
||||
/*
|
||||
* A failed zone info query leaves zi zero-initialized, so skip the
|
||||
* zoned limits update instead of configuring the queue from it.
|
||||
* During a revalidation that keeps the zone geometry the queue was
|
||||
* last validated with; on a first scan the namespace is registered
|
||||
* without zoned limits, so that it is still available as a handle
|
||||
* for admin commands.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
|
||||
ns->head->ids.csi == NVME_CSI_ZNS)
|
||||
nvme_update_zone_info(ns, &lim, &zi);
|
||||
ns->head->ids.csi == NVME_CSI_ZNS) {
|
||||
if (zi.zone_size)
|
||||
nvme_update_zone_info(ns, &lim, &zi);
|
||||
else
|
||||
dev_warn(ns->ctrl->device,
|
||||
"zone info query failed for nsid %u, %s\n",
|
||||
ns->head->ns_id,
|
||||
blk_queue_is_zoned(ns->disk->queue) ?
|
||||
"keeping the previous zone limits" :
|
||||
"not enabling zoned mode");
|
||||
}
|
||||
|
||||
if ((ns->ctrl->vwc & NVME_CTRL_VWC_PRESENT) && !info->no_vwc)
|
||||
lim.features |= BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA;
|
||||
|
|
@ -2490,10 +2492,7 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
|
|||
capacity = 0;
|
||||
|
||||
lim.max_write_streams = ns->head->nr_plids;
|
||||
if (lim.max_write_streams)
|
||||
lim.write_stream_granularity = min(info->runs, U32_MAX);
|
||||
else
|
||||
lim.write_stream_granularity = 0;
|
||||
lim.write_stream_granularity = ns->head->write_stream_granularity;
|
||||
|
||||
/*
|
||||
* Only set the DEAC bit if the device guarantees that reads from
|
||||
|
|
@ -4001,10 +4000,11 @@ static void nvme_add_ns_cdev(struct nvme_ns *ns)
|
|||
set_bit(NVME_NS_CDEV_LIVE, &ns->flags);
|
||||
}
|
||||
|
||||
static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
|
||||
static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ns *ns,
|
||||
struct nvme_ns_info *info)
|
||||
__must_hold(&ctrl->subsys->lock)
|
||||
__must_hold(&ns->ctrl->subsys->lock)
|
||||
{
|
||||
struct nvme_ctrl *ctrl = ns->ctrl;
|
||||
struct nvme_ns_head *head;
|
||||
size_t size = sizeof(*head);
|
||||
int ret = -ENOMEM;
|
||||
|
|
@ -4032,6 +4032,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
|
|||
ratelimit_state_init(&head->rs_nuse, 5 * HZ, 1);
|
||||
ratelimit_set_flags(&head->rs_nuse, RATELIMIT_MSG_ON_RELEASE);
|
||||
kref_init(&head->ref);
|
||||
ns->head = head;
|
||||
|
||||
if (head->ids.csi) {
|
||||
ret = nvme_get_effects_log(ctrl, head->ids.csi, &head->effects);
|
||||
|
|
@ -4040,21 +4041,30 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
|
|||
} else
|
||||
head->effects = ctrl->effects;
|
||||
|
||||
if (ctrl->ctratt & NVME_CTRL_ATTR_FDPS) {
|
||||
ret = nvme_query_fdp_info(ns, info);
|
||||
if (ret < 0)
|
||||
goto out_cleanup_srcu;
|
||||
}
|
||||
|
||||
ret = nvme_mpath_alloc_disk(ctrl, head);
|
||||
if (ret)
|
||||
goto out_cleanup_srcu;
|
||||
goto out_cleanup_fdp;
|
||||
|
||||
list_add_tail(&head->entry, &ctrl->subsys->nsheads);
|
||||
|
||||
kref_get(&ctrl->subsys->ref);
|
||||
|
||||
return head;
|
||||
out_cleanup_fdp:
|
||||
kfree(head->plids);
|
||||
out_cleanup_srcu:
|
||||
cleanup_srcu_struct(&head->srcu);
|
||||
out_ida_remove:
|
||||
ida_free(&ctrl->subsys->ns_ida, head->instance);
|
||||
out_free_head:
|
||||
kfree(head);
|
||||
ns->head = NULL;
|
||||
out:
|
||||
if (ret > 0)
|
||||
ret = blk_status_to_errno(nvme_error_status(ret));
|
||||
|
|
@ -4116,13 +4126,13 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
|
|||
((ns->ctrl->subsys->cmic & NVME_CTRL_CMIC_MULTI_CTRL) &&
|
||||
info->is_shared)) {
|
||||
dev_err(ctrl->device,
|
||||
"ignoring nsid %d because of duplicate IDs\n",
|
||||
"ignoring nsid %u because of duplicate IDs\n",
|
||||
info->nsid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_err(ctrl->device,
|
||||
"clearing duplicate IDs for nsid %d\n", info->nsid);
|
||||
"clearing duplicate IDs for nsid %u\n", info->nsid);
|
||||
dev_err(ctrl->device,
|
||||
"use of /dev/disk/by-id/ may cause data corruption\n");
|
||||
memset(&info->ids.nguid, 0, sizeof(info->ids.nguid));
|
||||
|
|
@ -4137,11 +4147,11 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
|
|||
ret = nvme_subsys_check_duplicate_ids(ctrl->subsys, &info->ids);
|
||||
if (ret) {
|
||||
dev_err(ctrl->device,
|
||||
"duplicate IDs in subsystem for nsid %d\n",
|
||||
"duplicate IDs in subsystem for nsid %u\n",
|
||||
info->nsid);
|
||||
goto out_unlock;
|
||||
}
|
||||
head = nvme_alloc_ns_head(ctrl, info);
|
||||
head = nvme_alloc_ns_head(ns, info);
|
||||
if (IS_ERR(head)) {
|
||||
ret = PTR_ERR(head);
|
||||
goto out_unlock;
|
||||
|
|
@ -4151,20 +4161,20 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
|
|||
if ((!info->is_shared || !head->shared) &&
|
||||
!list_empty(&head->list)) {
|
||||
dev_err(ctrl->device,
|
||||
"Duplicate unshared namespace %d\n",
|
||||
"Duplicate unshared namespace %u\n",
|
||||
info->nsid);
|
||||
goto out_put_ns_head;
|
||||
}
|
||||
if (!nvme_ns_ids_equal(&head->ids, &info->ids)) {
|
||||
dev_err(ctrl->device,
|
||||
"IDs don't match for shared namespace %d\n",
|
||||
"IDs don't match for shared namespace %u\n",
|
||||
info->nsid);
|
||||
goto out_put_ns_head;
|
||||
}
|
||||
|
||||
if (!multipath) {
|
||||
dev_warn(ctrl->device,
|
||||
"Found shared namespace %d, but multipathing not supported.\n",
|
||||
"Found shared namespace %u, but multipathing not supported.\n",
|
||||
info->nsid);
|
||||
dev_warn_once(ctrl->device,
|
||||
"Shared namespace support requires core_nvme.multipath=Y.\n");
|
||||
|
|
@ -4333,6 +4343,9 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
|
|||
last_path = true;
|
||||
}
|
||||
mutex_unlock(&ctrl->subsys->lock);
|
||||
|
||||
/* guarantee not available in head->list */
|
||||
synchronize_srcu(&ns->head->srcu);
|
||||
if (last_path)
|
||||
nvme_put_ns_head(ns->head);
|
||||
nvme_put_ns_head(ns->head);
|
||||
|
|
@ -4410,7 +4423,7 @@ static void nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_info *info)
|
|||
|
||||
if (!nvme_ns_ids_equal(&ns->head->ids, &info->ids)) {
|
||||
dev_err(ns->ctrl->device,
|
||||
"identifiers changed for nsid %d\n", ns->head->ns_id);
|
||||
"identifiers changed for nsid %u\n", ns->head->ns_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -4437,7 +4450,7 @@ static void nvme_scan_ns(struct nvme_ctrl *ctrl, unsigned nsid)
|
|||
|
||||
if (info.ids.csi != NVME_CSI_NVM && !nvme_multi_css(ctrl)) {
|
||||
dev_warn(ctrl->device,
|
||||
"command set not reported for nsid: %d\n", nsid);
|
||||
"command set not reported for nsid: %u\n", nsid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -4501,15 +4514,16 @@ static void nvme_scan_ns_async(void *data, async_cookie_t cookie)
|
|||
nvme_scan_ns(scan_info->ctrl, nsid);
|
||||
}
|
||||
|
||||
static void nvme_remove_invalid_namespaces(struct nvme_ctrl *ctrl,
|
||||
unsigned nsid)
|
||||
static void nvme_remove_nsid_range(struct nvme_ctrl *ctrl, u32 start, u32 end)
|
||||
{
|
||||
struct nvme_ns *ns, *next;
|
||||
LIST_HEAD(rm_list);
|
||||
|
||||
mutex_lock(&ctrl->namespaces_lock);
|
||||
list_for_each_entry_safe(ns, next, &ctrl->namespaces, list) {
|
||||
if (ns->head->ns_id > nsid) {
|
||||
if (ns->head->ns_id >= end)
|
||||
break;
|
||||
if (ns->head->ns_id > start) {
|
||||
list_del_rcu(&ns->list);
|
||||
synchronize_srcu(&ctrl->srcu);
|
||||
list_add_tail_rcu(&ns->list, &rm_list);
|
||||
|
|
@ -4559,13 +4573,14 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl)
|
|||
goto out;
|
||||
async_schedule_domain(nvme_scan_ns_async, &scan_info,
|
||||
&domain);
|
||||
while (++prev < nsid)
|
||||
nvme_ns_remove_by_nsid(ctrl, prev);
|
||||
if (prev + 1 < nsid)
|
||||
nvme_remove_nsid_range(ctrl, prev, nsid);
|
||||
prev = max(prev + 1, nsid);
|
||||
}
|
||||
async_synchronize_full_domain(&domain);
|
||||
}
|
||||
out:
|
||||
nvme_remove_invalid_namespaces(ctrl, prev);
|
||||
nvme_remove_nsid_range(ctrl, prev, UINT_MAX);
|
||||
free:
|
||||
async_synchronize_full_domain(&domain);
|
||||
kfree(ns_list);
|
||||
|
|
@ -4585,7 +4600,7 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl)
|
|||
for (i = 1; i <= nn; i++)
|
||||
nvme_scan_ns(ctrl, i);
|
||||
|
||||
nvme_remove_invalid_namespaces(ctrl, nn);
|
||||
nvme_remove_nsid_range(ctrl, nn, UINT_MAX);
|
||||
}
|
||||
|
||||
static void nvme_clear_changed_ns_log(struct nvme_ctrl *ctrl)
|
||||
|
|
|
|||
|
|
@ -1028,6 +1028,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
|
|||
}
|
||||
if (strlen(p) < 11 || strncmp(p, "DHHC-1:", 7)) {
|
||||
pr_err("Invalid DH-CHAP secret %s\n", p);
|
||||
kfree_sensitive(p);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1042,6 +1043,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
|
|||
}
|
||||
if (strlen(p) < 11 || strncmp(p, "DHHC-1:", 7)) {
|
||||
pr_err("Invalid DH-CHAP secret %s\n", p);
|
||||
kfree_sensitive(p);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,9 +42,11 @@ void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
|
|||
}
|
||||
fault_inj->parent = parent;
|
||||
|
||||
/* create debugfs for status code and dont_retry */
|
||||
/* create debugfs for opcode, status code, and dont_retry */
|
||||
fault_inj->opcode = 0xffff;
|
||||
fault_inj->status = NVME_SC_INVALID_OPCODE;
|
||||
fault_inj->dont_retry = true;
|
||||
debugfs_create_x16("opcode", 0600, dir, &fault_inj->opcode);
|
||||
debugfs_create_x16("status", 0600, dir, &fault_inj->status);
|
||||
debugfs_create_bool("dont_retry", 0600, dir, &fault_inj->dont_retry);
|
||||
}
|
||||
|
|
@ -59,6 +61,7 @@ void nvme_should_fail(struct request *req)
|
|||
{
|
||||
struct gendisk *disk = req->q->disk;
|
||||
struct nvme_fault_inject *fault_inject = NULL;
|
||||
struct nvme_command *cmd = nvme_req(req)->cmd;
|
||||
u16 status;
|
||||
|
||||
if (disk) {
|
||||
|
|
@ -72,7 +75,14 @@ void nvme_should_fail(struct request *req)
|
|||
fault_inject = &nvme_req(req)->ctrl->fault_inject;
|
||||
}
|
||||
|
||||
if (fault_inject && should_fail(&fault_inject->attr, 1)) {
|
||||
if (!fault_inject)
|
||||
return;
|
||||
|
||||
if (fault_inject->opcode <= 0xff &&
|
||||
fault_inject->opcode != cmd->common.opcode)
|
||||
return;
|
||||
|
||||
if (should_fail(&fault_inject->attr, 1)) {
|
||||
/* inject status code and DNR bit */
|
||||
status = fault_inject->status;
|
||||
if (fault_inject->dont_retry)
|
||||
|
|
|
|||
|
|
@ -2364,9 +2364,15 @@ nvme_fc_ctrl_free(struct kref *ref)
|
|||
struct nvme_fc_ctrl *ctrl =
|
||||
container_of(ref, struct nvme_fc_ctrl, ref);
|
||||
unsigned long flags;
|
||||
bool owns_opts;
|
||||
|
||||
/* remove from rport list */
|
||||
/*
|
||||
* Presence on the rport list means nvme_fc_init_ctrl() completed,
|
||||
* and with it ownership of the fabrics options passed to it. If it
|
||||
* failed instead, the options still belong to nvmf_create_ctrl().
|
||||
*/
|
||||
spin_lock_irqsave(&ctrl->rport->lock, flags);
|
||||
owns_opts = !list_empty(&ctrl->ctrl_list);
|
||||
list_del(&ctrl->ctrl_list);
|
||||
spin_unlock_irqrestore(&ctrl->rport->lock, flags);
|
||||
|
||||
|
|
@ -2376,7 +2382,7 @@ nvme_fc_ctrl_free(struct kref *ref)
|
|||
nvme_fc_rport_put(ctrl->rport);
|
||||
|
||||
ida_free(&nvme_fc_ctrl_cnt, ctrl->cnum);
|
||||
if (ctrl->ctrl.opts)
|
||||
if (owns_opts)
|
||||
nvmf_free_options(ctrl->ctrl.opts);
|
||||
kfree(ctrl);
|
||||
}
|
||||
|
|
@ -3575,14 +3581,14 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
|
|||
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
|
||||
dev_err(ctrl->ctrl.device,
|
||||
"NVME-FC{%d}: failed to init ctrl state\n", ctrl->cnum);
|
||||
goto fail_ctrl;
|
||||
goto fail_unlist;
|
||||
}
|
||||
|
||||
if (!queue_delayed_work(nvme_wq, &ctrl->connect_work, 0)) {
|
||||
dev_err(ctrl->ctrl.device,
|
||||
"NVME-FC{%d}: failed to schedule initial connect\n",
|
||||
ctrl->cnum);
|
||||
goto fail_ctrl;
|
||||
goto fail_unlist;
|
||||
}
|
||||
|
||||
flush_delayed_work(&ctrl->connect_work);
|
||||
|
|
@ -3593,14 +3599,22 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
|
|||
|
||||
return &ctrl->ctrl;
|
||||
|
||||
fail_unlist:
|
||||
/*
|
||||
* Leaving the list hands the options back to nvmf_create_ctrl();
|
||||
* see nvme_fc_ctrl_free(). Re-init so that list_empty() there
|
||||
* reports the controller as unlisted.
|
||||
*/
|
||||
spin_lock_irqsave(&rport->lock, flags);
|
||||
list_del_init(&ctrl->ctrl_list);
|
||||
spin_unlock_irqrestore(&rport->lock, flags);
|
||||
|
||||
fail_ctrl:
|
||||
nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
|
||||
cancel_work_sync(&ctrl->ioerr_work);
|
||||
cancel_work_sync(&ctrl->ctrl.reset_work);
|
||||
cancel_delayed_work_sync(&ctrl->connect_work);
|
||||
|
||||
ctrl->ctrl.opts = NULL;
|
||||
|
||||
if (ctrl->ctrl.admin_tagset)
|
||||
nvme_remove_admin_tag_set(&ctrl->ctrl);
|
||||
/* initiate nvme ctrl ref counting teardown */
|
||||
|
|
|
|||
|
|
@ -323,6 +323,7 @@ struct nvme_fault_inject {
|
|||
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
|
||||
struct fault_attr attr;
|
||||
struct dentry *parent;
|
||||
u16 opcode;
|
||||
bool dont_retry; /* DNR, do not retry */
|
||||
u16 status; /* status code */
|
||||
#endif
|
||||
|
|
@ -571,6 +572,7 @@ struct nvme_ns_head {
|
|||
|
||||
u16 nr_plids;
|
||||
u16 *plids;
|
||||
u32 write_stream_granularity;
|
||||
#ifdef CONFIG_NVME_MULTIPATH
|
||||
struct bio_list requeue_list
|
||||
__guarded_by(&requeue_lock);
|
||||
|
|
|
|||
|
|
@ -2036,7 +2036,7 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
|
|||
struct ib_device *dev;
|
||||
bool queue_ready = test_bit(NVME_RDMA_Q_LIVE, &queue->flags);
|
||||
blk_status_t ret;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
WARN_ON_ONCE(rq->tag < 0);
|
||||
|
||||
|
|
@ -2092,16 +2092,18 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
|
|||
err_unmap:
|
||||
nvme_rdma_unmap_data(queue, rq);
|
||||
err:
|
||||
if (err == -EIO)
|
||||
ret = nvme_host_path_error(rq);
|
||||
else if (err == -ENOMEM || err == -EAGAIN)
|
||||
ret = BLK_STS_RESOURCE;
|
||||
else
|
||||
ret = BLK_STS_IOERR;
|
||||
nvme_cleanup_cmd(rq);
|
||||
if (err != -EIO) {
|
||||
nvme_cleanup_cmd(rq);
|
||||
if (err == -ENOMEM || err == -EAGAIN)
|
||||
ret = BLK_STS_RESOURCE;
|
||||
else
|
||||
ret = BLK_STS_IOERR;
|
||||
}
|
||||
unmap_qe:
|
||||
ib_dma_unmap_single(dev, req->sqe.dma, sizeof(struct nvme_command),
|
||||
DMA_TO_DEVICE);
|
||||
if (err == -EIO)
|
||||
return nvme_host_path_error(rq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ static DEVICE_ATTR_RO(eui);
|
|||
static ssize_t nsid_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", dev_to_ns_head(dev)->ns_id);
|
||||
return sysfs_emit(buf, "%u\n", dev_to_ns_head(dev)->ns_id);
|
||||
}
|
||||
static DEVICE_ATTR_RO(nsid);
|
||||
|
||||
|
|
|
|||
|
|
@ -413,8 +413,13 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
|
|||
* if we're the first on the send_list and we can try to send
|
||||
* directly, otherwise queue io_work. Also, only do that if we
|
||||
* are on the same cpu, so we don't introduce contention.
|
||||
*
|
||||
* TLS kTLS send takes ctx->tx_lock while blk_mq holds set->srcu.
|
||||
* lockdep reports circular locking via elevator_lock. Defer TLS
|
||||
* sends to the io workqueue instead of inline from this path.
|
||||
*/
|
||||
if (queue->io_cpu == raw_smp_processor_id() &&
|
||||
!nvme_tcp_queue_tls(queue) &&
|
||||
empty && mutex_trylock(&queue->send_mutex)) {
|
||||
nvme_tcp_send_all(queue);
|
||||
mutex_unlock(&queue->send_mutex);
|
||||
|
|
@ -684,6 +689,13 @@ static int nvme_tcp_handle_c2h_data(struct nvme_tcp_queue *queue,
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (rq_data_dir(rq) != READ) {
|
||||
dev_err(queue->ctrl->ctrl.device,
|
||||
"queue %d tag %#x unexpected data for a write\n",
|
||||
nvme_tcp_queue_id(queue), rq->tag);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
req = blk_mq_rq_to_pdu(rq);
|
||||
if (!blk_rq_payload_bytes(rq) || !req->curr_bio || !req->data_len) {
|
||||
dev_err(queue->ctrl->ctrl.device,
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@ int nvme_query_zone_info(struct nvme_ns *ns, unsigned lbaf,
|
|||
NVME_CMD_EFFECTS_CSUPP)) {
|
||||
if (test_and_clear_bit(NVME_NS_FORCE_RO, &ns->flags))
|
||||
dev_warn(ns->ctrl->device,
|
||||
"Zone Append supported for zoned namespace:%d. Remove read-only mode\n",
|
||||
"Zone Append supported for zoned namespace:%u. Remove read-only mode\n",
|
||||
ns->head->ns_id);
|
||||
} else {
|
||||
set_bit(NVME_NS_FORCE_RO, &ns->flags);
|
||||
dev_warn(ns->ctrl->device,
|
||||
"Zone Append not supported for zoned namespace:%d. Forcing to read-only mode\n",
|
||||
"Zone Append not supported for zoned namespace:%u. Forcing to read-only mode\n",
|
||||
ns->head->ns_id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -238,6 +238,12 @@ void nvmet_auth_sq_free(struct nvmet_sq *sq)
|
|||
sq->dhchap_skey = NULL;
|
||||
}
|
||||
|
||||
void nvmet_auth_sq_destroy(struct nvmet_sq *sq)
|
||||
{
|
||||
cancel_delayed_work_sync(&sq->auth_expired_work);
|
||||
nvmet_auth_sq_free(sq);
|
||||
}
|
||||
|
||||
void nvmet_destroy_auth(struct nvmet_ctrl *ctrl)
|
||||
{
|
||||
ctrl->shash_id = 0;
|
||||
|
|
|
|||
|
|
@ -814,7 +814,7 @@ static ssize_t nvmet_ns_resv_enable_store(struct config_item *item,
|
|||
|
||||
mutex_lock(&ns->subsys->lock);
|
||||
if (ns->enabled) {
|
||||
pr_err("the ns:%d is already enabled.\n", ns->nsid);
|
||||
pr_err("the ns:%u is already enabled.\n", ns->nsid);
|
||||
mutex_unlock(&ns->subsys->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -880,7 +880,7 @@ static struct config_group *nvmet_ns_make(struct config_group *group,
|
|||
goto out;
|
||||
config_group_init_type_name(&ns->group, name, &nvmet_ns_type);
|
||||
|
||||
pr_info("adding nsid %d to subsystem %s\n", nsid, subsys->subsysnqn);
|
||||
pr_info("adding nsid %u to subsystem %s\n", nsid, subsys->subsysnqn);
|
||||
|
||||
return &ns->group;
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -558,7 +558,7 @@ static void nvmet_p2pmem_ns_add_p2p(struct nvmet_ctrl *ctrl,
|
|||
if (ret < 0)
|
||||
pci_dev_put(p2p_dev);
|
||||
|
||||
pr_info("using p2pmem on %s for nsid %d\n", pci_name(p2p_dev),
|
||||
pr_info("using p2pmem on %s for nsid %u\n", pci_name(p2p_dev),
|
||||
ns->nsid);
|
||||
}
|
||||
|
||||
|
|
@ -591,6 +591,11 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
|
|||
if (ns->enabled)
|
||||
goto out_unlock;
|
||||
|
||||
if (!ns->device_path) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = nvmet_bdev_ns_enable(ns);
|
||||
if (ret == -ENOTBLK)
|
||||
ret = nvmet_file_ns_enable(ns);
|
||||
|
|
@ -980,7 +985,7 @@ void nvmet_sq_destroy(struct nvmet_sq *sq)
|
|||
wait_for_completion(&sq->confirm_done);
|
||||
wait_for_completion(&sq->free_done);
|
||||
percpu_ref_exit(&sq->ref);
|
||||
nvmet_auth_sq_free(sq);
|
||||
nvmet_auth_sq_destroy(sq);
|
||||
nvmet_cq_put(sq->cq);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -924,6 +924,7 @@ u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, bool reset);
|
|||
void nvmet_auth_sq_init(struct nvmet_sq *sq);
|
||||
void nvmet_destroy_auth(struct nvmet_ctrl *ctrl);
|
||||
void nvmet_auth_sq_free(struct nvmet_sq *sq);
|
||||
void nvmet_auth_sq_destroy(struct nvmet_sq *sq);
|
||||
int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, u8 dhgroup_id);
|
||||
bool nvmet_check_auth_status(struct nvmet_req *req);
|
||||
int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
|
||||
|
|
@ -950,6 +951,7 @@ static inline void nvmet_auth_sq_init(struct nvmet_sq *sq)
|
|||
}
|
||||
static inline void nvmet_destroy_auth(struct nvmet_ctrl *ctrl) {};
|
||||
static inline void nvmet_auth_sq_free(struct nvmet_sq *sq) {};
|
||||
static inline void nvmet_auth_sq_destroy(struct nvmet_sq *sq) {};
|
||||
static inline bool nvmet_check_auth_status(struct nvmet_req *req)
|
||||
{
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ static void nvmet_pr_add_resv_log(struct nvmet_ctrl *ctrl, u8 log_type,
|
|||
log.nsid = cpu_to_le32(nsid);
|
||||
|
||||
if (!kfifo_put(&log_mgr->log_queue, log)) {
|
||||
pr_info("a reservation log lost, cntlid:%d, log_type:%d, nsid:%d\n",
|
||||
pr_info("a reservation log lost, cntlid:%d, log_type:%d, nsid:%u\n",
|
||||
ctrl->cntlid, log_type, nsid);
|
||||
log_mgr->lost_count++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1631,19 +1631,13 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,
|
|||
mutex_unlock(&nvmet_rdma_queue_mutex);
|
||||
if (pending > NVMET_RDMA_BACKLOG) {
|
||||
ret = NVME_SC_CONNECT_CTRL_BUSY;
|
||||
goto put_device;
|
||||
goto free_queue;
|
||||
}
|
||||
}
|
||||
|
||||
ret = nvmet_rdma_cm_accept(cm_id, queue, &event->param.conn);
|
||||
if (ret) {
|
||||
/*
|
||||
* Don't destroy the cm_id in free path, as we implicitly
|
||||
* destroy the cm_id here with non-zero ret code.
|
||||
*/
|
||||
queue->cm_id = NULL;
|
||||
if (ret)
|
||||
goto free_queue;
|
||||
}
|
||||
|
||||
mutex_lock(&nvmet_rdma_queue_mutex);
|
||||
list_add_tail(&queue->queue_list, &nvmet_rdma_queue_list);
|
||||
|
|
@ -1652,6 +1646,11 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,
|
|||
return 0;
|
||||
|
||||
free_queue:
|
||||
/*
|
||||
* Don't destroy the cm_id in free path, as we implicitly
|
||||
* destroy the cm_id here with non-zero ret code.
|
||||
*/
|
||||
queue->cm_id = NULL;
|
||||
nvmet_rdma_free_queue(queue);
|
||||
put_device:
|
||||
kref_put(&ndev->ref, nvmet_rdma_free_dev);
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ enum nvmet_tcp_recv_state {
|
|||
|
||||
enum {
|
||||
NVMET_TCP_F_INIT_FAILED = (1 << 0),
|
||||
NVMET_TCP_F_R2T_SENT = (1 << 1),
|
||||
};
|
||||
|
||||
struct nvmet_tcp_cmd {
|
||||
|
|
@ -776,6 +777,7 @@ static int nvmet_try_send_r2t(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
|
|||
return -EAGAIN;
|
||||
|
||||
cmd->queue->snd_cmd = NULL;
|
||||
cmd->flags |= NVMET_TCP_F_R2T_SENT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -1009,6 +1011,12 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
|
|||
cmd = &queue->connect;
|
||||
}
|
||||
|
||||
if (unlikely(!(cmd->flags & NVMET_TCP_F_R2T_SENT))) {
|
||||
pr_err("queue %d: unsolicited H2CData (ttag %u)\n",
|
||||
queue->idx, data->ttag);
|
||||
goto err_proto;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(data->data_offset) != cmd->rbytes_done) {
|
||||
pr_err("ttag %u unexpected data offset %u (expected %u)\n",
|
||||
data->ttag, le32_to_cpu(data->data_offset),
|
||||
|
|
@ -1244,6 +1252,8 @@ static int nvmet_tcp_try_recv_pdu(struct nvmet_tcp_queue *queue)
|
|||
}
|
||||
|
||||
queue->left = hdr->hlen - queue->offset + hdgst;
|
||||
if (queue->left > sizeof(queue->pdu) - queue->offset)
|
||||
return -EPROTO;
|
||||
goto recv;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ struct nvme_tcp_hdr {
|
|||
__le32 plen;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct nvme_tcp_icreq_pdu - nvme tcp initialize connection request pdu
|
||||
*
|
||||
* @hdr: pdu generic header
|
||||
|
|
@ -95,7 +95,7 @@ struct nvme_tcp_icreq_pdu {
|
|||
__u8 rsvd2[112];
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct nvme_tcp_icresp_pdu - nvme tcp initialize connection response pdu
|
||||
*
|
||||
* @hdr: pdu common header
|
||||
|
|
@ -113,12 +113,13 @@ struct nvme_tcp_icresp_pdu {
|
|||
__u8 rsvd[112];
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct nvme_tcp_term_pdu - nvme tcp terminate connection pdu
|
||||
*
|
||||
* @hdr: pdu common header
|
||||
* @fes: fatal error status
|
||||
* @fei: fatal error information
|
||||
* @feil: fatal error information (low 16 bits)
|
||||
* @feih: fatal error information (high 16 bits)
|
||||
*/
|
||||
struct nvme_tcp_term_pdu {
|
||||
struct nvme_tcp_hdr hdr;
|
||||
|
|
@ -128,7 +129,7 @@ struct nvme_tcp_term_pdu {
|
|||
__u8 rsvd[10];
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct nvme_tcp_cmd_pdu - nvme tcp command capsule pdu
|
||||
*
|
||||
* @hdr: pdu common header
|
||||
|
|
@ -139,10 +140,9 @@ struct nvme_tcp_cmd_pdu {
|
|||
struct nvme_command cmd;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct nvme_tcp_rsp_pdu - nvme tcp response capsule pdu
|
||||
*
|
||||
* @hdr: pdu common header
|
||||
* @hdr: nvme-tcp generic header
|
||||
* @cqe: nvme completion queue entry
|
||||
*/
|
||||
|
|
@ -151,7 +151,7 @@ struct nvme_tcp_rsp_pdu {
|
|||
struct nvme_completion cqe;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct nvme_tcp_r2t_pdu - nvme tcp ready-to-transfer pdu
|
||||
*
|
||||
* @hdr: pdu common header
|
||||
|
|
@ -169,7 +169,7 @@ struct nvme_tcp_r2t_pdu {
|
|||
__u8 rsvd[4];
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* struct nvme_tcp_data_pdu - nvme tcp data pdu
|
||||
*
|
||||
* @hdr: pdu common header
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user