Skip to content

Commit 3fd40fa

Browse files
committed
Merge tag 'nvme-5.16-2021-11-25' of git://git.infradead.org/nvme into block-5.16
Pull NVMe fixes from Christoph: "nvme fixes for Linux 5.16 - add a NO APST quirk for a Kioxia device (Enzo Matsumiya) - fix write zeroes pi (Klaus Jensen) - various TCP transport fixes (Maurizio Lombardi and Varun Prakash) - ignore invalid fast_io_fail_tmo values (Maurizio Lombardi) - use IOCB_NOWAIT only if the filesystem supports it (Maurizio Lombardi)" * tag 'nvme-5.16-2021-11-25' of git://git.infradead.org/nvme: nvmet: use IOCB_NOWAIT only if the filesystem supports it nvme: fix write zeroes pi nvme-fabrics: ignore invalid fast_io_fail_tmo values nvme-pci: add NO APST quirk for Kioxia device nvme-tcp: fix memory leak when freeing a queue nvme-tcp: validate R2T PDU in nvme_tcp_handle_r2t() nvmet-tcp: fix incomplete data digest send nvmet-tcp: fix memory leak when performing a controller reset nvmet-tcp: add an helper to free the cmd buffers nvmet-tcp: fix a race condition between release_queue and io_work
2 parents efcf593 + c024b22 commit 3fd40fa

File tree

5 files changed

+94
-47
lines changed

5 files changed

+94
-47
lines changed

drivers/nvme/host/core.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -895,10 +895,19 @@ static inline blk_status_t nvme_setup_write_zeroes(struct nvme_ns *ns,
895895
cpu_to_le64(nvme_sect_to_lba(ns, blk_rq_pos(req)));
896896
cmnd->write_zeroes.length =
897897
cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
898-
if (nvme_ns_has_pi(ns))
898+
899+
if (nvme_ns_has_pi(ns)) {
899900
cmnd->write_zeroes.control = cpu_to_le16(NVME_RW_PRINFO_PRACT);
900-
else
901-
cmnd->write_zeroes.control = 0;
901+
902+
switch (ns->pi_type) {
903+
case NVME_NS_DPS_PI_TYPE1:
904+
case NVME_NS_DPS_PI_TYPE2:
905+
cmnd->write_zeroes.reftag =
906+
cpu_to_le32(t10_pi_ref_tag(req));
907+
break;
908+
}
909+
}
910+
902911
return BLK_STS_OK;
903912
}
904913

@@ -2469,6 +2478,20 @@ static const struct nvme_core_quirk_entry core_quirks[] = {
24692478
.vid = 0x14a4,
24702479
.fr = "22301111",
24712480
.quirks = NVME_QUIRK_SIMPLE_SUSPEND,
2481+
},
2482+
{
2483+
/*
2484+
* This Kioxia CD6-V Series / HPE PE8030 device times out and
2485+
* aborts I/O during any load, but more easily reproducible
2486+
* with discards (fstrim).
2487+
*
2488+
* The device is left in a state where it is also not possible
2489+
* to use "nvme set-feature" to disable APST, but booting with
2490+
* nvme_core.default_ps_max_latency=0 works.
2491+
*/
2492+
.vid = 0x1e0f,
2493+
.mn = "KCD6XVUL6T40",
2494+
.quirks = NVME_QUIRK_NO_APST,
24722495
}
24732496
};
24742497

drivers/nvme/host/fabrics.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
698698
if (token >= 0)
699699
pr_warn("I/O fail on reconnect controller after %d sec\n",
700700
token);
701+
else
702+
token = -1;
703+
701704
opts->fast_io_fail_tmo = token;
702705
break;
703706
case NVMF_OPT_HOSTNQN:

drivers/nvme/host/tcp.c

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ static int nvme_tcp_handle_comp(struct nvme_tcp_queue *queue,
572572
return ret;
573573
}
574574

