Home | History | Annotate | Download | only in nfs
      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 (at) 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