xref: /illumos-gate/usr/src/uts/common/rpc/mt_rpcinit.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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 /*
31  * Define and initialize MT client/server data.
32  */
33 
34 #include	<sys/types.h>
35 #include	<sys/t_lock.h>
36 #include	<sys/kstat.h>
37 #include	<sys/systm.h>
38 #include	<sys/zone.h>
39 
40 #include	<rpc/types.h>
41 #include	<rpc/auth.h>
42 #include	<rpc/clnt.h>
43 
44 kmutex_t xid_lock;		/* XID allocation */
45 kmutex_t clnt_pending_lock;	/* for list of pending calls awaiting replies */
46 kmutex_t clnt_max_msg_lock;	/* updating max message sanity check for cots */
47 
48 zone_key_t	rpcstat_zone_key;
49 
50 /*
51  * rpcstat_zone_[init|fini]_common() ends up being nearly identical to
52  * nfsstat_zone_[init|fini]_common().  Due to them necessarily being in
53  * different modules, however, we end up needing to duplicate the code.
54  */
55 kstat_named_t *
56 rpcstat_zone_init_common(zoneid_t zoneid, const char *module, const char *name,
57     const kstat_named_t *template, size_t template_size)
58 {
59 	kstat_t *ksp;
60 	kstat_named_t *ks_data;
61 
62 
63 /*
64  * PSARC 2001/697 Contract Private Interface
65  * rpc_clts_client
66  * rpc_cots_client
67  * Changes must be reviewed by Solaris File Sharing
68  * Changes must be communicated to contract-2001-697@sun.com
69  *
70  */
71 	ks_data = kmem_alloc(template_size, KM_SLEEP);
72 	bcopy(template, ks_data, template_size);
73 	if ((ksp = kstat_create_zone(module, 0, name, "rpc",
74 	    KSTAT_TYPE_NAMED, template_size / sizeof (kstat_named_t),
75 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, zoneid)) != NULL) {
76 		ksp->ks_data = ks_data;
77 		kstat_install(ksp);
78 	}
79 	return (ks_data);
80 }
81 
82 void
83 rpcstat_zone_fini_common(zoneid_t zoneid, const char *module, const char *name)
84 {
85 	kstat_delete_byname_zone(module, 0, name, zoneid);
86 }
87 
88 static void *
89 mt_kstat_zone_init(zoneid_t zoneid)
90 {
91 	struct rpcstat *rpcstat;
92 
93 	rpcstat = kmem_alloc(sizeof (*rpcstat), KM_SLEEP);
94 
95 	clnt_clts_stats_init(zoneid, &rpcstat->rpc_clts_client);
96 	svc_clts_stats_init(zoneid, &rpcstat->rpc_clts_server);
97 
98 	clnt_cots_stats_init(zoneid, &rpcstat->rpc_cots_client);
99 	svc_cots_stats_init(zoneid, &rpcstat->rpc_cots_server);
100 
101 	return (rpcstat);
102 }
103 
104 /*
105  * Deletes the previously allocated "rpc" kstats
106  */
107 static void
108 mt_kstat_zone_fini(zoneid_t zoneid, void *data)
109 {
110 	struct rpcstat *rpcstat = data;
111 
112 	clnt_cots_stats_fini(zoneid, &rpcstat->rpc_cots_client);
113 	svc_cots_stats_fini(zoneid, &rpcstat->rpc_cots_server);
114 
115 	clnt_clts_stats_fini(zoneid, &rpcstat->rpc_clts_client);
116 	svc_clts_stats_fini(zoneid, &rpcstat->rpc_clts_server);
117 
118 	kmem_free(rpcstat, sizeof (*rpcstat));
119 }
120 
121 void
122 mt_kstat_init(void)
123 {
124 	zone_key_create(&rpcstat_zone_key, mt_kstat_zone_init, NULL,
125 	    mt_kstat_zone_fini);
126 }
127 
128 void
129 mt_kstat_fini(void)
130 {
131 	(void) zone_key_delete(rpcstat_zone_key);
132 }
133 
134 static bool_t	clnt_xid_initialized = FALSE;
135 static uint32_t clnt_xid = 0;	/* transaction id used by all clients */
136 
137 uint32_t
138 alloc_xid(void)
139 {
140 	uint32_t  xid;
141 	timestruc_t now;
142 
143 	/*
144 	 * Do a one time initialzation to better utilize the number
145 	 * space.
146 	 */
147 	mutex_enter(&xid_lock);
148 	if (clnt_xid_initialized == FALSE) {
149 		clnt_xid_initialized = TRUE;
150 		gethrestime(&now);
151 		clnt_xid = (uint32_t)((now.tv_sec << 20) |
152 		    (now.tv_nsec >> 10));
153 	}
154 
155 	xid = clnt_xid++;
156 
157 	/*
158 	 * Don't return a zero xid.  This could happen if the initialization
159 	 * happens to return zero or if clnt_xid wraps.
160 	 */
161 	if (xid == 0)
162 		xid = clnt_xid++;
163 
164 	mutex_exit(&xid_lock);
165 	return (xid);
166 }
167 
168 /*
169  * These functions are temporary and designed for the upgrade-workaround only.
170  * They cannot be used for general zone-crossing RPC client support, and will
171  * be removed shortly.
172  *
173  * Currently these functions route all nfs global clients to the global zone.
174  * When this upgrade-workaround is removed these function should return the
175  * correct zone or their calls should be changed (rpc_zone() to curproc->p_zone
176  * and rpc_zoneid() to getzoneid()).
177  */
178 struct zone *
179 rpc_zone(void)
180 {
181 	return (nfs_global_client_only != 0 ? global_zone : curproc->p_zone);
182 }
183 
184 zoneid_t
185 rpc_zoneid(void)
186 {
187 	return (nfs_global_client_only != 0 ? GLOBAL_ZONEID : getzoneid());
188 }
189