575-
static int nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
575+
static void nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
576576
struct nvme_tcp_r2t_pdu *pdu)
577577
{
578578
struct nvme_tcp_data_pdu *data = req->pdu;
@@ -581,32 +581,11 @@ static int nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
581581
u8 hdgst = nvme_tcp_hdgst_len(queue);
582582
u8 ddgst = nvme_tcp_ddgst_len(queue);
583583

584+
req->state = NVME_TCP_SEND_H2C_PDU;
585+
req->offset = 0;
584586
req->pdu_len = le32_to_cpu(pdu->r2t_length);
585587
req->pdu_sent = 0;
586588

587-
if (unlikely(!req->pdu_len)) {
588-
dev_err(queue->ctrl->ctrl.device,
589-
"req %d r2t len is %u, probably a bug...\n",
590-
rq->tag, req->pdu_len);
591-
return -EPROTO;
592-
}
593-
594-
if (unlikely(req->data_sent + req->pdu_len > req->data_len)) {
595-
dev_err(queue->ctrl->ctrl.device,
596-
"req %d r2t len %u exceeded data len %u (%zu sent)\n",
597-
rq->tag, req->pdu_len, req->data_len,
598-
req->data_sent);
599-
return -EPROTO;
600-
}
601-
602-
if (unlikely(le32_to_cpu(pdu->r2t_offset) < req->data_sent)) {
603-
dev_err(queue->ctrl->ctrl.device,
604-
"req %d unexpected r2t offset %u (expected %zu)\n",
605-
rq->tag, le32_to_cpu(pdu->r2t_offset),
606-
req->data_sent);
607-
return -EPROTO;
608-
}
609-
610589
memset(data, 0, sizeof(*data));
611590
data->hdr.type = nvme_tcp_h2c_data;
612591
data->hdr.flags = NVME_TCP_F_DATA_LAST;
@@ -622,15 +601,14 @@ static int nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
622601
data->command_id = nvme_cid(rq);
623602
data->data_offset = pdu->r2t_offset;
624603
data->data_length = cpu_to_le32(req->pdu_len);
625-
return 0;
626604
}
627605

