Skip to content

Commit d19f98c

Browse files
logostgregkh
authored andcommitted
nvme-tcp: fix usage of page_frag_cache
commit 36ac05f upstream. nvme uses page_frag_cache to preallocate PDU for each preallocated request of block device. Block devices are created in parallel threads, consequently page_frag_cache is used in not thread-safe manner. That leads to incorrect refcounting of backstore pages and premature free. That can be catched by !sendpage_ok inside network stack: WARNING: CPU: 7 PID: 467 at ../net/core/skbuff.c:6931 skb_splice_from_iter+0xfa/0x310. tcp_sendmsg_locked+0x782/0xce0 tcp_sendmsg+0x27/0x40 sock_sendmsg+0x8b/0xa0 nvme_tcp_try_send_cmd_pdu+0x149/0x2a0 Then random panic may occur. Fix that by serializing the usage of page_frag_cache. Fixes: 4e893ca ("nvme_core: scan namespaces asynchronously") Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com> Signed-off-by: Daniel Wagner <wagi@kernel.org> Signed-off-by: Keith Busch <kbusch@kernel.org> [carlos.bilbao: adjust context in nvme_tcp_free_queue; branch predates 19bdb70 ("nvme-tcp: lockdep: use dynamic lockdep keys per socket instance")] Signed-off-by: Carlos Bilbao (Lambda) <carlos.bilbao@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 2acc77e commit d19f98c

1 file changed

Lines changed: 8 additions & 0 deletions

File tree

drivers/nvme/host/tcp.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ struct nvme_tcp_queue {
146146

147147
struct mutex queue_lock;
148148
struct mutex send_mutex;
149+
struct mutex pf_cache_lock;
149150
struct llist_head req_list;
150151
struct list_head send_list;
151152

@@ -552,9 +553,11 @@ static int nvme_tcp_init_request(struct blk_mq_tag_set *set,
552553
struct nvme_tcp_queue *queue = &ctrl->queues[queue_idx];
553554
u8 hdgst = nvme_tcp_hdgst_len(queue);
554555

556+
mutex_lock(&queue->pf_cache_lock);
555557
req->pdu = page_frag_alloc(&queue->pf_cache,
556558
sizeof(struct nvme_tcp_cmd_pdu) + hdgst,
557559
GFP_KERNEL | __GFP_ZERO);
560+
mutex_unlock(&queue->pf_cache_lock);
558561
if (!req->pdu)
559562
return -ENOMEM;
560563

@@ -1452,9 +1455,11 @@ static int nvme_tcp_alloc_async_req(struct nvme_tcp_ctrl *ctrl)
14521455
struct nvme_tcp_request *async = &ctrl->async_req;
14531456
u8 hdgst = nvme_tcp_hdgst_len(queue);
14541457

1458+
mutex_lock(&queue->pf_cache_lock);
14551459
async->pdu = page_frag_alloc(&queue->pf_cache,
14561460
sizeof(struct nvme_tcp_cmd_pdu) + hdgst,
14571461
GFP_KERNEL | __GFP_ZERO);
1462+
mutex_unlock(&queue->pf_cache_lock);
14581463
if (!async->pdu)
14591464
return -ENOMEM;
14601465

@@ -1485,6 +1490,7 @@ static void nvme_tcp_free_queue(struct nvme_ctrl *nctrl, int qid)
14851490
kfree(queue->pdu);
14861491
mutex_destroy(&queue->send_mutex);
14871492
mutex_destroy(&queue->queue_lock);
1493+
mutex_destroy(&queue->pf_cache_lock);
14881494
}
14891495

14901496
static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
@@ -1807,6 +1813,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
18071813
INIT_LIST_HEAD(&queue->send_list);
18081814
mutex_init(&queue->send_mutex);
18091815
INIT_WORK(&queue->io_work, nvme_tcp_io_work);
1816+
mutex_init(&queue->pf_cache_lock);
18101817

18111818
if (qid > 0)
18121819
queue->cmnd_capsule_len = nctrl->ioccsz * 16;
@@ -1946,6 +1953,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
19461953
err_destroy_mutex:
19471954
mutex_destroy(&queue->send_mutex);
19481955
mutex_destroy(&queue->queue_lock);
1956+
mutex_destroy(&queue->pf_cache_lock);
19491957
return ret;
19501958
}
19511959

0 commit comments

Comments
 (0)