4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
30 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
34 * Portions of this source code were derived from Berkeley 4.3 BSD
35 * under license from the Regents of the University of California.
38 #include <sys/types.h>
39 #include <sys/sysmacros.h>
40 #include <sys/param.h>
41 #include <sys/cmn_err.h>
42 #include <sys/debug.h>
43 #include <rpc/types.h>
44 #include <netinet/in.h>
47 #include <sys/tiuser.h>
48 #include <sys/t_kuser.h>
52 #include <sys/stream.h>
53 #include <sys/strsubr.h>
54 #include <sys/stropts.h>
55 #include <sys/tihdr.h>
56 #include <sys/timod.h>
57 #include <sys/sunddi.h>
58 #include <sys/fcntl.h>
59 #include <sys/errno.h>
62 * Create server-side kernel RPC `master' transport handle
64 * This is public interface for creation of a server RPC transport handle
65 * for a given file descriptor. This function is called from nfs_svc()
68 * PSARC 2003/523 Contract Private Interface
70 * Changes must be reviewed by Solaris File Sharing
71 * Changes must be communicated to contract-2003-523@sun.com
74 * - fp - connection end point
75 * - max_msgsize - max receive size
77 * - addrmask - address mask
78 * - nxprt - filled with outgoing transport handle
79 * - sct - callout table to be registered with this transport handle
80 * - closeproc - optional pointer to a closeproc for this transport or NULL
81 * - id - RPC pool id (currently only NFS_SVCPOOL_ID or LM_SVCPOOL_ID)
82 * - hotstream - very MT-hot flag (TRUE for NFS, FALSE for Lock Manager)
85 * - make sure rpcmod is on the stream
86 * - call T_INFO_REQ to get the transport service type info
87 * - call transport-type specific `create' routine (svc_clts_kcreate(),
88 * svc_cots_kcreate()) to create and initialize transport for the stream
89 * - call svc_xprt_register() to register the transport handle into the
91 * - initialize transport-type independent fields (synchronization objects,
92 * thread counts, callout table, closeproc)
93 * - optionally, for CLTS transports tell streams framework that the
94 * stream can be MT-hot
95 * - call transport-type specific `start' function to tell rpcmod that
96 * the transport is ready to receive.
100 struct file
*fp
, /* connection end point */
101 uint_t max_msgsize
, /* max receive size */
103 struct netbuf
*addrmask
,
104 SVCMASTERXPRT
**nxprt
,
105 SVC_CALLOUT_TABLE
*sct
,
106 void (*closeproc
)(const SVCMASTERXPRT
*),
107 int id
, /* thread pool */
111 SVCMASTERXPRT
*xprt
= NULL
; /* service handle */
113 struct strioctl strioc
;
114 struct T_info_ack tinfo
;
119 RPCLOG(16, "svc_tli_kcreate: on file %p\n", (void *)fp
);
121 if (fp
== NULL
|| nxprt
== NULL
)
124 if (fp
->f_vnode
->v_stream
== NULL
)
128 * Make sure that an RPC interface module is on the stream.
130 wq
= fp
->f_vnode
->v_stream
->sd_wrq
;
131 while ((wq
= wq
->q_next
) != NULL
) {
132 if (strcmp(wq
->q_qinfo
->qi_minfo
->mi_idname
, "rpcmod") == 0)
136 RPCLOG0(1, "svc_tli_kcreate: no RPC module on stream\n");
141 * Find out what type of transport this is.
143 strioc
.ic_cmd
= TI_GETINFO
;
144 strioc
.ic_timout
= -1;
145 strioc
.ic_len
= sizeof (tinfo
);
146 strioc
.ic_dp
= (char *)&tinfo
;
147 tinfo
.PRIM_type
= T_INFO_REQ
;
149 error
= strioctl(fp
->f_vnode
, I_STR
, (intptr_t)&strioc
, 0, K_TO_K
,
151 if (error
|| retval
) {
152 RPCLOG(1, "svc_tli_kcreate: getinfo ioctl: %d\n", error
);
157 * Call transport-type specific `create' function.
158 * It will allocate transport structure.
160 switch (tinfo
.SERV_type
) {
162 error
= svc_clts_kcreate(fp
, max_msgsize
, &tinfo
, &xprt
);
166 error
= svc_cots_kcreate(fp
, max_msgsize
, &tinfo
, &xprt
);
169 RPCLOG(1, "svc_tli_kcreate: Bad service type %d\n",
177 * Initialize transport-type independent fields.
179 xprt
->xp_req_head
= (mblk_t
*)0;
180 xprt
->xp_req_tail
= (mblk_t
*)0;
181 xprt
->xp_full
= FALSE
;
182 xprt
->xp_enable
= FALSE
;
185 mutex_init(&xprt
->xp_req_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
186 mutex_init(&xprt
->xp_thread_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
187 xprt
->xp_type
= tinfo
.SERV_type
;
188 xprt
->xp_threads
= 0;
189 xprt
->xp_detached_threads
= 0;
192 xprt
->xp_closeproc
= closeproc
;
194 xprt
->xp_netid
= NULL
;
196 xprt
->xp_netid
= kmem_alloc(strlen(netid
) + 1, KM_SLEEP
);
197 (void) strcpy(xprt
->xp_netid
, netid
);
200 xprt
->xp_addrmask
.len
= 0;
201 xprt
->xp_addrmask
.maxlen
= 0;
202 xprt
->xp_addrmask
.buf
= NULL
;
204 if (addrmask
!= NULL
) {
205 xprt
->xp_addrmask
= *addrmask
;
209 * Register this transport handle after all fields have been
210 * initialized. The registration can fail only if we try to register
211 * with a non-existent pool (ENOENT) or a closing pool (EBUSY).
213 if (error
= svc_xprt_register(xprt
, id
)) {
214 /* if there was an addrmask, caller will delete it */
215 xprt
->xp_addrmask
.maxlen
= 0;
217 cmn_err(CE_WARN
, "svc_tli_kcreate: xprt_register failed");
223 * Set the private RPC cell in the module's data.
225 vp
= (void **)wq
->q_ptr
;
229 * Inform the streams framework that the stream may be very MT hot.
231 if (hotstream
&& tinfo
.SERV_type
== T_CLTS
) {
232 udpmaj
= ddi_name_to_major("udp");
233 if (udpmaj
!= (major_t
)-1 &&
234 getmajor(fp
->f_vnode
->v_rdev
) == udpmaj
)
235 create_putlocks(wq
, 1);
241 * Tell rpcmod that the transport is fully initialized and
242 * ready to process requests.