xref: /illumos-gate/usr/src/uts/common/fs/nfs/nfs_stats.c (revision b0fe7b8fa79924061f3bdf7f240ea116c2c0b704)
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 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/kstat.h>
30 #include <sys/zone.h>
31 #include <sys/kmem.h>
32 #include <sys/systm.h>
33 
34 #include <nfs/nfs.h>
35 #include <nfs/nfs4_kprot.h>
36 
37 /*
38  * Key to retrieve per-zone data corresponding to NFS kstats consumed by
39  * nfsstat(1m).
40  */
41 zone_key_t nfsstat_zone_key;
42 
43 /*
44  * Convenience routine to create a named kstat associated with zoneid, named
45  * module:0:name:"misc", using the provided template to initialize the names
46  * and values of the stats.
47  */
48 static kstat_named_t *
49 nfsstat_zone_init_common(zoneid_t zoneid, const char *module, int vers,
50 			    const char *name, const kstat_named_t *template,
51 			    size_t template_size)
52 {
53 	kstat_t *ksp;
54 	kstat_named_t *ks_data;
55 
56 	ks_data = kmem_alloc(template_size, KM_SLEEP);
57 	bcopy(template, ks_data, template_size);
58 	if ((ksp = kstat_create_zone(module, vers, name, "misc",
59 	    KSTAT_TYPE_NAMED, template_size / sizeof (kstat_named_t),
60 	    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, zoneid)) != NULL) {
61 		ksp->ks_data = ks_data;
62 		kstat_install(ksp);
63 	}
64 	return (ks_data);
65 }
66 
67 /*
68  * Convenience routine to remove a kstat in specified zone with name
69  * module:0:name.
70  */
71 static void
72 nfsstat_zone_fini_common(zoneid_t zoneid, const char *module, int vers,
73 			    const char *name)
74 {
75 	kstat_delete_byname_zone(module, vers, name, zoneid);
76 }
77 
78 /*
79  * Server statistics.  These are defined here, rather than in the server
80  * code, so that they can be referenced before the nfssrv kmod is loaded.
81  *
82  * The "calls" counter is a Contract Private interface covered by
83  * PSARC/2001/357.  Please contact contract-2001-357-01@eng.sun.com before
84  * making any changes.
85  */
86 
87 static const kstat_named_t svstat_tmpl[] = {
88 	{ "calls",	KSTAT_DATA_UINT64 },
89 	{ "badcalls",	KSTAT_DATA_UINT64 },
90 };
91 
92 /* Points to the global zone server kstat data for all nfs versions */
93 kstat_named_t *global_svstat_ptr[NFS_VERSMAX + 1];
94 
95 static void
96 nfsstat_zone_init_server(zoneid_t zoneid, kstat_named_t *svstatp[])
97 {
98 	int vers;
99 
100 	/*
101 	 * first two indexes of these arrays are not used, so initialize
102 	 * to NULL
103 	 */
104 	svstatp[0] = NULL;
105 	svstatp[1] = NULL;
106 	global_svstat_ptr[0] = NULL;
107 	global_svstat_ptr[0] = NULL;
108 
109 	for (vers = NFS_VERSION; vers <= NFS_V4; vers++) {
110 		svstatp[vers] = nfsstat_zone_init_common(zoneid, "nfs", vers,
111 			    "nfs_server", svstat_tmpl, sizeof (svstat_tmpl));
112 		if (zoneid == GLOBAL_ZONEID)
113 			global_svstat_ptr[vers] = svstatp[vers];
114 	}
115 }
116 
117 static void
118 nfsstat_zone_fini_server(zoneid_t zoneid, kstat_named_t **svstatp)
119 {
120 	int vers;
121 	for (vers = NFS_VERSION; vers <= NFS_V4; vers++) {
122 		if (zoneid == GLOBAL_ZONEID)
123 			global_svstat_ptr[vers] = NULL;
124 		nfsstat_zone_fini_common(zoneid, "nfs", vers, "nfs_server");
125 		kmem_free(svstatp[vers], sizeof (svstat_tmpl));
126 	}
127 }
128 
129 /*
130  * NFSv2 client stats
131  */
132 static const kstat_named_t rfsreqcnt_v2_tmpl[] = {
133 	{ "null",	KSTAT_DATA_UINT64 },
134 	{ "getattr",	KSTAT_DATA_UINT64 },
135 	{ "setattr",	KSTAT_DATA_UINT64 },
136 	{ "root",	KSTAT_DATA_UINT64 },
137 	{ "lookup",	KSTAT_DATA_UINT64 },
138 	{ "readlink",	KSTAT_DATA_UINT64 },
139 	{ "read",	KSTAT_DATA_UINT64 },
140 	{ "wrcache",	KSTAT_DATA_UINT64 },
141 	{ "write",	KSTAT_DATA_UINT64 },
142 	{ "create",	KSTAT_DATA_UINT64 },
143 	{ "remove",	KSTAT_DATA_UINT64 },
144 	{ "rename",	KSTAT_DATA_UINT64 },
145 	{ "link",	KSTAT_DATA_UINT64 },
146 	{ "symlink",	KSTAT_DATA_UINT64 },
147 	{ "mkdir",	KSTAT_DATA_UINT64 },
148 	{ "rmdir",	KSTAT_DATA_UINT64 },
149 	{ "readdir",	KSTAT_DATA_UINT64 },
150 	{ "statfs",	KSTAT_DATA_UINT64 }
151 };
152 
153 static void
154 nfsstat_zone_init_rfsreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
155 {
156 	statsp->rfsreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
157 	    "rfsreqcnt_v2", rfsreqcnt_v2_tmpl, sizeof (rfsreqcnt_v2_tmpl));
158 }
159 
160 static void
161 nfsstat_zone_fini_rfsreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
162 {
163 	nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsreqcnt_v2");
164 	kmem_free(statsp->rfsreqcnt_ptr, sizeof (rfsreqcnt_v2_tmpl));
165 }
166 
167 /*
168  * NFSv2 server stats
169  */
170 static const kstat_named_t rfsproccnt_v2_tmpl[] = {
171 	{ "null",	KSTAT_DATA_UINT64 },
172 	{ "getattr",	KSTAT_DATA_UINT64 },
173 	{ "setattr",	KSTAT_DATA_UINT64 },
174 	{ "root",	KSTAT_DATA_UINT64 },
175 	{ "lookup",	KSTAT_DATA_UINT64 },
176 	{ "readlink",	KSTAT_DATA_UINT64 },
177 	{ "read",	KSTAT_DATA_UINT64 },
178 	{ "wrcache",	KSTAT_DATA_UINT64 },
179 	{ "write",	KSTAT_DATA_UINT64 },
180 	{ "create",	KSTAT_DATA_UINT64 },
181 	{ "remove",	KSTAT_DATA_UINT64 },
182 	{ "rename",	KSTAT_DATA_UINT64 },
183 	{ "link",	KSTAT_DATA_UINT64 },
184 	{ "symlink",	KSTAT_DATA_UINT64 },
185 	{ "mkdir",	KSTAT_DATA_UINT64 },
186 	{ "rmdir",	KSTAT_DATA_UINT64 },
187 	{ "readdir",	KSTAT_DATA_UINT64 },
188 	{ "statfs",	KSTAT_DATA_UINT64 }
189 };
190 
191 kstat_named_t *rfsproccnt_v2_ptr;
192 
193 static void
194 nfsstat_zone_init_rfsproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
195 {
196 	kstat_named_t *ks_data;
197 
198 	ks_data = nfsstat_zone_init_common(zoneid, "nfs", 0, "rfsproccnt_v2",
199 	    rfsproccnt_v2_tmpl, sizeof (rfsproccnt_v2_tmpl));
200 	statsp->rfsproccnt_ptr = ks_data;
201 	if (zoneid == GLOBAL_ZONEID)
202 		rfsproccnt_v2_ptr = ks_data;
203 }
204 
205 static void
206 nfsstat_zone_fini_rfsproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
207 {
208 	if (zoneid == GLOBAL_ZONEID)
209 		rfsproccnt_v2_ptr = NULL;
210 	nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v2");
211 	kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v2_tmpl));
212 }
213 
214 /*
215  * NFSv2 client ACL stats
216  */
217 static const kstat_named_t aclreqcnt_v2_tmpl[] = {
218 	{ "null",	KSTAT_DATA_UINT64 },
219 	{ "getacl",	KSTAT_DATA_UINT64 },
220 	{ "setacl",	KSTAT_DATA_UINT64 },
221 	{ "getattr",	KSTAT_DATA_UINT64 },
222 	{ "access",	KSTAT_DATA_UINT64 },
223 	{ "getxattrdir",	KSTAT_DATA_UINT64 }
224 };
225 
226 static void
227 nfsstat_zone_init_aclreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
228 {
229 	statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
230 	    "aclreqcnt_v2", aclreqcnt_v2_tmpl, sizeof (aclreqcnt_v2_tmpl));
231 }
232 
233 static void
234 nfsstat_zone_fini_aclreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
235 {
236 	nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclreqcnt_v2");
237 	kmem_free(statsp->aclreqcnt_ptr, sizeof (aclreqcnt_v2_tmpl));
238 }
239 
240 /*
241  * NFSv2 server ACL stats
242  */
243 static const kstat_named_t aclproccnt_v2_tmpl[] = {
244 	{ "null",	KSTAT_DATA_UINT64 },
245 	{ "getacl",	KSTAT_DATA_UINT64 },
246 	{ "setacl",	KSTAT_DATA_UINT64 },
247 	{ "getattr",	KSTAT_DATA_UINT64 },
248 	{ "access",	KSTAT_DATA_UINT64 },
249 	{ "getxattrdir",	KSTAT_DATA_UINT64 }
250 };
251 
252 kstat_named_t *aclproccnt_v2_ptr;
253 
254 static void
255 nfsstat_zone_init_aclproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
256 {
257 	kstat_named_t *ks_data;
258 
259 	ks_data = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
260 	    "aclproccnt_v2", aclproccnt_v2_tmpl,
261 	    sizeof (aclproccnt_v2_tmpl));
262 	statsp->aclproccnt_ptr = ks_data;
263 	if (zoneid == GLOBAL_ZONEID)
264 		aclproccnt_v2_ptr = ks_data;
265 }
266 
267 static void
268 nfsstat_zone_fini_aclproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
269 {
270 	if (zoneid == GLOBAL_ZONEID)
271 		aclproccnt_v2_ptr = NULL;
272 	nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v2");
273 	kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v2_tmpl));
274 }
275 
276 /*
277  * NFSv3 client stats
278  */
279 static const kstat_named_t rfsreqcnt_v3_tmpl[] = {
280 	{ "null",	KSTAT_DATA_UINT64 },
281 	{ "getattr",	KSTAT_DATA_UINT64 },
282 	{ "setattr",	KSTAT_DATA_UINT64 },
283 	{ "lookup",	KSTAT_DATA_UINT64 },
284 	{ "access",	KSTAT_DATA_UINT64 },
285 	{ "readlink",	KSTAT_DATA_UINT64 },
286 	{ "read",	KSTAT_DATA_UINT64 },
287 	{ "write",	KSTAT_DATA_UINT64 },
288 	{ "create",	KSTAT_DATA_UINT64 },
289 	{ "mkdir",	KSTAT_DATA_UINT64 },
290 	{ "symlink",	KSTAT_DATA_UINT64 },
291 	{ "mknod",	KSTAT_DATA_UINT64 },
292 	{ "remove",	KSTAT_DATA_UINT64 },
293 	{ "rmdir",	KSTAT_DATA_UINT64 },
294 	{ "rename",	KSTAT_DATA_UINT64 },
295 	{ "link",	KSTAT_DATA_UINT64 },
296 	{ "readdir",	KSTAT_DATA_UINT64 },
297 	{ "readdirplus", KSTAT_DATA_UINT64 },
298 	{ "fsstat",	KSTAT_DATA_UINT64 },
299 	{ "fsinfo",	KSTAT_DATA_UINT64 },
300 	{ "pathconf",	KSTAT_DATA_UINT64 },
301 	{ "commit",	KSTAT_DATA_UINT64 }
302 };
303 
304 static void
305 nfsstat_zone_init_rfsreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
306 {
307 	statsp->rfsreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
308 	    "rfsreqcnt_v3", rfsreqcnt_v3_tmpl, sizeof (rfsreqcnt_v3_tmpl));
309 }
310 
311 static void
312 nfsstat_zone_fini_rfsreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
313 {
314 	nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsreqcnt_v3");
315 	kmem_free(statsp->rfsreqcnt_ptr, sizeof (rfsreqcnt_v3_tmpl));
316 }
317 
318 /*
319  * NFSv3 server stats
320  */
321 static const kstat_named_t rfsproccnt_v3_tmpl[] = {
322 	{ "null",	KSTAT_DATA_UINT64 },
323 	{ "getattr",	KSTAT_DATA_UINT64 },
324 	{ "setattr",	KSTAT_DATA_UINT64 },
325 	{ "lookup",	KSTAT_DATA_UINT64 },
326 	{ "access",	KSTAT_DATA_UINT64 },
327 	{ "readlink",	KSTAT_DATA_UINT64 },
328 	{ "read",	KSTAT_DATA_UINT64 },
329 	{ "write",	KSTAT_DATA_UINT64 },
330 	{ "create",	KSTAT_DATA_UINT64 },
331 	{ "mkdir",	KSTAT_DATA_UINT64 },
332 	{ "symlink",	KSTAT_DATA_UINT64 },
333 	{ "mknod",	KSTAT_DATA_UINT64 },
334 	{ "remove",	KSTAT_DATA_UINT64 },
335 	{ "rmdir",	KSTAT_DATA_UINT64 },
336 	{ "rename",	KSTAT_DATA_UINT64 },
337 	{ "link",	KSTAT_DATA_UINT64 },
338 	{ "readdir",	KSTAT_DATA_UINT64 },
339 	{ "readdirplus", KSTAT_DATA_UINT64 },
340 	{ "fsstat",	KSTAT_DATA_UINT64 },
341 	{ "fsinfo",	KSTAT_DATA_UINT64 },
342 	{ "pathconf",	KSTAT_DATA_UINT64 },
343 	{ "commit",	KSTAT_DATA_UINT64 }
344 };
345 
346 kstat_named_t *rfsproccnt_v3_ptr;
347 
348 static void
349 nfsstat_zone_init_rfsproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
350 {
351 	kstat_named_t *ks_data;
352 
353 	ks_data = nfsstat_zone_init_common(zoneid, "nfs", 0, "rfsproccnt_v3",
354 	    rfsproccnt_v3_tmpl, sizeof (rfsproccnt_v3_tmpl));
355 	statsp->rfsproccnt_ptr = ks_data;
356 	if (zoneid == GLOBAL_ZONEID)
357 		rfsproccnt_v3_ptr = ks_data;
358 }
359 
360 static void
361 nfsstat_zone_fini_rfsproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
362 {
363 	if (zoneid == GLOBAL_ZONEID)
364 		rfsproccnt_v3_ptr = NULL;
365 	nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v3");
366 	kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v3_tmpl));
367 }
368 
369 /*
370  * NFSv3 client ACL stats
371  */
372 static const kstat_named_t aclreqcnt_v3_tmpl[] = {
373 	{ "null",	KSTAT_DATA_UINT64 },
374 	{ "getacl",	KSTAT_DATA_UINT64 },
375 	{ "setacl",	KSTAT_DATA_UINT64 },
376 	{ "getxattrdir",	KSTAT_DATA_UINT64 }
377 };
378 
379 static void
380 nfsstat_zone_init_aclreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
381 {
382 	statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
383 	    "aclreqcnt_v3", aclreqcnt_v3_tmpl, sizeof (aclreqcnt_v3_tmpl));
384 }
385 
386 static void
387 nfsstat_zone_fini_aclreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
388 {
389 	nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclreqcnt_v3");
390 	kmem_free(statsp->aclreqcnt_ptr, sizeof (aclreqcnt_v3_tmpl));
391 }
392 
393 /*
394  * NFSv3 server ACL stats
395  */
396 static const kstat_named_t aclproccnt_v3_tmpl[] = {
397 	{ "null",	KSTAT_DATA_UINT64 },
398 	{ "getacl",	KSTAT_DATA_UINT64 },
399 	{ "setacl",	KSTAT_DATA_UINT64 },
400 	{ "getxattrdir",	KSTAT_DATA_UINT64 }
401 };
402 
403 kstat_named_t *aclproccnt_v3_ptr;
404 
405 static void
406 nfsstat_zone_init_aclproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
407 {
408 	kstat_named_t *ks_data;
409 
410 	ks_data = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
411 	    "aclproccnt_v3", aclproccnt_v3_tmpl,
412 	    sizeof (aclproccnt_v3_tmpl));
413 	statsp->aclproccnt_ptr = ks_data;
414 	if (zoneid == GLOBAL_ZONEID)
415 		aclproccnt_v3_ptr = ks_data;
416 }
417 
418 static void
419 nfsstat_zone_fini_aclproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
420 {
421 	if (zoneid == GLOBAL_ZONEID)
422 		aclproccnt_v3_ptr = NULL;
423 	nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v3");
424 	kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v3_tmpl));
425 }
426 
427 /*
428  * NFSv4 client stats
429  */
430 static const kstat_named_t rfsreqcnt_v4_tmpl[] = {
431 	{ "null",	KSTAT_DATA_UINT64 },
432 	{ "compound",	KSTAT_DATA_UINT64 },
433 	{ "reserved",	KSTAT_DATA_UINT64 },
434 	{ "access",	KSTAT_DATA_UINT64 },
435 	{ "close",	KSTAT_DATA_UINT64 },
436 	{ "commit",	KSTAT_DATA_UINT64 },
437 	{ "create",	KSTAT_DATA_UINT64 },
438 	{ "delegpurge",	KSTAT_DATA_UINT64 },
439 	{ "delegreturn",	KSTAT_DATA_UINT64 },
440 	{ "getattr",	KSTAT_DATA_UINT64 },
441 	{ "getfh",	KSTAT_DATA_UINT64 },
442 	{ "link",	KSTAT_DATA_UINT64 },
443 	{ "lock",	KSTAT_DATA_UINT64 },
444 	{ "lockt",	KSTAT_DATA_UINT64 },
445 	{ "locku",	KSTAT_DATA_UINT64 },
446 	{ "lookup",	KSTAT_DATA_UINT64 },
447 	{ "lookupp",	KSTAT_DATA_UINT64 },
448 	{ "nverify",	KSTAT_DATA_UINT64 },
449 	{ "open",	KSTAT_DATA_UINT64 },
450 	{ "openattr",	KSTAT_DATA_UINT64 },
451 	{ "open_confirm",	KSTAT_DATA_UINT64 },
452 	{ "open_downgrade",	KSTAT_DATA_UINT64 },
453 	{ "putfh",	KSTAT_DATA_UINT64 },
454 	{ "putpubfh",	KSTAT_DATA_UINT64 },
455 	{ "putrootfh",	KSTAT_DATA_UINT64 },
456 	{ "read",	KSTAT_DATA_UINT64 },
457 	{ "readdir",	KSTAT_DATA_UINT64 },
458 	{ "readlink",	KSTAT_DATA_UINT64 },
459 	{ "remove",	KSTAT_DATA_UINT64 },
460 	{ "rename",	KSTAT_DATA_UINT64 },
461 	{ "renew",	KSTAT_DATA_UINT64 },
462 	{ "restorefh",	KSTAT_DATA_UINT64 },
463 	{ "savefh",	KSTAT_DATA_UINT64 },
464 	{ "secinfo",	KSTAT_DATA_UINT64 },
465 	{ "setattr",	KSTAT_DATA_UINT64 },
466 	{ "setclientid",	KSTAT_DATA_UINT64 },
467 	{ "setclientid_confirm",	KSTAT_DATA_UINT64 },
468 	{ "verify", KSTAT_DATA_UINT64 },
469 	{ "write",	KSTAT_DATA_UINT64 }
470 };
471 
472 static void
473 nfsstat_zone_init_rfsreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
474 {
475 	statsp->rfsreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
476 	    "rfsreqcnt_v4", rfsreqcnt_v4_tmpl, sizeof (rfsreqcnt_v4_tmpl));
477 }
478 
479 static void
480 nfsstat_zone_fini_rfsreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
481 {
482 	nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsreqcnt_v4");
483 	kmem_free(statsp->rfsreqcnt_ptr, sizeof (rfsreqcnt_v4_tmpl));
484 }
485 
486 /*
487  * NFSv4 server stats
488  */
489 static const kstat_named_t rfsproccnt_v4_tmpl[] = {
490 	{ "null",	KSTAT_DATA_UINT64 },
491 	{ "compound",	KSTAT_DATA_UINT64 },
492 	{ "reserved",	KSTAT_DATA_UINT64 },
493 	{ "access",	KSTAT_DATA_UINT64 },
494 	{ "close",	KSTAT_DATA_UINT64 },
495 	{ "commit",	KSTAT_DATA_UINT64 },
496 	{ "create",	KSTAT_DATA_UINT64 },
497 	{ "delegpurge",	KSTAT_DATA_UINT64 },
498 	{ "delegreturn",	KSTAT_DATA_UINT64 },
499 	{ "getattr",	KSTAT_DATA_UINT64 },
500 	{ "getfh",	KSTAT_DATA_UINT64 },
501 	{ "link",	KSTAT_DATA_UINT64 },
502 	{ "lock",	KSTAT_DATA_UINT64 },
503 	{ "lockt",	KSTAT_DATA_UINT64 },
504 	{ "locku",	KSTAT_DATA_UINT64 },
505 	{ "lookup",	KSTAT_DATA_UINT64 },
506 	{ "lookupp",	KSTAT_DATA_UINT64 },
507 	{ "nverify",	KSTAT_DATA_UINT64 },
508 	{ "open",	KSTAT_DATA_UINT64 },
509 	{ "openattr",	KSTAT_DATA_UINT64 },
510 	{ "open_confirm",	KSTAT_DATA_UINT64 },
511 	{ "open_downgrade",	KSTAT_DATA_UINT64 },
512 	{ "putfh",	KSTAT_DATA_UINT64 },
513 	{ "putpubfh",	KSTAT_DATA_UINT64 },
514 	{ "putrootfh",	KSTAT_DATA_UINT64 },
515 	{ "read",	KSTAT_DATA_UINT64 },
516 	{ "readdir",	KSTAT_DATA_UINT64 },
517 	{ "readlink",	KSTAT_DATA_UINT64 },
518 	{ "remove",	KSTAT_DATA_UINT64 },
519 	{ "rename",	KSTAT_DATA_UINT64 },
520 	{ "renew",	KSTAT_DATA_UINT64 },
521 	{ "restorefh",	KSTAT_DATA_UINT64 },
522 	{ "savefh",	KSTAT_DATA_UINT64 },
523 	{ "secinfo",	KSTAT_DATA_UINT64 },
524 	{ "setattr",	KSTAT_DATA_UINT64 },
525 	{ "setclientid",	KSTAT_DATA_UINT64 },
526 	{ "setclientid_confirm",	KSTAT_DATA_UINT64 },
527 	{ "verify",	KSTAT_DATA_UINT64 },
528 	{ "write",	KSTAT_DATA_UINT64 },
529 	{ "release_lockowner",	KSTAT_DATA_UINT64 },
530 	{ "illegal",	KSTAT_DATA_UINT64 },
531 };
532 
533 kstat_named_t *rfsproccnt_v4_ptr;
534 
535 static void
536 nfsstat_zone_init_rfsproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
537 {
538 	kstat_named_t *ks_data;
539 
540 	ks_data = nfsstat_zone_init_common(zoneid, "nfs", 0, "rfsproccnt_v4",
541 	    rfsproccnt_v4_tmpl, sizeof (rfsproccnt_v4_tmpl));
542 	statsp->rfsproccnt_ptr = ks_data;
543 	if (zoneid == GLOBAL_ZONEID)
544 		rfsproccnt_v4_ptr = ks_data;
545 }
546 
547 static void
548 nfsstat_zone_fini_rfsproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
549 {
550 	if (zoneid == GLOBAL_ZONEID)
551 		rfsproccnt_v4_ptr = NULL;
552 	nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v4");
553 	kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v4_tmpl));
554 }
555 
556 /*
557  * NFSv4 client ACL stats
558  */
559 static const kstat_named_t aclreqcnt_v4_tmpl[] = {
560 	{ "null",	KSTAT_DATA_UINT64 },
561 	{ "getacl",	KSTAT_DATA_UINT64 },
562 	{ "setacl",	KSTAT_DATA_UINT64 },
563 };
564 
565 static void
566 nfsstat_zone_init_aclreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
567 {
568 	statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
569 	    "aclreqcnt_v4", aclreqcnt_v4_tmpl, sizeof (aclreqcnt_v4_tmpl));
570 }
571 
572 static void
573 nfsstat_zone_fini_aclreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
574 {
575 	nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclreqcnt_v4");
576 	kmem_free(statsp->aclreqcnt_ptr, sizeof (aclreqcnt_v4_tmpl));
577 }
578 
579 /*
580  * NFSv4 server ACL stats
581  */
582 static const kstat_named_t aclproccnt_v4_tmpl[] = {
583 	{ "null",	KSTAT_DATA_UINT64 },
584 	{ "getacl",	KSTAT_DATA_UINT64 },
585 	{ "setacl",	KSTAT_DATA_UINT64 }
586 };
587 
588 kstat_named_t *aclproccnt_v4_ptr;
589 
590 static void
591 nfsstat_zone_init_aclproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
592 {
593 	kstat_named_t *ks_data;
594 
595 	ks_data = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
596 	    "aclproccnt_v4", aclproccnt_v4_tmpl,
597 	    sizeof (aclproccnt_v4_tmpl));
598 	statsp->aclproccnt_ptr = ks_data;
599 	if (zoneid == GLOBAL_ZONEID)
600 		aclproccnt_v4_ptr = ks_data;
601 }
602 
603 static void
604 nfsstat_zone_fini_aclproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
605 {
606 	if (zoneid == GLOBAL_ZONEID)
607 		aclproccnt_v4_ptr = NULL;
608 	nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v4");
609 	kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v4_tmpl));
610 }
611 
612 /*
613  * Zone initializer callback to setup the kstats.
614  */
615 void *
616 nfsstat_zone_init(zoneid_t zoneid)
617 {
618 	struct nfs_stats *nfs_stats_ptr;
619 
620 	nfs_stats_ptr = kmem_zalloc(sizeof (*nfs_stats_ptr), KM_SLEEP);
621 
622 	/*
623 	 * Initialize all versions of the nfs_server
624 	 */
625 	nfsstat_zone_init_server(zoneid, nfs_stats_ptr->nfs_stats_svstat_ptr);
626 
627 	/*
628 	 * Initialize v2 stats
629 	 */
630 	nfsstat_zone_init_rfsreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
631 	nfsstat_zone_init_rfsproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
632 	nfsstat_zone_init_aclreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
633 	nfsstat_zone_init_aclproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
634 	/*
635 	 * Initialize v3 stats
636 	 */
637 	nfsstat_zone_init_rfsreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
638 	nfsstat_zone_init_rfsproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
639 	nfsstat_zone_init_aclreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
640 	nfsstat_zone_init_aclproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
641 	/*
642 	 * Initialize v4 stats
643 	 */
644 	nfsstat_zone_init_rfsreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
645 	nfsstat_zone_init_rfsproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
646 	nfsstat_zone_init_aclreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
647 	nfsstat_zone_init_aclproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
648 
649 	return (nfs_stats_ptr);
650 }
651 
652 /*
653  * Zone destructor callback to tear down the various kstats.
654  */
655 void
656 nfsstat_zone_fini(zoneid_t zoneid, void *data)
657 {
658 	struct nfs_stats *nfs_stats_ptr = data;
659 
660 	/*
661 	 * Free nfs:0:nfs_server stats
662 	 */
663 	nfsstat_zone_fini_server(zoneid, nfs_stats_ptr->nfs_stats_svstat_ptr);
664 
665 	/*
666 	 * Free v2 stats
667 	 */
668 	nfsstat_zone_fini_rfsreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
669 	nfsstat_zone_fini_rfsproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
670 	nfsstat_zone_fini_aclreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
671 	nfsstat_zone_fini_aclproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
672 	/*
673 	 * Free v3 stats
674 	 */
675 	nfsstat_zone_fini_rfsreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
676 	nfsstat_zone_fini_rfsproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
677 	nfsstat_zone_fini_aclreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
678 	nfsstat_zone_fini_aclproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
679 	/*
680 	 * Free v4 stats
681 	 */
682 	nfsstat_zone_fini_rfsreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
683 	nfsstat_zone_fini_rfsproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
684 	nfsstat_zone_fini_aclreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
685 	nfsstat_zone_fini_aclproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
686 
687 	kmem_free(nfs_stats_ptr, sizeof (*nfs_stats_ptr));
688 }
689