changeset 11967:f91b268929d9

6896473 Server rpcmod panic when client trying to mount rdma/krb5
author Karen Rochford <Karen.Rochford@Sun.COM>
date Mon, 22 Mar 2010 08:06:49 -0500
parents 926aaadc2d28
children 176a85f50024
files usr/src/uts/common/rpc/sec_gss/svc_rpcsec_gss.c usr/src/uts/common/rpc/svc.c usr/src/uts/common/rpc/svc.h usr/src/uts/common/rpc/svc_clts.c usr/src/uts/common/rpc/svc_cots.c usr/src/uts/common/rpc/svc_rdma.c
diffstat 6 files changed, 93 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/rpc/sec_gss/svc_rpcsec_gss.c	Mon Mar 22 11:35:36 2010 +0100
+++ b/usr/src/uts/common/rpc/sec_gss/svc_rpcsec_gss.c	Mon Mar 22 08:06:49 2010 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -970,20 +970,9 @@
 
 	/* get a xprt clone for taskq thread, taskq func must free it */
 	arg->rq_xprt = svc_clone_init();
-	svc_clone_link(rqst->rq_xprt->xp_master, arg->rq_xprt);
+	svc_clone_link(rqst->rq_xprt->xp_master, arg->rq_xprt, rqst->rq_xprt);
 	arg->rq_xprt->xp_xid = rqst->rq_xprt->xp_xid;
 
-	/* UDP uses the incoming mblk for the response, so dup it. */
-	/* Note this probably should be done by svc_clone_link().  */
-	if (rqst->rq_xprt->xp_type == T_CLTS) {
-		struct udp_data *ud_src =
-		    (struct udp_data *)rqst->rq_xprt->xp_p2buf;
-		struct udp_data *ud_dst =
-		    (struct udp_data *)arg->rq_xprt->xp_p2buf;
-		if (ud_src->ud_resp) {
-			ud_dst->ud_resp = dupb(ud_src->ud_resp);
-		}
-	}
 
 	/* set the appropriate wrap/unwrap routine for RPCSEC_GSS */
 	arg->rq_xprt->xp_auth.svc_ah_ops = svc_rpc_gss_ops;
--- a/usr/src/uts/common/rpc/svc.c	Mon Mar 22 11:35:36 2010 +0100
+++ b/usr/src/uts/common/rpc/svc.c	Mon Mar 22 08:06:49 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1469,7 +1469,7 @@
  * - call a transport specific clone routine.
  */
 void
-svc_clone_link(SVCMASTERXPRT *xprt, SVCXPRT *clone_xprt)
+svc_clone_link(SVCMASTERXPRT *xprt, SVCXPRT *clone_xprt, SVCXPRT *clone_xprt2)
 {
 	cred_t *cred = clone_xprt->xp_cred;
 
@@ -1496,14 +1496,8 @@
 	/* Restore per-thread fields (xp_cred) */
 	clone_xprt->xp_cred = cred;
 
-
-	/*
-	 * NOTICE: There is no transport-type specific code now.
-	 *	   If you want to add a transport-type specific cloning code
-	 *	   add one more operation (e.g. xp_clone()) to svc_ops,
-	 *	   implement it for each transport type, and call it here
-	 *	   through an appropriate macro (e.g. SVC_CLONE()).
-	 */
+	if (clone_xprt2)
+		SVC_CLONE_XPRT(clone_xprt2, clone_xprt);
 }
 
 /*
@@ -2192,7 +2186,7 @@
 		if (next != xprt) {
 			if (xprt)
 				svc_clone_unlink(clone_xprt);
-			svc_clone_link(next, clone_xprt);
+			svc_clone_link(next, clone_xprt, NULL);
 			xprt = next;
 		}
 
--- a/usr/src/uts/common/rpc/svc.h	Mon Mar 22 11:35:36 2010 +0100
+++ b/usr/src/uts/common/rpc/svc.h	Mon Mar 22 08:06:49 2010 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -187,6 +187,8 @@
 		/* destroy a clone xprt */
 	void	(*xp_start)(SVCMASTERXPRT *);
 		/* `ready-to-receive' */
