git: 717800323493 - stable/14 - xen/netfront: Decouple XENNET tags from mbuf lifetimes

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 20 Aug 2024 14:05:33 UTC
The branch stable/14 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=7178003234932e62dd552da9b39d2e6c35ed97f8

commit 7178003234932e62dd552da9b39d2e6c35ed97f8
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-08-02 13:09:41 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-08-20 13:27:05 +0000

    xen/netfront: Decouple XENNET tags from mbuf lifetimes
    
    netmap's generic mode tries to improve performance by minimizing mbuf
    allocations.  In service of this goal, it maintains an extra reference
    to the mbuf and polls the counter to see if the driver has released its
    reference by calling m_freem().  As a result, the extref destructor is
    not called when expected by the netfront driver, and mbufs tags are not
    freed.
    
    Modify the tx path to release its mbuf tags promptly when reclaiming tx
    descriptors.  They are drawn from a fixed-size pool, so otherwise are
    quickly exhausted when a netfront interface is in netmap generic mode.
    
    Co-authored by: royger
    MFC after:      2 weeks
    Fixes:  dabb3db7a817 ("xen/netfront: deal with mbuf data crossing a page boundary")
    Sponsored by:   Cloud Software Group
    Sponsored by:   Klara, Inc.
    Sponsored by:   Zenarmor
    
    (cherry picked from commit 2e4781cb12af2d13262ed5decf6fd95c8d58d9f5)
---
 sys/dev/xen/netfront/netfront.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index dafb838cf328..da0f1680a87e 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -335,8 +335,16 @@ static void mbuf_release(struct mbuf *m)
 	KASSERT(ref != NULL, ("Cannot find refcount"));
 	KASSERT(ref->count > 0, ("Invalid reference count"));
 
-	if (--ref->count == 0)
+	if (--ref->count == 0) {
+		/*
+		 * Explicitly free the tag while we hold the tx queue lock.
+		 * This ensures that the tag is deleted promptly in case
+		 * something else is holding extra references to the mbuf chain,
+		 * such as netmap.
+		 */
+		m_tag_delete(m, &ref->tag);
 		m_freem(m);
+	}
 }
 
 static void tag_free(struct m_tag *t)