628606
static int nvme_tcp_handle_r2t(struct nvme_tcp_queue *queue,
629607
struct nvme_tcp_r2t_pdu *pdu)
630608
{
631609
struct nvme_tcp_request *req;
632610
struct request *rq;
633-
int ret;
611+
u32 r2t_length = le32_to_cpu(pdu->r2t_length);
634612

635613
rq = nvme_find_rq(nvme_tcp_tagset(queue), pdu->command_id);
636614
if (!rq) {
@@ -641,13 +619,28 @@ static int nvme_tcp_handle_r2t(struct nvme_tcp_queue *queue,
641619
}
642620
req = blk_mq_rq_to_pdu(rq);
643621

644-
ret = nvme_tcp_setup_h2c_data_pdu(req, pdu);
645-
if (unlikely(ret))
646-
return ret;
622+
if (unlikely(!r2t_length)) {
623+
dev_err(queue->ctrl->ctrl.device,
624+
"req %d r2t len is %u, probably a bug...\n",
625+
rq->tag, r2t_length);
626+
return -EPROTO;
627+
}
647628

648-
req->state = NVME_TCP_SEND_H2C_PDU;
649-
req->offset = 0;
629+
if (unlikely(req->data_sent + r2t_length > req->data_len)) {
630+
dev_err(queue->ctrl->ctrl.device,
631+
"req %d r2t len %u exceeded data len %u (%zu sent)\n",
632+
rq->tag, r2t_length, req->data_len, req->data_sent);
633+
return -EPROTO;
634+
}
650635

636+
if (unlikely(le32_to_cpu(pdu->r2t_offset) < req->data_sent)) {
637+
dev_err(queue->ctrl->ctrl.device,
638+
"req %d unexpected r2t offset %u (expected %zu)\n",
639+
rq->tag, le32_to_cpu(pdu->r2t_offset), req->data_sent);
640+
return -EPROTO;
641+
}
642+
643+
nvme_tcp_setup_h2c_data_pdu(req, pdu);
651644
nvme_tcp_queue_request(req, false, true);
652645

653646
return 0;
@@ -1232,6 +1225,7 @@ static int nvme_tcp_alloc_async_req(struct nvme_tcp_ctrl *ctrl)
12321225

12331226
static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid)
12341227
{
1228+
struct page *page;
12351229
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
12361230
struct nvme_tcp_queue *queue = &ctrl->queues[qid];
12371231

@@ -1241,6 +1235,11 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid)
12411235
if (queue->hdr_digest || queue->data_digest)
12421236
nvme_tcp_free_crypto(queue);
12431237

1238+
if (queue->pf_cache.va) {
1239+
page = virt_to_head_page(queue->pf_cache.va);
1240+
__page_frag_cache_drain(page, queue->pf_cache.pagecnt_bias);
1241+
queue->pf_cache.va = NULL;
1242+
}
12441243
sock_release(queue->sock);
12451244
kfree(queue->pdu);
12461245
mutex_destroy(&queue->send_mutex);

drivers/nvme/target/io-cmd-file.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/uio.h>
99
#include <linux/falloc.h>
1010
#include <linux/file.h>
11+
#include <linux/fs.h>
1112
#include "nvmet.h"
1213

1314
#define NVMET_MAX_MPOOL_BVEC 16
@@ -266,7 +267,8 @@ static void nvmet_file_execute_rw(struct nvmet_req *req)
266267

267268
if (req->ns->buffered_io) {
268269
if (likely(!req->f.mpool_alloc) &&
269-
nvmet_file_execute_io(req, IOCB_NOWAIT))
270+
(req->ns->file->f_mode & FMODE_NOWAIT) &&
271+
nvmet_file_execute_io(req, IOCB_NOWAIT))
270272
return;
271273
nvmet_file_submit_buffered_io(req);
272274
} else

drivers/nvme/target/tcp.c

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ static struct workqueue_struct *nvmet_tcp_wq;
166166
static const struct nvmet_fabrics_ops nvmet_tcp_ops;
167167
static void nvmet_tcp_free_cmd(struct nvmet_tcp_cmd *c);
168168
static void nvmet_tcp_finish_cmd(struct nvmet_tcp_cmd *cmd);
169+
static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd);
170+
static void nvmet_tcp_unmap_pdu_iovec(struct nvmet_tcp_cmd *cmd);
169171

170172
static inline u16 nvmet_tcp_cmd_tag(struct nvmet_tcp_queue *queue,
171173
struct nvmet_tcp_cmd *cmd)
@@ -297,6 +299,16 @@ static int nvmet_tcp_check_ddgst(struct nvmet_tcp_queue *queue, void *pdu)
297299
return 0;
298300
}
299301

302+
static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd)
303+
{
304+
WARN_ON(unlikely(cmd->nr_mapped > 0));
305+
306+
kfree(cmd->iov);
307+
sgl_free(cmd->req.sg);
308+
cmd->iov = NULL;
309+
cmd->req.sg = NULL;
310+
}
311+
300312
static void nvmet_tcp_unmap_pdu_iovec(struct nvmet_tcp_cmd *cmd)
301313
{
302314
struct scatterlist *sg;
@@ -306,6 +318,8 @@ static void nvmet_tcp_unmap_pdu_iovec(struct nvmet_tcp_cmd *cmd)
306318

307319
for (i = 0; i < cmd->nr_mapped; i++)
308320
kunmap(sg_page(&sg[i]));
321+
322+
cmd->nr_mapped = 0;
309323
}
310324

311325
static void nvmet_tcp_map_pdu_iovec(struct nvmet_tcp_cmd *cmd)
@@ -387,7 +401,7 @@ static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd)
387401

388402
return 0;
389403
err:
390-
sgl_free(cmd->req.sg);
404+
nvmet_tcp_free_cmd_buffers(cmd);
391405
return NVME_SC_INTERNAL;
392406
}
393407