+	void	(*xp_clone_xprt)(SVCXPRT *, SVCXPRT *);
+		/* transport specific clone function */
 };
 #else	/* _KERNEL */
 /*
@@ -510,6 +512,12 @@
  */
 
 #ifdef	_KERNEL
+
+#define	SVC_CLONE_XPRT(src_xprt, dst_xprt) \
+	if ((src_xprt)->xp_ops->xp_clone_xprt) \
+		(*(src_xprt)->xp_ops->xp_clone_xprt) \
+		    (src_xprt, dst_xprt)
+
 #define	SVC_RECV(clone_xprt, mp, msg) \
 	(*(clone_xprt)->xp_ops->xp_recv)((clone_xprt), (mp), (msg))
 
@@ -1103,7 +1111,7 @@
  */
 extern SVCXPRT *svc_clone_init(void);
 extern void svc_clone_free(SVCXPRT *);
-extern void svc_clone_link(SVCMASTERXPRT *, SVCXPRT *);
+extern void svc_clone_link(SVCMASTERXPRT *, SVCXPRT *, SVCXPRT *);
 extern void svc_clone_unlink(SVCXPRT *);
 #endif	/* _KERNEL */
 
--- a/usr/src/uts/common/rpc/svc_clts.c	Mon Mar 22 11:35:36 2010 +0100
+++ b/usr/src/uts/common/rpc/svc_clts.c	Mon Mar 22 08:06:49 2010 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- *  Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ *  Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  *  Use is subject to license terms.
  */
 
@@ -79,6 +79,7 @@
 static void		svc_clts_kclone_destroy(SVCXPRT *);
 static void		svc_clts_kfreeres(SVCXPRT *);
 static void		svc_clts_kstart(SVCMASTERXPRT *);
+static void		svc_clts_kclone_xprt(SVCXPRT *, SVCXPRT *);
 
 /*
  * Server transport operations vector.
@@ -94,7 +95,8 @@
 	svc_clts_kgetres,	/* Get pointer to response buffer */
 	svc_clts_kfreeres,	/* Destroy pre-serialized response header */
 	svc_clts_kclone_destroy, /* Destroy a clone xprt */
-	svc_clts_kstart		/* Tell `ready-to-receive' to rpcmod */
+	svc_clts_kstart,	/* Tell `ready-to-receive' to rpcmod */
+	svc_clts_kclone_xprt	/* transport specific clone xprt function */
 };
 
 /*
@@ -230,6 +232,20 @@
 {
 }
 
+static void
+svc_clts_kclone_xprt(SVCXPRT *src_xprt, SVCXPRT *dst_xprt)
+{
+	struct udp_data *ud_src =
+	    (struct udp_data *)src_xprt->xp_p2buf;
+	struct udp_data *ud_dst =
+	    (struct udp_data *)dst_xprt->xp_p2buf;
+
+	if (ud_src->ud_resp)
+		ud_dst->ud_resp = dupb(ud_src->ud_resp);
+
+}
+
+
 /*
  * Receive rpc requests.
  * Pulls a request in off the socket, checks if the packet is intact,
--- a/usr/src/uts/common/rpc/svc_cots.c	Mon Mar 22 11:35:36 2010 +0100
+++ b/usr/src/uts/common/rpc/svc_cots.c	Mon Mar 22 08:06:49 2010 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- *  Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ *  Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  *  Use is subject to license terms.
  */
 
@@ -99,7 +99,8 @@
 	svc_cots_kgetres,	/* Get pointer to response buffer */
 	svc_cots_kfreeres,	/* Destroy pre-serialized response header */
 	svc_cots_kclone_destroy, /* Destroy a clone xprt */
