git: 66612e673652 - main - xdr: provide x_putmbuf method for kernel XDR

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

URL: https://cgit.FreeBSD.org/src/commit/?id=66612e673652fce27f83402b7871fcd58447c5a0

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

    xdr: provide x_putmbuf method for kernel XDR
    
    Get it implemented for mbuf based XDR.  Right now all existing consumers
    use only mbuf based XDR.  However, future changes will require appending
    data stored in an mbuf to memory buffer based XDR.
    
    Reviewed by:            rmacklem
    Differential Revision:  https://reviews.freebsd.org/D48547
---
 sys/rpc/auth_none.c             |  4 +---
 sys/rpc/auth_unix.c             |  4 +---
 sys/rpc/rpcsec_gss/rpcsec_gss.c |  9 +++------
 sys/rpc/rpcsec_tls/auth_tls.c   |  4 +---
 sys/rpc/svc_dg.c                |  2 +-
 sys/rpc/svc_vc.c                |  4 ++--
 sys/rpc/xdr.h                   | 11 +++++++++--
 sys/xdr/xdr_mbuf.c              | 16 ++++++++++------
 8 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/sys/rpc/auth_none.c b/sys/rpc/auth_none.c
index fc0ab285b233..17b52c74c375 100644
--- a/sys/rpc/auth_none.c
+++ b/sys/rpc/auth_none.c
@@ -115,9 +115,7 @@ authnone_marshal(AUTH *client, uint32_t xid, XDR *xdrs, struct mbuf *args)
 	if (!XDR_PUTBYTES(xdrs, ap->mclient, ap->mcnt))
 		return (FALSE);
 
-	xdrmbuf_append(xdrs, args);
-
-	return (TRUE);
+	return (xdr_putmbuf(xdrs, args));
 }
 
 /* All these unused parameters are required to keep ANSI-C from grumbling */
diff --git a/sys/rpc/auth_unix.c b/sys/rpc/auth_unix.c
index 6134beb2541c..150e099a0ea4 100644
--- a/sys/rpc/auth_unix.c
+++ b/sys/rpc/auth_unix.c
@@ -251,9 +251,7 @@ authunix_marshal(AUTH *auth, uint32_t xid, XDR *xdrs, struct mbuf *args)
 	if (!XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos))
 		return (FALSE);
 
-	xdrmbuf_append(xdrs, args);
-
-	return (TRUE);
+	return (xdr_putmbuf(xdrs, args));
 }
 
 static bool_t
diff --git a/sys/rpc/rpcsec_gss/rpcsec_gss.c b/sys/rpc/rpcsec_gss/rpcsec_gss.c
index 2b566bbdb90f..62c71937a185 100644
--- a/sys/rpc/rpcsec_gss/rpcsec_gss.c
+++ b/sys/rpc/rpcsec_gss/rpcsec_gss.c
@@ -547,8 +547,7 @@ rpc_gss_marshal(AUTH *auth, uint32_t xid, XDR *xdrs, struct mbuf *args)
 			_rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM);
 			return (FALSE);
 		}
-		xdrmbuf_append(xdrs, args);
-		return (TRUE);
+		return (xdr_putmbuf(xdrs, args));
 	} else {
 		/*
 		 * Keep track of this XID + seq pair so that we can do
@@ -596,15 +595,13 @@ rpc_gss_marshal(AUTH *auth, uint32_t xid, XDR *xdrs, struct mbuf *args)
 		}
 		if (gd->gd_state != RPCSEC_GSS_ESTABLISHED ||
 		    gd->gd_cred.gc_svc == rpc_gss_svc_none) {
-			xdrmbuf_append(xdrs, args);
-			return (TRUE);
+			return (xdr_putmbuf(xdrs, args));
 		} else {
 			if (!xdr_rpc_gss_wrap_data(&args,
 				gd->gd_ctx, gd->gd_qop, gd->gd_cred.gc_svc,
 				seq))
 				return (FALSE);
-			xdrmbuf_append(xdrs, args);
-			return (TRUE);
+			return (xdr_putmbuf(xdrs, args));
 		}
 	}
 
diff --git a/sys/rpc/rpcsec_tls/auth_tls.c b/sys/rpc/rpcsec_tls/auth_tls.c
index 86b5aa53ec6f..fb3b9c05aaaf 100644
--- a/sys/rpc/rpcsec_tls/auth_tls.c
+++ b/sys/rpc/rpcsec_tls/auth_tls.c
@@ -124,9 +124,7 @@ authtls_marshal(AUTH *client, uint32_t xid, XDR *xdrs, struct mbuf *args)
 	if (!XDR_PUTBYTES(xdrs, ap->mclient, ap->mcnt))
 		return (FALSE);
 
-	xdrmbuf_append(xdrs, args);
-
-	return (TRUE);
+	return (xdr_putmbuf(xdrs, args));
 }
 
 /* All these unused parameters are required to keep ANSI-C from grumbling */
diff --git a/sys/rpc/svc_dg.c b/sys/rpc/svc_dg.c
index 02e0c9a43fd9..29c072ff9e46 100644
--- a/sys/rpc/svc_dg.c
+++ b/sys/rpc/svc_dg.c
@@ -240,7 +240,7 @@ svc_dg_reply(SVCXPRT *xprt, struct rpc_msg *msg,
 		if (!xdr_replymsg(&xdrs, msg))
 			stat = FALSE;
 		else
-			xdrmbuf_append(&xdrs, m);
+			(void)xdr_putmbuf(&xdrs, m);
 	} else {
 		stat = xdr_replymsg(&xdrs, msg);
 	}
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c
index f70aabc5425d..44c61a9141a6 100644
--- a/sys/rpc/svc_vc.c
+++ b/sys/rpc/svc_vc.c
@@ -1001,7 +1001,7 @@ svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg,
 		if (!xdr_replymsg(&xdrs, msg))
 			stat = FALSE;
 		else
-			xdrmbuf_append(&xdrs, m);
+			(void)xdr_putmbuf(&xdrs, m);
 	} else {
 		stat = xdr_replymsg(&xdrs, msg);
 	}
