git: 5418b1ebdfa0 - main - xdr: provide x_putmbuf method for xdrmem

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Sat, 01 Feb 2025 09:02:03 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=5418b1ebdfa0c6118894ce0e91115c3c13f3850d

commit 5418b1ebdfa0c6118894ce0e91115c3c13f3850d
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-02-01 01:01:53 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-02-01 09:00:25 +0000

    xdr: provide x_putmbuf method for xdrmem
    
    It has slightly different semantic than same method for xdrmbuf.  The
    mbuf data is copied and caller is responsible to keep or free the
    original mbuf.
    
    Reviewed by:            rmacklem, markj
    Differential Revision:  https://reviews.freebsd.org/D48548
---
 sys/xdr/xdr_mem.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/sys/xdr/xdr_mem.c b/sys/xdr/xdr_mem.c
index 65a74836b7b3..fbab893a995d 100644
--- a/sys/xdr/xdr_mem.c
+++ b/sys/xdr/xdr_mem.c
@@ -44,6 +44,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
+#include <sys/mbuf.h>
 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
@@ -55,6 +56,7 @@ static bool_t xdrmem_getlong_unaligned(XDR *, long *);
 static bool_t xdrmem_putlong_unaligned(XDR *, const long *);
 static bool_t xdrmem_getbytes(XDR *, char *, u_int);
 static bool_t xdrmem_putbytes(XDR *, const char *, u_int);
+static bool_t xdrmem_putmbuf(XDR *, struct mbuf *);
 /* XXX: w/64-bit pointers, u_int not enough! */
 static u_int xdrmem_getpos(XDR *);
 static bool_t xdrmem_setpos(XDR *, u_int);
@@ -67,6 +69,7 @@ static const struct	xdr_ops xdrmem_ops_aligned = {
 	.x_putlong =	xdrmem_putlong_aligned,
 	.x_getbytes =	xdrmem_getbytes,
 	.x_putbytes =	xdrmem_putbytes,
+	.x_putmbuf =	xdrmem_putmbuf,
 	.x_getpostn =	xdrmem_getpos,
 	.x_setpostn =	xdrmem_setpos,
 	.x_inline =	xdrmem_inline_aligned,
@@ -79,6 +82,7 @@ static const struct	xdr_ops xdrmem_ops_unaligned = {
 	.x_putlong =	xdrmem_putlong_unaligned,
 	.x_getbytes =	xdrmem_getbytes,
 	.x_putbytes =	xdrmem_putbytes,
+	.x_putmbuf =	xdrmem_putmbuf,
 	.x_getpostn =	xdrmem_getpos,
 	.x_setpostn =	xdrmem_setpos,
 	.x_inline =	xdrmem_inline_unaligned,
@@ -184,6 +188,27 @@ xdrmem_putbytes(XDR *xdrs, const char *addr, u_int len)
 	return (TRUE);
 }
 
+/*
+ * Append mbuf.  May fail if not enough space.  Caller owns the mbuf.
+ */
+static bool_t
+xdrmem_putmbuf(XDR *xdrs, struct mbuf *m)
+{
+	u_int len;
+
+	if (__predict_false(m == NULL))
+		return (TRUE);
+
+	len = m_length(m, NULL);
+
+	if (__predict_false(xdrs->x_handy < len))
+		return (FALSE);
+	xdrs->x_handy -= len;
+	m_copydata(m, 0, len, xdrs->x_private);
+	xdrs->x_private = (char *)xdrs->x_private + len;
+	return (TRUE);
+}
+
 static u_int
 xdrmem_getpos(XDR *xdrs)
 {