-	svc_cots_kstart		/* Tell `ready-to-receive' to rpcmod */
+	svc_cots_kstart,	/* Tell `ready-to-receive' to rpcmod */
+	NULL			/* Transport specific clone xprt */
 };
 
 /*
--- a/usr/src/uts/common/rpc/svc_rdma.c	Mon Mar 22 11:35:36 2010 +0100
+++ b/usr/src/uts/common/rpc/svc_rdma.c	Mon Mar 22 08:06:49 2010 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -90,12 +90,14 @@
  * Plugin connection specific data stashed away in clone SVCXPRT
  */
 struct clone_rdma_data {
+	bool_t		cloned;		/* xprt cloned for thread processing */
 	CONN		*conn;		/* RDMA connection */
 	rdma_buf_t	rpcbuf;		/* RPC req/resp buffer */
 	struct clist	*cl_reply;	/* reply chunk buffer info */
 	struct clist	*cl_wlist;		/* write list clist */
 };
 
+
 #define	MAXADDRLEN	128	/* max length for address mask */
 
 /*
@@ -115,6 +117,7 @@
 static void		svc_rdma_kclone_destroy(SVCXPRT *);
 static void		svc_rdma_kstart(SVCMASTERXPRT *);
 void			svc_rdma_kstop(SVCMASTERXPRT *);
+static void		svc_rdma_kclone_xprt(SVCXPRT *, SVCXPRT *);
 
 static int	svc_process_long_reply(SVCXPRT *, xdrproc_t,
 			caddr_t, struct rpc_msg *, bool_t, int *,
@@ -141,7 +144,8 @@
 	svc_rdma_kgetres,	/* Get pointer to response buffer */
 	svc_rdma_kfreeres,	/* Destroy pre-serialized response header */
 	svc_rdma_kclone_destroy,	/* Destroy a clone xprt */
-	svc_rdma_kstart		/* Tell `ready-to-receive' to rpcmod */
+	svc_rdma_kstart,	/* Tell `ready-to-receive' to rpcmod */
+	svc_rdma_kclone_xprt	/* Transport specific clone xprt */
 };
 
 /*
@@ -384,8 +388,46 @@
 static void
 svc_rdma_kclone_destroy(SVCXPRT *clone_xprt)
 {
+
+	struct clone_rdma_data *cdrp;
+	cdrp = (struct clone_rdma_data *)clone_xprt->xp_p2buf;
+
+	/*
+	 * Only free buffers and release connection when cloned is set.
+	 */
+	if (cdrp->cloned != TRUE)
+		return;
+
+	rdma_buf_free(cdrp->conn, &cdrp->rpcbuf);
+	if (cdrp->cl_reply) {
+		clist_free(cdrp->cl_reply);
+		cdrp->cl_reply = NULL;
+	}
+	RDMA_REL_CONN(cdrp->conn);
+
+	cdrp->cloned = 0;
 }
 
+/*
+ * Clone the xprt specific information.  It will be freed by
+ * SVC_CLONE_DESTROY.
+ */
+static void
+svc_rdma_kclone_xprt(SVCXPRT *src_xprt, SVCXPRT *dst_xprt)
+{
+	struct clone_rdma_data *srcp2;
+	struct clone_rdma_data *dstp2;
+
+	srcp2 = (struct clone_rdma_data *)src_xprt->xp_p2buf;
+	dstp2 = (struct clone_rdma_data *)dst_xprt->xp_p2buf;
+
+	if (srcp2->conn != NULL) {
+		srcp2->cloned = TRUE;
+		*dstp2 = *srcp2;
+	}
+}
+
+
 static bool_t
 svc_rdma_krecv(SVCXPRT *clone_xprt, mblk_t *mp, struct rpc_msg *msg)
 {
@@ -1029,7 +1071,18 @@
 	struct clone_rdma_data *crdp;
 	bool_t retval;
 
+	/*
+	 * If the cloned bit is true, then this transport specific
+	 * rmda data has been duplicated into another cloned xprt. Do
+	 * not free, or release the connection, it is still in use.  The
+	 * buffers will be freed and the connection released later by
+	 * SVC_CLONE_DESTROY().
+	 */
 	crdp = (struct clone_rdma_data *)clone_xprt->xp_p2buf;
+	if (crdp->cloned == TRUE) {
+		crdp->cloned = 0;
+		return (TRUE);
+	}
 
 	/*
 	 * Free the args if needed then XDR_DESTROY