mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
net/mlx5e: kTLS, Fix incorrect page refcounting
[ Upstream commit dd6e972cc5890d91d6749bb48e3912721c4e4b25 ]
The kTLS tx handling code is using a mix of get_page() and
page_ref_inc() APIs to increment the page reference. But on the release
path (mlx5e_ktls_tx_handle_resync_dump_comp()), only put_page() is used.
This is an issue when using pages from large folios: the get_page()
references are stored on the folio page while the page_ref_inc()
references are stored directly in the given page. On release the folio
page will be dereferenced too many times.
This was found while doing kTLS testing with sendfile() + ZC when the
served file was read from NFS on a kernel with NFS large folios support
(commit 49b29a573da8 ("nfs: add support for large folios")).
Fixes: 84d1bb2b13 ("net/mlx5e: kTLS, Limit DUMP wqe size")
Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20241107183527.676877-5-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
bfba288f53
commit
69fbd07f17
@@ -665,7 +665,7 @@ tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx,
|
|||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
skb_frag_t *frag = &record->frags[i];
|
skb_frag_t *frag = &record->frags[i];
|
||||||
|
|
||||||
get_page(skb_frag_page(frag));
|
page_ref_inc(skb_frag_page(frag));
|
||||||
remaining -= skb_frag_size(frag);
|
remaining -= skb_frag_size(frag);
|
||||||
info->frags[i++] = *frag;
|
info->frags[i++] = *frag;
|
||||||
}
|
}
|
||||||
@@ -768,7 +768,7 @@ void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
|
|||||||
stats = sq->stats;
|
stats = sq->stats;
|
||||||
|
|
||||||
mlx5e_tx_dma_unmap(sq->pdev, dma);
|
mlx5e_tx_dma_unmap(sq->pdev, dma);
|
||||||
put_page(wi->resync_dump_frag_page);
|
page_ref_dec(wi->resync_dump_frag_page);
|
||||||
stats->tls_dump_packets++;
|
stats->tls_dump_packets++;
|
||||||
stats->tls_dump_bytes += wi->num_bytes;
|
stats->tls_dump_bytes += wi->num_bytes;
|
||||||
}
|
}
|
||||||
@@ -821,12 +821,12 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx,
|
|||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
for (; i < info.nr_frags; i++)
|
for (; i < info.nr_frags; i++)
|
||||||
/* The put_page() here undoes the page ref obtained in tx_sync_info_get().
|
/* The page_ref_dec() here undoes the page ref obtained in tx_sync_info_get().
|
||||||
* Page refs obtained for the DUMP WQEs above (by page_ref_add) will be
|
* Page refs obtained for the DUMP WQEs above (by page_ref_add) will be
|
||||||
* released only upon their completions (or in mlx5e_free_txqsq_descs,
|
* released only upon their completions (or in mlx5e_free_txqsq_descs,
|
||||||
* if channel closes).
|
* if channel closes).
|
||||||
*/
|
*/
|
||||||
put_page(skb_frag_page(&info.frags[i]));
|
page_ref_dec(skb_frag_page(&info.frags[i]));
|
||||||
|
|
||||||
return MLX5E_KTLS_SYNC_FAIL;
|
return MLX5E_KTLS_SYNC_FAIL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user