@@ -1085,7 +1085,7 @@ svc_vc_backchannel_reply(SVCXPRT *xprt, struct rpc_msg *msg,
 		if (!xdr_replymsg(&xdrs, msg))
 			stat = FALSE;
 		else
-			xdrmbuf_append(&xdrs, m);
+			(void)xdr_putmbuf(&xdrs, m);
 	} else {
 		stat = xdr_replymsg(&xdrs, msg);
 	}
diff --git a/sys/rpc/xdr.h b/sys/rpc/xdr.h
index 1bb03a2a58ba..4307b5101477 100644
--- a/sys/rpc/xdr.h
+++ b/sys/rpc/xdr.h
@@ -40,6 +40,8 @@
 #define _KRPC_XDR_H
 #include <sys/cdefs.h>
 
+struct mbuf;
+
 /*
  * XDR provides a conventional way for converting between C data
  * types and an external bit-string representation.  Library supplied
@@ -105,6 +107,8 @@ typedef struct XDR {
 		bool_t	(*x_getbytes)(struct XDR *, char *, u_int);
 		/* put some bytes to " */
 		bool_t	(*x_putbytes)(struct XDR *, const char *, u_int);
+		/* put mbuf or copy its bytes */
+		bool_t	(*x_putmbuf)(struct XDR *, struct mbuf *);
 		/* returns bytes off from beginning */
 		u_int	(*x_getpostn)(struct XDR *);
 		/* lets you reposition the stream */
@@ -190,6 +194,11 @@ xdr_putint32(XDR *xdrs, int32_t *ip)
 #define xdr_putbytes(xdrs, addr, len)			\
 	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
 
+#define XDR_PUTMBUF(xdrs, mbuf)				\
+	(*(xdrs)->x_ops->x_putmbuf)(xdrs, mbuf)
+#define xdr_putmbuf(xdrs, mbuf)				\
+	(*(xdrs)->x_ops->x_putmbuf)(xdrs, mbuf)
+
 #define XDR_GETPOS(xdrs)				\
 	(*(xdrs)->x_ops->x_getpostn)(xdrs)
 #define xdr_getpos(xdrs)				\
@@ -359,9 +368,7 @@ __BEGIN_DECLS
 extern void   xdrmem_create(XDR *, char *, u_int, enum xdr_op);
 
 /* XDR using mbufs */
-struct mbuf;
 extern void   xdrmbuf_create(XDR *, struct mbuf *, enum xdr_op);
-extern void   xdrmbuf_append(XDR *, struct mbuf *);
 extern struct mbuf * xdrmbuf_getall(XDR *);
 
 /* XDR pseudo records for tcp */
diff --git a/sys/xdr/xdr_mbuf.c b/sys/xdr/xdr_mbuf.c
index 896e317f5526..6cb72f8fe1b4 100644
--- a/sys/xdr/xdr_mbuf.c
+++ b/sys/xdr/xdr_mbuf.c
@@ -40,6 +40,7 @@ static bool_t xdrmbuf_getlong(XDR *, long *);
 static bool_t xdrmbuf_putlong(XDR *, const long *);
 static bool_t xdrmbuf_getbytes(XDR *, char *, u_int);
 static bool_t xdrmbuf_putbytes(XDR *, const char *, u_int);
+static bool_t xdrmbuf_putmbuf(XDR *, struct mbuf *);
 /* XXX: w/64-bit pointers, u_int not enough! */
 static u_int xdrmbuf_getpos(XDR *);
 static bool_t xdrmbuf_setpos(XDR *, u_int);
@@ -50,6 +51,7 @@ static const struct	xdr_ops xdrmbuf_ops = {
 	.x_putlong =	xdrmbuf_putlong,
 	.x_getbytes =	xdrmbuf_getbytes,
 	.x_putbytes =	xdrmbuf_putbytes,
+	.x_putmbuf =	xdrmbuf_putmbuf,
 	.x_getpostn =	xdrmbuf_getpos,
 	.x_setpostn =	xdrmbuf_setpos,
 	.x_inline =	xdrmbuf_inline,
@@ -78,17 +80,17 @@ xdrmbuf_create(XDR *xdrs, struct mbuf *m, enum xdr_op op)
 	}
 }
 
-void
-xdrmbuf_append(XDR *xdrs, struct mbuf *madd)
+/*
+ * Append mbuf.  Always succeds and we own mbuf.
+ */
+static bool_t
+xdrmbuf_putmbuf(XDR *xdrs, struct mbuf *madd)
 {
 	struct mbuf *m;
 
-	KASSERT(xdrs->x_ops == &xdrmbuf_ops && xdrs->x_op == XDR_ENCODE,
-	    ("xdrmbuf_append: invalid XDR stream"));
-
 	if (m_length(madd, NULL) == 0) {
 		m_freem(madd);
-		return;
+		return (TRUE);
 	}
 
 	m = (struct mbuf *) xdrs->x_private;
@@ -97,6 +99,8 @@ xdrmbuf_append(XDR *xdrs, struct mbuf *madd)
 	m = m_last(madd);
 	xdrs->x_private = m;
 	xdrs->x_handy = m->m_len;
+
+	return (TRUE);
 }
 
 struct mbuf *