xref: /illumos-gate/usr/src/uts/common/rpc/mt_rpcinit.c (revision 132157d7fb25c120ae1deca2a65fa7c78e8fcfd0)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 */
31 
32 /*
33  * Define and initialize MT client/server data.
34  */
35 
36 #include	<sys/types.h>
37 #include	<sys/t_lock.h>
38 #include	<sys/kstat.h>
39 #include	<sys/systm.h>
40 #include	<sys/zone.h>
41 
42 #include	<rpc/types.h>
43 #include	<rpc/auth.h>
44 #include	<rpc/clnt.h>
45 
46 kmutex_t xid_lock;		/* XID allocation */
47 kmutex_t clnt_pending_lock;	/* for list of pending calls awaiting replies */
48 kmutex_t clnt_max_msg_lock;	/* updating max message sanity check for cots */
49 
50 zone_key_t	rpcstat_zone_key;
51 
52 /*
53  * rpcstat_zone_[init|fini]_common() ends up being nearly identical to
54  * nfsstat_zone_[init|fini]_common().  Due to them necessarily being in
55  * different modules, however, we end up needing to duplicate the code.
56  */
57 kstat_named_t *
58 rpcstat_zone_init_common(zoneid_t zoneid, const char *module, const char *name,
59     const kstat_named_t *template, size_t template_size)
60 {
61 	kstat_t *ksp;
62 	kstat_named_t *ks_data;
63 
64 
65 /*
66  * PSARC 2001/697 Contract Private Interface
67  * rpc_clts_client
68  * rpc_cots_client
69  * Changes must be reviewed by Solaris File Sharing
70  * Changes must be communicated to contract-2001-697@sun.com
71  *
72  */
73 	ks_data = kmem_alloc(template_size, KM_SLEEP);
74 	bcopy(template, ks_data, template_size);
75 	if ((ksp = kstat_create_zone(module, 0, name, "rpc",
76 	    KSTAT_TYPE_NAMED, template_size / sizeof (kstat_named_t),
77 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, zoneid)) != NULL) {
78 		ksp->ks_data = ks_data;
79 		kstat_install(ksp);
80 	}
81 	return (ks_data);
82 }
83 
84 void
85 rpcstat_zone_fini_common(zoneid_t zoneid, const char *module, const char *name)
86 {
87 	kstat_delete_byname_zone(module, 0, name, zoneid);
88 }
89 
90 static void *
91 mt_kstat_zone_init(zoneid_t zoneid)
92 {
93 	struct rpcstat *rpcstat;
94 
95 	rpcstat = kmem_alloc(sizeof (*rpcstat), KM_SLEEP);
96 
97 	clnt_clts_stats_init(zoneid, &rpcstat->rpc_clts_client);
98 	svc_clts_stats_init(zoneid, &rpcstat->rpc_clts_server);
99 
100 	clnt_cots_stats_init(zoneid, &rpcstat->rpc_cots_client);
101 	svc_cots_stats_init(zoneid, &rpcstat->rpc_cots_server);
102 
103 	return (rpcstat);
104 }
105 
106 /*
107  * Deletes the previously allocated "rpc" kstats
108  */
109 static void
110 mt_kstat_zone_fini(zoneid_t zoneid, void *data)
111 {
112 	struct rpcstat *rpcstat = data;
113 
114 	clnt_cots_stats_fini(zoneid, &rpcstat->rpc_cots_client);
115 	svc_cots_stats_fini(zoneid, &rpcstat->rpc_cots_server);
116 
117 	clnt_clts_stats_fini(zoneid, &rpcstat->rpc_clts_client);
118 	svc_clts_stats_fini(zoneid, &rpcstat->rpc_clts_server);
119 
120 	kmem_free(rpcstat, sizeof (*rpcstat));
121 }
122 
123 void
124 mt_kstat_init(void)
125 {
126 	zone_key_create(&rpcstat_zone_key, mt_kstat_zone_init, NULL,
127 	    mt_kstat_zone_fini);
128 }
129 
130 void
131 mt_kstat_fini(void)
132 {
133 	(void) zone_key_delete(rpcstat_zone_key);
134 }
135 
136 static bool_t	clnt_xid_initialized = FALSE;
137 static uint32_t clnt_xid = 0;	/* transaction id used by all clients */
138 
139 uint32_t
140 alloc_xid(void)
141 {
142 	uint32_t  xid;
143 	timestruc_t now;
144 
145 	/*
146 	 * Do a one time initialzation to better utilize the number
147 	 * space.
148 	 */
149 	mutex_enter(&xid_lock);
150 	if (clnt_xid_initialized == FALSE) {
151 		clnt_xid_initialized = TRUE;
152 		gethrestime(&now);
153 		clnt_xid = (uint32_t)((now.tv_sec << 20) |
154 		    (now.tv_nsec >> 10));
155 	}
156 
157 	xid = clnt_xid++;
158 
159 	/*
160 	 * Don't return a zero xid.  This could happen if the initialization
161 	 * happens to return zero or if clnt_xid wraps.
162 	 */
163 	if (xid == 0)
164 		xid = clnt_xid++;
165 
166 	mutex_exit(&xid_lock);
167 	return (xid);
168 }
169 
170 /*
171  * These functions are temporary and designed for the upgrade-workaround only.
172  * They cannot be used for general zone-crossing RPC client support, and will
173  * be removed shortly.
174  *
175  * Currently these functions route all nfs global clients to the global zone.
176  * When this upgrade-workaround is removed these function should return the
177  * correct zone or their calls should be changed (rpc_zone() to curproc->p_zone
178  * and rpc_zoneid() to getzoneid()).
179  */
180 struct zone *
181 rpc_zone(void)
182 {
183 	return (nfs_global_client_only != 0 ? global_zone : curproc->p_zone);
184 }
185 
186 zoneid_t
187 rpc_zoneid(void)
188 {
189 	return (nfs_global_client_only != 0 ? GLOBAL_ZONEID : getzoneid());
190 }
191