> From: Stephen Hemminger [mailto:[email protected]]
> Sent: Friday, 8 May 2026 22.34
>
> This allows callers to avoid NULL checks and just call
> rte_pktmbuf_free_bulk, similar to rte_pktmbuf_free.
>
> Signed-off-by: Stephen Hemminger <[email protected]>
I disagree with this patch.
The parameter is an array of (pointers to) mbufs.
We already accept that the array can contain NULL pointers (no mbuf present).
This is extremely forgiving, considering that other fast path functions don't
allow NULL pointers in arrays;
e.g. rte_eth_tx_burst(), rte_mempool_put_bulk().
But since it's a "free()" class of function, I don't object to it.
However, this patch changes the parameter type from "array" to "array or NULL
(no array present)".
And I don't think we should change the parameter type; it should remain "array"
only.
If there are any scenarios where a non-present array (NULL) is passed to the
function, the count should be zero too.
And when the count is zero, the function does not dereference the array, so
explicitly checking for NULL is superfluous.
We have a convention of not checking parameter validity in fast path functions.
And I consider it invalid parameters passing NULL with a non-zero count.
You might argue that this is a "free()" class of function, which warrants
checking for NULL; but since it already accepts NULL with zero count, it is
already covered.
We could change the function declaration for clarity:
void rte_pktmbuf_free_bulk(
unsigned int count;
struct rte_mbuf *mbufs[count], unsigned int count);
Or add a debug assertion at the start of the function:
RTE_ASSERT(mbufs != NULL || count == 0);
> ---
> devtools/cocci/nullfree.cocci | 5 ++++-
> doc/guides/rel_notes/release_26_07.rst | 5 +++++
> lib/mbuf/rte_mbuf.c | 3 +++
> lib/mbuf/rte_mbuf.h | 1 +
> 4 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/devtools/cocci/nullfree.cocci
> b/devtools/cocci/nullfree.cocci
> index e7417b69ff..78e30f730a 100644
> --- a/devtools/cocci/nullfree.cocci
> +++ b/devtools/cocci/nullfree.cocci
> @@ -4,7 +4,7 @@
> // free(NULL) as a no-op.
> //
> @@
> -expression E;
> +expression E, N;
> @@
> (
> - if (E != NULL) cmdline_free(E);
> @@ -79,6 +79,9 @@ expression E;
> - if (E != NULL) rte_pktmbuf_free(E);
> + rte_pktmbuf_free(E);
> |
> +- if (E != NULL) rte_pktmbuf_free_bulk(E, N);
> ++ rte_pktmbuf_free_bulk(E, N);
> +|
> - if (E != NULL) rte_rib_free(E);
> + rte_rib_free(E);
> |
> diff --git a/doc/guides/rel_notes/release_26_07.rst
> b/doc/guides/rel_notes/release_26_07.rst
> index f012d47a4b..6f2f7f849f 100644
> --- a/doc/guides/rel_notes/release_26_07.rst
> +++ b/doc/guides/rel_notes/release_26_07.rst
> @@ -63,6 +63,11 @@ New Features
> ``rte_eal_init`` and the application is responsible for probing
> each device,
> * ``--auto-probing`` enables the initial bus probing, which is the
> current default behavior.
>
> +* **mbuf: rte_pktmbuf_free_bulk now accepts NULL array pointer.**
> +
> + Calling ``rte_pktmbuf_free_bulk`` with a NULL ``mbufs`` argument is
> a no-op,
> + matching the behavior of ``rte_pktmbuf_free()`` and ``rte_free()``.
> +
>
> Removed Items
> -------------
> diff --git a/lib/mbuf/rte_mbuf.c b/lib/mbuf/rte_mbuf.c
> index c2476e7704..8ec3bb53bb 100644
> --- a/lib/mbuf/rte_mbuf.c
> +++ b/lib/mbuf/rte_mbuf.c
> @@ -562,6 +562,9 @@ void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs,
> unsigned int count)
> struct rte_mbuf *m, *m_next,
> *pending[RTE_PKTMBUF_FREE_PENDING_SZ];
> unsigned int idx, nb_pending = 0;
>
> + if (mbufs == NULL)
> + return;
> +
> rte_mbuf_history_mark_bulk(mbufs, count,
> RTE_MBUF_HISTORY_OP_LIB_FREE);
>
> for (idx = 0; idx < count; idx++) {
> diff --git a/lib/mbuf/rte_mbuf.h b/lib/mbuf/rte_mbuf.h
> index e7c3bbadd4..e9f8932e80 100644
> --- a/lib/mbuf/rte_mbuf.h
> +++ b/lib/mbuf/rte_mbuf.h
> @@ -1534,6 +1534,7 @@ static inline void rte_pktmbuf_free(struct
> rte_mbuf *m)
> * @param mbufs
> * Array of pointers to packet mbufs.
> * The array may contain NULL pointers.
> + * The array pointer is NULL function does nothing.
> * @param count
> * Array size.
> */
> --
> 2.53.0