]> www.infradead.org Git - users/hch/misc.git/commitdiff
net/mlx5e: kTLS, Fix incorrect page refcounting
authorDragos Tatulea <dtatulea@nvidia.com>
Thu, 7 Nov 2024 18:35:24 +0000 (20:35 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 12 Nov 2024 03:23:38 +0000 (19:23 -0800)
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: 84d1bb2b139e ("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>
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c

index d61be26a4df1a52508ea2b58dacc528fe0a37a4a..3db31cc10719260ebb49bc9af0aec4adf980bf30 100644 (file)
@@ -660,7 +660,7 @@ tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx,
        while (remaining > 0) {
                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);
                info->frags[i++] = *frag;
        }
@@ -763,7 +763,7 @@ void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
        stats = sq->stats;
 
        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_bytes += wi->num_bytes;
 }
@@ -816,12 +816,12 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx,
 
 err_out:
        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
                 * released only upon their completions (or in mlx5e_free_txqsq_descs,
                 * 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;
 }