xref: /illumos-gate/usr/src/uts/common/rpc/svc_gen.c (revision 2695d4f4)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  *  Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  *  Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
26*2695d4f4SMarcel Telka /*
27*2695d4f4SMarcel Telka  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
28*2695d4f4SMarcel Telka  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
317c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
357c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
367c478bd9Sstevel@tonic-gate  */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
407c478bd9Sstevel@tonic-gate #include <sys/param.h>
417c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
427c478bd9Sstevel@tonic-gate #include <sys/debug.h>
437c478bd9Sstevel@tonic-gate #include <rpc/types.h>
447c478bd9Sstevel@tonic-gate #include <netinet/in.h>
457c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
467c478bd9Sstevel@tonic-gate #include <rpc/clnt.h>
477c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
487c478bd9Sstevel@tonic-gate #include <sys/t_kuser.h>
497c478bd9Sstevel@tonic-gate #include <rpc/svc.h>
507c478bd9Sstevel@tonic-gate #include <sys/file.h>
517c478bd9Sstevel@tonic-gate #include <sys/user.h>
527c478bd9Sstevel@tonic-gate #include <sys/stream.h>
537c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
547c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
557c478bd9Sstevel@tonic-gate #include <sys/tihdr.h>
567c478bd9Sstevel@tonic-gate #include <sys/timod.h>
577c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
587c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
597c478bd9Sstevel@tonic-gate #include <sys/errno.h>
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate  * Create server-side kernel RPC `master' transport handle
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  * This is public interface for creation of a server RPC transport handle
657c478bd9Sstevel@tonic-gate  * for a given file descriptor. This function is called from nfs_svc()
667c478bd9Sstevel@tonic-gate  * and lm_svc().
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  * PSARC 2003/523 Contract Private Interface
697c478bd9Sstevel@tonic-gate  * svc_tli_kcreate
707c478bd9Sstevel@tonic-gate  * Changes must be reviewed by Solaris File Sharing
717c478bd9Sstevel@tonic-gate  * Changes must be communicated to contract-2003-523@sun.com
727c478bd9Sstevel@tonic-gate  *
737c478bd9Sstevel@tonic-gate  * Arguments:
747c478bd9Sstevel@tonic-gate  * - fp		 - connection end point
757c478bd9Sstevel@tonic-gate  * - max_msgsize - max receive size
767c478bd9Sstevel@tonic-gate  * - netid	 - netid
777c478bd9Sstevel@tonic-gate  * - addrmask	 - address mask
787c478bd9Sstevel@tonic-gate  * - nxprt       - filled with outgoing transport handle
797c478bd9Sstevel@tonic-gate  * - sct	 - callout table to be registered with this transport handle
807c478bd9Sstevel@tonic-gate  * - closeproc	 - optional pointer to a closeproc for this transport or NULL
817c478bd9Sstevel@tonic-gate  * - id	         - RPC pool id (currently only NFS_SVCPOOL_ID or LM_SVCPOOL_ID)
827c478bd9Sstevel@tonic-gate  * - hotstream	 - very MT-hot flag (TRUE for NFS, FALSE for Lock Manager)
837c478bd9Sstevel@tonic-gate  *
847c478bd9Sstevel@tonic-gate  * Description:
857c478bd9Sstevel@tonic-gate  * - make sure rpcmod is on the stream
867c478bd9Sstevel@tonic-gate  * - call T_INFO_REQ to get the transport service type info
877c478bd9Sstevel@tonic-gate  * - call transport-type specific `create' routine (svc_clts_kcreate(),
887c478bd9Sstevel@tonic-gate  *   svc_cots_kcreate()) to create and initialize transport for the stream
897c478bd9Sstevel@tonic-gate  * - call svc_xprt_register() to register the transport handle into the
907c478bd9Sstevel@tonic-gate  *   service thread pool
917c478bd9Sstevel@tonic-gate  * - initialize transport-type independent fields (synchronization objects,
927c478bd9Sstevel@tonic-gate  *   thread counts, callout table, closeproc)
937c478bd9Sstevel@tonic-gate  * - optionally, for CLTS transports tell streams framework that the
947c478bd9Sstevel@tonic-gate  *   stream can be MT-hot
957c478bd9Sstevel@tonic-gate  * - call transport-type specific `start' function to tell rpcmod that
967c478bd9Sstevel@tonic-gate  *   the transport is ready to receive.
977c478bd9Sstevel@tonic-gate  */
987c478bd9Sstevel@tonic-gate int
svc_tli_kcreate(struct file * fp,uint_t max_msgsize,char * netid,struct netbuf * addrmask,SVCMASTERXPRT ** nxprt,SVC_CALLOUT_TABLE * sct,void (* closeproc)(const SVCMASTERXPRT *),int id,bool_t hotstream)997c478bd9Sstevel@tonic-gate svc_tli_kcreate(
1007c478bd9Sstevel@tonic-gate 	struct file	*fp,		/* connection end point */
1017c478bd9Sstevel@tonic-gate 	uint_t		max_msgsize,	/* max receive size */
1027c478bd9Sstevel@tonic-gate 	char		*netid,
1037c478bd9Sstevel@tonic-gate 	struct netbuf	*addrmask,
1047c478bd9Sstevel@tonic-gate 	SVCMASTERXPRT	**nxprt,
1057c478bd9Sstevel@tonic-gate 	SVC_CALLOUT_TABLE *sct,
1067c478bd9Sstevel@tonic-gate 	void		(*closeproc)(const SVCMASTERXPRT *),
1077c478bd9Sstevel@tonic-gate 	int		id,		/* thread pool  */
1087c478bd9Sstevel@tonic-gate 	bool_t		hotstream)
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate 	queue_t		*wq;
1117c478bd9Sstevel@tonic-gate 	SVCMASTERXPRT	*xprt = NULL;	/* service handle */
1127c478bd9Sstevel@tonic-gate 	int		retval;
1137c478bd9Sstevel@tonic-gate 	struct strioctl strioc;
1147c478bd9Sstevel@tonic-gate 	struct T_info_ack tinfo;
1157c478bd9Sstevel@tonic-gate 	int		error;
1167c478bd9Sstevel@tonic-gate 	void		**vp;
1177c478bd9Sstevel@tonic-gate 	major_t		udpmaj;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	RPCLOG(16, "svc_tli_kcreate: on file %p\n", (void *)fp);
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	if (fp == NULL || nxprt == NULL)
1227c478bd9Sstevel@tonic-gate 		return (EINVAL);
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (fp->f_vnode->v_stream == NULL)
1257c478bd9Sstevel@tonic-gate 		return (ENOSTR);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/*
1287c478bd9Sstevel@tonic-gate 	 * Make sure that an RPC interface module is on the stream.
1297c478bd9Sstevel@tonic-gate 	 */
1307c478bd9Sstevel@tonic-gate 	wq = fp->f_vnode->v_stream->sd_wrq;
1317c478bd9Sstevel@tonic-gate 	while ((wq = wq->q_next) != NULL) {
1327c478bd9Sstevel@tonic-gate 		if (strcmp(wq->q_qinfo->qi_minfo->mi_idname, "rpcmod") == 0)
1337c478bd9Sstevel@tonic-gate 			break;
1347c478bd9Sstevel@tonic-gate 	}
1357c478bd9Sstevel@tonic-gate 	if (!wq) {
1367c478bd9Sstevel@tonic-gate 		RPCLOG0(1, "svc_tli_kcreate: no RPC module on stream\n");
1377c478bd9Sstevel@tonic-gate 		return (EINVAL);
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	/*
1417c478bd9Sstevel@tonic-gate 	 * Find out what type of transport this is.
1427c478bd9Sstevel@tonic-gate 	 */
1437c478bd9Sstevel@tonic-gate 	strioc.ic_cmd = TI_GETINFO;
1447c478bd9Sstevel@tonic-gate 	strioc.ic_timout = -1;
1457c478bd9Sstevel@tonic-gate 	strioc.ic_len = sizeof (tinfo);
1467c478bd9Sstevel@tonic-gate 	strioc.ic_dp = (char *)&tinfo;
1477c478bd9Sstevel@tonic-gate 	tinfo.PRIM_type = T_INFO_REQ;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	error = strioctl(fp->f_vnode, I_STR, (intptr_t)&strioc, 0, K_TO_K,
1507c478bd9Sstevel@tonic-gate 	    CRED(), &retval);
1517c478bd9Sstevel@tonic-gate 	if (error || retval) {
1527c478bd9Sstevel@tonic-gate 		RPCLOG(1, "svc_tli_kcreate: getinfo ioctl: %d\n", error);
1537c478bd9Sstevel@tonic-gate 		return (error);
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	/*
1577c478bd9Sstevel@tonic-gate 	 * Call transport-type specific `create' function.
1587c478bd9Sstevel@tonic-gate 	 * It will allocate transport structure.
1597c478bd9Sstevel@tonic-gate 	 */
1607c478bd9Sstevel@tonic-gate 	switch (tinfo.SERV_type) {
1617c478bd9Sstevel@tonic-gate 	case T_CLTS:
1627c478bd9Sstevel@tonic-gate 		error = svc_clts_kcreate(fp, max_msgsize, &tinfo, &xprt);
1637c478bd9Sstevel@tonic-gate 		break;
1647c478bd9Sstevel@tonic-gate 	case T_COTS:
1657c478bd9Sstevel@tonic-gate 	case T_COTS_ORD:
1667c478bd9Sstevel@tonic-gate 		error = svc_cots_kcreate(fp, max_msgsize, &tinfo, &xprt);
1677c478bd9Sstevel@tonic-gate 		break;
1687c478bd9Sstevel@tonic-gate 	default:
1697c478bd9Sstevel@tonic-gate 		RPCLOG(1, "svc_tli_kcreate: Bad service type %d\n",
1707c478bd9Sstevel@tonic-gate 		    tinfo.SERV_type);
1717c478bd9Sstevel@tonic-gate 		error = EINVAL;
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate 	if (error)
1747c478bd9Sstevel@tonic-gate 		return (error);
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	/*
1777c478bd9Sstevel@tonic-gate 	 * Initialize transport-type independent fields.
1787c478bd9Sstevel@tonic-gate 	 */
1797c478bd9Sstevel@tonic-gate 	xprt->xp_req_head = (mblk_t *)0;
1807c478bd9Sstevel@tonic-gate 	xprt->xp_req_tail = (mblk_t *)0;
181*2695d4f4SMarcel Telka 	xprt->xp_full = FALSE;
182*2695d4f4SMarcel Telka 	xprt->xp_enable = FALSE;
183*2695d4f4SMarcel Telka 	xprt->xp_reqs = 0;
184*2695d4f4SMarcel Telka 	xprt->xp_size = 0;
1857c478bd9Sstevel@tonic-gate 	mutex_init(&xprt->xp_req_lock, NULL, MUTEX_DEFAULT, NULL);
1867c478bd9Sstevel@tonic-gate 	mutex_init(&xprt->xp_thread_lock, NULL, MUTEX_DEFAULT, NULL);
1877c478bd9Sstevel@tonic-gate 	xprt->xp_type = tinfo.SERV_type;
1887c478bd9Sstevel@tonic-gate 	xprt->xp_threads = 0;
1897c478bd9Sstevel@tonic-gate 	xprt->xp_detached_threads = 0;
1907c478bd9Sstevel@tonic-gate 	xprt->xp_fp = fp;
1917c478bd9Sstevel@tonic-gate 	xprt->xp_wq = wq;
1927c478bd9Sstevel@tonic-gate 	xprt->xp_closeproc = closeproc;
1937c478bd9Sstevel@tonic-gate 	xprt->xp_sct = sct;
1947c478bd9Sstevel@tonic-gate 	xprt->xp_netid = NULL;
1957c478bd9Sstevel@tonic-gate 	if (netid != NULL) {
1967c478bd9Sstevel@tonic-gate 		xprt->xp_netid = kmem_alloc(strlen(netid) + 1, KM_SLEEP);
1977c478bd9Sstevel@tonic-gate 		(void) strcpy(xprt->xp_netid, netid);
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	xprt->xp_addrmask.len = 0;
2017c478bd9Sstevel@tonic-gate 	xprt->xp_addrmask.maxlen = 0;
2027c478bd9Sstevel@tonic-gate 	xprt->xp_addrmask.buf = NULL;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	if (addrmask != NULL) {
2057c478bd9Sstevel@tonic-gate 		xprt->xp_addrmask = *addrmask;
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	/*
2097c478bd9Sstevel@tonic-gate 	 * Register this transport handle after all fields have been
2107c478bd9Sstevel@tonic-gate 	 * initialized. The registration can fail only if we try to register
2117c478bd9Sstevel@tonic-gate 	 * with a non-existent pool (ENOENT) or a closing pool (EBUSY).
2127c478bd9Sstevel@tonic-gate 	 */
2137c478bd9Sstevel@tonic-gate 	if (error = svc_xprt_register(xprt, id)) {
2147c478bd9Sstevel@tonic-gate 		/* if there was an addrmask, caller will delete it */
2157c478bd9Sstevel@tonic-gate 		xprt->xp_addrmask.maxlen = 0;
2167c478bd9Sstevel@tonic-gate 		SVC_DESTROY(xprt);
2177c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "svc_tli_kcreate: xprt_register failed");
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 		return (error);
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	/*
2237c478bd9Sstevel@tonic-gate 	 * Set the private RPC cell in the module's data.
2247c478bd9Sstevel@tonic-gate 	 */
2257c478bd9Sstevel@tonic-gate 	vp = (void **)wq->q_ptr;
2267c478bd9Sstevel@tonic-gate 	vp[0] = xprt;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	/*
2297c478bd9Sstevel@tonic-gate 	 * Inform the streams framework that the stream may be very MT hot.
2307c478bd9Sstevel@tonic-gate 	 */
2317c478bd9Sstevel@tonic-gate 	if (hotstream && tinfo.SERV_type == T_CLTS) {
2327c478bd9Sstevel@tonic-gate 		udpmaj = ddi_name_to_major("udp");
2337c478bd9Sstevel@tonic-gate 		if (udpmaj != (major_t)-1 &&
2347c478bd9Sstevel@tonic-gate 		    getmajor(fp->f_vnode->v_rdev) == udpmaj)
2357c478bd9Sstevel@tonic-gate 			create_putlocks(wq, 1);
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	*nxprt = xprt;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	/*
2417c478bd9Sstevel@tonic-gate 	 * Tell rpcmod that the transport is fully initialized and
2427c478bd9Sstevel@tonic-gate 	 * ready to process requests.
2437c478bd9Sstevel@tonic-gate 	 */
2447c478bd9Sstevel@tonic-gate 	SVC_START(xprt);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	return (0);
2477c478bd9Sstevel@tonic-gate }
248