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