@@ -632,10 +646,8 @@ static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
632646
}
633647
}
634648

635-
if (queue->nvme_sq.sqhd_disabled) {
636-
kfree(cmd->iov);
637-
sgl_free(cmd->req.sg);
638-
}
649+
if (queue->nvme_sq.sqhd_disabled)
650+
nvmet_tcp_free_cmd_buffers(cmd);
639651

640652
return 1;
641653

@@ -664,8 +676,7 @@ static int nvmet_try_send_response(struct nvmet_tcp_cmd *cmd,
664676
if (left)
665677
return -EAGAIN;
666678

667-
kfree(cmd->iov);
668-
sgl_free(cmd->req.sg);
679+
nvmet_tcp_free_cmd_buffers(cmd);
669680
cmd->queue->snd_cmd = NULL;
670681
nvmet_tcp_put_cmd(cmd);
671682
return 1;
@@ -700,10 +711,11 @@ static int nvmet_try_send_r2t(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
700711
static int nvmet_try_send_ddgst(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
701712
{
702713
struct nvmet_tcp_queue *queue = cmd->queue;
714+
int left = NVME_TCP_DIGEST_LENGTH - cmd->offset;
703715
struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
704716
struct kvec iov = {
705717
.iov_base = (u8 *)&cmd->exp_ddgst + cmd->offset,
706-
.iov_len = NVME_TCP_DIGEST_LENGTH - cmd->offset
718+
.iov_len = left
707719
};
708720
int ret;
709721

@@ -717,6 +729,10 @@ static int nvmet_try_send_ddgst(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
717729
return ret;
718730

719731
cmd->offset += ret;
732+
left -= ret;
733+
734+
if (left)
735+
return -EAGAIN;
720736

721737
if (queue->nvme_sq.sqhd_disabled) {
722738
cmd->queue->snd_cmd = NULL;
@@ -1406,8 +1422,7 @@ static void nvmet_tcp_finish_cmd(struct nvmet_tcp_cmd *cmd)
14061422
{
14071423
nvmet_req_uninit(&cmd->req);
14081424
nvmet_tcp_unmap_pdu_iovec(cmd);
1409-
kfree(cmd->iov);
1410-
sgl_free(cmd->req.sg);
1425+
nvmet_tcp_free_cmd_buffers(cmd);
14111426
}
14121427

14131428
static void nvmet_tcp_uninit_data_in_cmds(struct nvmet_tcp_queue *queue)
@@ -1417,7 +1432,10 @@ static void nvmet_tcp_uninit_data_in_cmds(struct nvmet_tcp_queue *queue)
14171432

14181433
for (i = 0; i < queue->nr_cmds; i++, cmd++) {
14191434
if (nvmet_tcp_need_data_in(cmd))
1420-
nvmet_tcp_finish_cmd(cmd);
1435+
nvmet_req_uninit(&cmd->req);
1436+
1437+
nvmet_tcp_unmap_pdu_iovec(cmd);
1438+
nvmet_tcp_free_cmd_buffers(cmd);
14211439
}
14221440

14231441
if (!queue->nr_cmds && nvmet_tcp_need_data_in(&queue->connect)) {
@@ -1437,7 +1455,9 @@ static void nvmet_tcp_release_queue_work(struct work_struct *w)
14371455
mutex_unlock(&nvmet_tcp_queue_mutex);
14381456

14391457
nvmet_tcp_restore_socket_callbacks(queue);
1440-
flush_work(&queue->io_work);
1458+
cancel_work_sync(&queue->io_work);
1459+
/* stop accepting incoming data */
1460+
queue->rcv_state = NVMET_TCP_RECV_ERR;
14411461

14421462
nvmet_tcp_uninit_data_in_cmds(queue);
14431463
nvmet_sq_destroy(&queue->nvme_sq);

0 commit comments

Comments
 (0)