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 /* 23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/kstat.h> 33 #include <sys/zone.h> 34 #include <sys/kmem.h> 35 #include <sys/systm.h> 36 37 #include <nfs/nfs.h> 38 #include <nfs/nfs4_kprot.h> 39 40 /* 41 * Key to retrieve per-zone data corresponding to NFS kstats consumed by 42 * nfsstat(1m). 43 */ 44 zone_key_t nfsstat_zone_key; 45 46 /* 47 * Convenience routine to create a named kstat associated with zoneid, named 48 * module:0:name:"misc", using the provided template to initialize the names 49 * and values of the stats. 50 */ 51 static kstat_named_t * 52 nfsstat_zone_init_common(zoneid_t zoneid, const char *module, int vers, 53 const char *name, const kstat_named_t *template, 54 size_t template_size) 55 { 56 kstat_t *ksp; 57 kstat_named_t *ks_data; 58 59 ks_data = kmem_alloc(template_size, KM_SLEEP); 60 bcopy(template, ks_data, template_size); 61 if ((ksp = kstat_create_zone(module, vers, name, "misc", 62 KSTAT_TYPE_NAMED, template_size / sizeof (kstat_named_t), 63 KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, zoneid)) != NULL) { 64 ksp->ks_data = ks_data; 65 kstat_install(ksp); 66 } 67 return (ks_data); 68 } 69 70 /* 71 * Convenience routine to remove a kstat in specified zone with name 72 * module:0:name. 73 */ 74 static void 75 nfsstat_zone_fini_common(zoneid_t zoneid, const char *module, int vers, 76 const char *name) 77 { 78 kstat_delete_byname_zone(module, vers, name, zoneid); 79 } 80 81 /* 82 * Server statistics. These are defined here, rather than in the server 83 * code, so that they can be referenced before the nfssrv kmod is loaded. 84 * 85 * The "calls" counter is a Contract Private interface covered by 86 * PSARC/2001/357. Please contact contract-2001-357-01@eng.sun.com before 87 * making any changes. 88 */ 89 90 static const kstat_named_t svstat_tmpl[] = { 91 { "calls", KSTAT_DATA_UINT64 }, 92 { "badcalls", KSTAT_DATA_UINT64 }, 93 { "referrals", KSTAT_DATA_UINT64 }, 94 { "referlinks", KSTAT_DATA_UINT64 }, 95 }; 96 97 /* Points to the global zone server kstat data for all nfs versions */ 98 kstat_named_t *global_svstat_ptr[NFS_VERSMAX + 1]; 99 100 static void 101 nfsstat_zone_init_server(zoneid_t zoneid, kstat_named_t *svstatp[]) 102 { 103 int vers; 104 105 /* 106 * first two indexes of these arrays are not used, so initialize 107 * to NULL 108 */ 109 svstatp[0] = NULL; 110 svstatp[1] = NULL; 111 global_svstat_ptr[0] = NULL; 112 global_svstat_ptr[0] = NULL; 113 114 for (vers = NFS_VERSION; vers <= NFS_V4; vers++) { 115 svstatp[vers] = nfsstat_zone_init_common(zoneid, "nfs", vers, 116 "nfs_server", svstat_tmpl, sizeof (svstat_tmpl)); 117 if (zoneid == GLOBAL_ZONEID) 118 global_svstat_ptr[vers] = svstatp[vers]; 119 } 120 } 121 122 static void 123 nfsstat_zone_fini_server(zoneid_t zoneid, kstat_named_t **svstatp) 124 { 125 int vers; 126 for (vers = NFS_VERSION; vers <= NFS_V4; vers++) { 127 if (zoneid == GLOBAL_ZONEID) 128 global_svstat_ptr[vers] = NULL; 129 nfsstat_zone_fini_common(zoneid, "nfs", vers, "nfs_server"); 130 kmem_free(svstatp[vers], sizeof (svstat_tmpl)); 131 } 132 } 133 134 /* 135 * Support functions for the kstat_io alloc/free 136 */ 137 static kstat_t ** 138 rfs_kstat_io_init(zoneid_t zoneid, const char *module, int instance, 139 const char *name, const char *class, const kstat_named_t *tmpl, int count, 140 kmutex_t *lock) 141 { 142 int i; 143 kstat_t **ret = kmem_alloc(count * sizeof (*ret), KM_SLEEP); 144 145 for (i = 0; i < count; i++) { 146 char namebuf[KSTAT_STRLEN]; 147 148 (void) snprintf(namebuf, sizeof (namebuf), "%s_%s", name, 149 tmpl[i].name); 150 ret[i] = kstat_create_zone(module, instance, namebuf, class, 151 KSTAT_TYPE_IO, 1, 0, zoneid); 152 if (ret[i] != NULL) { 153 ret[i]->ks_lock = lock; 154 kstat_install(ret[i]); 155 } 156 } 157 158 return (ret); 159 } 160 161 static void 162 rfs_kstat_io_delete(kstat_t **ks, int count) 163 { 164 int i; 165 166 for (i = 0; i < count; i++) { 167 if (ks[i] != NULL) { 168 kstat_delete(ks[i]); 169 ks[i] = NULL; 170 } 171 } 172 } 173 174 static void 175 rfs_kstat_io_free(kstat_t **ks, int count) 176 { 177 rfs_kstat_io_delete(ks, count); 178 kmem_free(ks, count * sizeof (*ks)); 179 } 180 181 /* 182 * NFSv2 client stats 183 */ 184 static const kstat_named_t rfsreqcnt_v2_tmpl[] = { 185 { "null", KSTAT_DATA_UINT64 }, 186 { "getattr", KSTAT_DATA_UINT64 }, 187 { "setattr", KSTAT_DATA_UINT64 }, 188 { "root", KSTAT_DATA_UINT64 }, 189 { "lookup", KSTAT_DATA_UINT64 }, 190 { "readlink", KSTAT_DATA_UINT64 }, 191 { "read", KSTAT_DATA_UINT64 }, 192 { "wrcache", KSTAT_DATA_UINT64 }, 193 { "write", KSTAT_DATA_UINT64 }, 194 { "create", KSTAT_DATA_UINT64 }, 195 { "remove", KSTAT_DATA_UINT64 }, 196 { "rename", KSTAT_DATA_UINT64 }, 197 { "link", KSTAT_DATA_UINT64 }, 198 { "symlink", KSTAT_DATA_UINT64 }, 199 { "mkdir", KSTAT_DATA_UINT64 }, 200 { "rmdir", KSTAT_DATA_UINT64 }, 201 { "readdir", KSTAT_DATA_UINT64 }, 202 { "statfs", KSTAT_DATA_UINT64 } 203 }; 204 205 static void 206 nfsstat_zone_init_rfsreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp) 207 { 208 statsp->rfsreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0, 209 "rfsreqcnt_v2", rfsreqcnt_v2_tmpl, sizeof (rfsreqcnt_v2_tmpl)); 210 } 211 212 static void 213 nfsstat_zone_fini_rfsreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp) 214 { 215 nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsreqcnt_v2"); 216 kmem_free(statsp->rfsreqcnt_ptr, sizeof (rfsreqcnt_v2_tmpl)); 217 } 218 219 /* 220 * NFSv2 server stats 221 */ 222 static const kstat_named_t rfsproccnt_v2_tmpl[] = { 223 { "null", KSTAT_DATA_UINT64 }, 224 { "getattr", KSTAT_DATA_UINT64 }, 225 { "setattr", KSTAT_DATA_UINT64 }, 226 { "root", KSTAT_DATA_UINT64 }, 227 { "lookup", KSTAT_DATA_UINT64 }, 228 { "readlink", KSTAT_DATA_UINT64 }, 229 { "read", KSTAT_DATA_UINT64 }, 230 { "wrcache", KSTAT_DATA_UINT64 }, 231 { "write", KSTAT_DATA_UINT64 }, 232 { "create", KSTAT_DATA_UINT64 }, 233 { "remove", KSTAT_DATA_UINT64 }, 234 { "rename", KSTAT_DATA_UINT64 }, 235 { "link", KSTAT_DATA_UINT64 }, 236 { "symlink", KSTAT_DATA_UINT64 }, 237 { "mkdir", KSTAT_DATA_UINT64 }, 238 { "rmdir", KSTAT_DATA_UINT64 }, 239 { "readdir", KSTAT_DATA_UINT64 }, 240 { "statfs", KSTAT_DATA_UINT64 } 241 }; 242 243 #define RFSPROCCNT_V2_COUNT \ 244 (sizeof (rfsproccnt_v2_tmpl) / sizeof (rfsproccnt_v2_tmpl[0])) 245 246 kstat_named_t *rfsproccnt_v2_ptr; 247 kstat_t **rfsprocio_v2_ptr; 248 249 static void 250 nfsstat_zone_init_rfsproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp) 251 { 252 statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0, 253 "rfsproccnt_v2", rfsproccnt_v2_tmpl, sizeof (rfsproccnt_v2_tmpl)); 254 255 mutex_init(&statsp->rfsprocio_lock, NULL, MUTEX_DEFAULT, NULL); 256 257 statsp->rfsprocio_ptr = rfs_kstat_io_init(zoneid, "nfs", 0, 258 "rfsprocio_v2", "rfsprocio_v2", rfsproccnt_v2_tmpl, 259 RFSPROCCNT_V2_COUNT, &statsp->rfsprocio_lock); 260 261 if (zoneid == GLOBAL_ZONEID) { 262 rfsproccnt_v2_ptr = statsp->rfsproccnt_ptr; 263 rfsprocio_v2_ptr = statsp->rfsprocio_ptr; 264 } 265 } 266 267 static void 268 nfsstat_zone_fini_rfsproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp) 269 { 270 if (zoneid == GLOBAL_ZONEID) { 271 rfsproccnt_v2_ptr = NULL; 272 rfsprocio_v2_ptr = NULL; 273 } 274 275 nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v2"); 276 kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v2_tmpl)); 277 278 rfs_kstat_io_free(statsp->rfsprocio_ptr, RFSPROCCNT_V2_COUNT); 279 280 mutex_destroy(&statsp->rfsprocio_lock); 281 } 282 283 /* 284 * NFSv2 client ACL stats 285 */ 286 static const kstat_named_t aclreqcnt_v2_tmpl[] = { 287 { "null", KSTAT_DATA_UINT64 }, 288 { "getacl", KSTAT_DATA_UINT64 }, 289 { "setacl", KSTAT_DATA_UINT64 }, 290 { "getattr", KSTAT_DATA_UINT64 }, 291 { "access", KSTAT_DATA_UINT64 }, 292 { "getxattrdir", KSTAT_DATA_UINT64 } 293 }; 294 295 static void 296 nfsstat_zone_init_aclreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp) 297 { 298 statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0, 299 "aclreqcnt_v2", aclreqcnt_v2_tmpl, sizeof (aclreqcnt_v2_tmpl)); 300 } 301 302 static void 303 nfsstat_zone_fini_aclreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp) 304 { 305 nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclreqcnt_v2"); 306 kmem_free(statsp->aclreqcnt_ptr, sizeof (aclreqcnt_v2_tmpl)); 307 } 308 309 /* 310 * NFSv2 server ACL stats 311 */ 312 static const kstat_named_t aclproccnt_v2_tmpl[] = { 313 { "null", KSTAT_DATA_UINT64 }, 314 { "getacl", KSTAT_DATA_UINT64 }, 315 { "setacl", KSTAT_DATA_UINT64 }, 316 { "getattr", KSTAT_DATA_UINT64 }, 317 { "access", KSTAT_DATA_UINT64 }, 318 { "getxattrdir", KSTAT_DATA_UINT64 } 319 }; 320 321 #define ACLPROCCNT_V2_COUNT \ 322 (sizeof (aclproccnt_v2_tmpl) / sizeof (aclproccnt_v2_tmpl[0])) 323 324 kstat_named_t *aclproccnt_v2_ptr; 325 kstat_t **aclprocio_v2_ptr; 326 327 static void 328 nfsstat_zone_init_aclproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp) 329 { 330 statsp->aclproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0, 331 "aclproccnt_v2", aclproccnt_v2_tmpl, sizeof (aclproccnt_v2_tmpl)); 332 333 mutex_init(&statsp->aclprocio_lock, NULL, MUTEX_DEFAULT, NULL); 334 335 statsp->aclprocio_ptr = rfs_kstat_io_init(zoneid, "nfs_acl", 0, 336 "aclprocio_v2", "aclprocio_v2", aclproccnt_v2_tmpl, 337 ACLPROCCNT_V2_COUNT, &statsp->aclprocio_lock); 338 339 if (zoneid == GLOBAL_ZONEID) { 340 aclproccnt_v2_ptr = statsp->aclproccnt_ptr; 341 aclprocio_v2_ptr = statsp->aclprocio_ptr; 342 } 343 } 344 345 static void 346 nfsstat_zone_fini_aclproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp) 347 { 348 if (zoneid == GLOBAL_ZONEID) { 349 aclproccnt_v2_ptr = NULL; 350 aclprocio_v2_ptr = NULL; 351 } 352 353 nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v2"); 354 kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v2_tmpl)); 355 356 rfs_kstat_io_free(statsp->aclprocio_ptr, ACLPROCCNT_V2_COUNT); 357 358 mutex_destroy(&statsp->aclprocio_lock); 359 } 360 361 /* 362 * NFSv3 client stats 363 */ 364 static const kstat_named_t rfsreqcnt_v3_tmpl[] = { 365 { "null", KSTAT_DATA_UINT64 }, 366 { "getattr", KSTAT_DATA_UINT64 }, 367 { "setattr", KSTAT_DATA_UINT64 }, 368 { "lookup", KSTAT_DATA_UINT64 }, 369 { "access", KSTAT_DATA_UINT64 }, 370 { "readlink", KSTAT_DATA_UINT64 }, 371 { "read", KSTAT_DATA_UINT64 }, 372 { "write", KSTAT_DATA_UINT64 }, 373 { "create", KSTAT_DATA_UINT64 }, 374 { "mkdir", KSTAT_DATA_UINT64 }, 375 { "symlink", KSTAT_DATA_UINT64 }, 376 { "mknod", KSTAT_DATA_UINT64 }, 377 { "remove", KSTAT_DATA_UINT64 }, 378 { "rmdir", KSTAT_DATA_UINT64 }, 379 { "rename", KSTAT_DATA_UINT64 }, 380 { "link", KSTAT_DATA_UINT64 }, 381 { "readdir", KSTAT_DATA_UINT64 }, 382 { "readdirplus", KSTAT_DATA_UINT64 }, 383 { "fsstat", KSTAT_DATA_UINT64 }, 384 { "fsinfo", KSTAT_DATA_UINT64 }, 385 { "pathconf", KSTAT_DATA_UINT64 }, 386 { "commit", KSTAT_DATA_UINT64 } 387 }; 388 389 static void 390 nfsstat_zone_init_rfsreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp) 391 { 392 statsp->rfsreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0, 393 "rfsreqcnt_v3", rfsreqcnt_v3_tmpl, sizeof (rfsreqcnt_v3_tmpl)); 394 } 395 396 static void 397 nfsstat_zone_fini_rfsreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp) 398 { 399 nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsreqcnt_v3"); 400 kmem_free(statsp->rfsreqcnt_ptr, sizeof (rfsreqcnt_v3_tmpl)); 401 } 402 403 /* 404 * NFSv3 server stats 405 */ 406 static const kstat_named_t rfsproccnt_v3_tmpl[] = { 407 { "null", KSTAT_DATA_UINT64 }, 408 { "getattr", KSTAT_DATA_UINT64 }, 409 { "setattr", KSTAT_DATA_UINT64 }, 410 { "lookup", KSTAT_DATA_UINT64 }, 411 { "access", KSTAT_DATA_UINT64 }, 412 { "readlink", KSTAT_DATA_UINT64 }, 413 { "read", KSTAT_DATA_UINT64 }, 414 { "write", KSTAT_DATA_UINT64 }, 415 { "create", KSTAT_DATA_UINT64 }, 416 { "mkdir", KSTAT_DATA_UINT64 }, 417 { "symlink", KSTAT_DATA_UINT64 }, 418 { "mknod", KSTAT_DATA_UINT64 }, 419 { "remove", KSTAT_DATA_UINT64 }, 420 { "rmdir", KSTAT_DATA_UINT64 }, 421 { "rename", KSTAT_DATA_UINT64 }, 422 { "link", KSTAT_DATA_UINT64 }, 423 { "readdir", KSTAT_DATA_UINT64 }, 424 { "readdirplus", KSTAT_DATA_UINT64 }, 425 { "fsstat", KSTAT_DATA_UINT64 }, 426 { "fsinfo", KSTAT_DATA_UINT64 }, 427 { "pathconf", KSTAT_DATA_UINT64 }, 428 { "commit", KSTAT_DATA_UINT64 } 429 }; 430 431 #define RFSPROCCNT_V3_COUNT \ 432 (sizeof (rfsproccnt_v3_tmpl) / sizeof (rfsproccnt_v3_tmpl[0])) 433 434 kstat_named_t *rfsproccnt_v3_ptr; 435 kstat_t **rfsprocio_v3_ptr; 436 437 static void 438 nfsstat_zone_init_rfsproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp) 439 { 440 statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0, 441 "rfsproccnt_v3", rfsproccnt_v3_tmpl, sizeof (rfsproccnt_v3_tmpl)); 442 443 mutex_init(&statsp->rfsprocio_lock, NULL, MUTEX_DEFAULT, NULL); 444 445 statsp->rfsprocio_ptr = rfs_kstat_io_init(zoneid, "nfs", 0, 446 "rfsprocio_v3", "rfsprocio_v3", rfsproccnt_v3_tmpl, 447 RFSPROCCNT_V3_COUNT, &statsp->rfsprocio_lock); 448 449 if (zoneid == GLOBAL_ZONEID) { 450 rfsproccnt_v3_ptr = statsp->rfsproccnt_ptr; 451 rfsprocio_v3_ptr = statsp->rfsprocio_ptr; 452 } 453 } 454 455 static void 456 nfsstat_zone_fini_rfsproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp) 457 { 458 if (zoneid == GLOBAL_ZONEID) { 459 rfsproccnt_v3_ptr = NULL; 460 rfsprocio_v3_ptr = NULL; 461 } 462 463 nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v3"); 464 kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v3_tmpl)); 465 466 rfs_kstat_io_free(statsp->rfsprocio_ptr, RFSPROCCNT_V3_COUNT); 467 468 mutex_destroy(&statsp->rfsprocio_lock); 469 } 470 471 /* 472 * NFSv3 client ACL stats 473 */ 474 static const kstat_named_t aclreqcnt_v3_tmpl[] = { 475 { "null", KSTAT_DATA_UINT64 }, 476 { "getacl", KSTAT_DATA_UINT64 }, 477 { "setacl", KSTAT_DATA_UINT64 }, 478 { "getxattrdir", KSTAT_DATA_UINT64 } 479 }; 480 481 static void 482 nfsstat_zone_init_aclreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp) 483 { 484 statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0, 485 "aclreqcnt_v3", aclreqcnt_v3_tmpl, sizeof (aclreqcnt_v3_tmpl)); 486 } 487 488 static void 489 nfsstat_zone_fini_aclreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp) 490 { 491 nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclreqcnt_v3"); 492 kmem_free(statsp->aclreqcnt_ptr, sizeof (aclreqcnt_v3_tmpl)); 493 } 494 495 /* 496 * NFSv3 server ACL stats 497 */ 498 static const kstat_named_t aclproccnt_v3_tmpl[] = { 499 { "null", KSTAT_DATA_UINT64 }, 500 { "getacl", KSTAT_DATA_UINT64 }, 501 { "setacl", KSTAT_DATA_UINT64 }, 502 { "getxattrdir", KSTAT_DATA_UINT64 } 503 }; 504 505 #define ACLPROCCNT_V3_COUNT \ 506 (sizeof (aclproccnt_v3_tmpl) / sizeof (aclproccnt_v3_tmpl[0])) 507 508 kstat_named_t *aclproccnt_v3_ptr; 509 kstat_t **aclprocio_v3_ptr; 510 511 static void 512 nfsstat_zone_init_aclproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp) 513 { 514 statsp->aclproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0, 515 "aclproccnt_v3", aclproccnt_v3_tmpl, sizeof (aclproccnt_v3_tmpl)); 516 517 mutex_init(&statsp->aclprocio_lock, NULL, MUTEX_DEFAULT, NULL); 518 519 statsp->aclprocio_ptr = rfs_kstat_io_init(zoneid, "nfs_acl", 0, 520 "aclprocio_v3", "aclprocio_v3", aclproccnt_v3_tmpl, 521 ACLPROCCNT_V3_COUNT, &statsp->aclprocio_lock); 522 523 if (zoneid == GLOBAL_ZONEID) { 524 aclproccnt_v3_ptr = statsp->aclproccnt_ptr; 525 aclprocio_v3_ptr = statsp->aclprocio_ptr; 526 } 527 } 528 529 static void 530 nfsstat_zone_fini_aclproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp) 531 { 532 if (zoneid == GLOBAL_ZONEID) { 533 aclproccnt_v3_ptr = NULL; 534 aclprocio_v3_ptr = NULL; 535 } 536 537 nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v3"); 538 kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v3_tmpl)); 539 540 rfs_kstat_io_free(statsp->aclprocio_ptr, ACLPROCCNT_V3_COUNT); 541 542 mutex_destroy(&statsp->aclprocio_lock); 543 } 544 545 /* 546 * NFSv4 client stats 547 */ 548 static const kstat_named_t rfsreqcnt_v4_tmpl[] = { 549 { "null", KSTAT_DATA_UINT64 }, 550 { "compound", KSTAT_DATA_UINT64 }, 551 { "reserved", KSTAT_DATA_UINT64 }, 552 { "access", KSTAT_DATA_UINT64 }, 553 { "close", KSTAT_DATA_UINT64 }, 554 { "commit", KSTAT_DATA_UINT64 }, 555 { "create", KSTAT_DATA_UINT64 }, 556 { "delegpurge", KSTAT_DATA_UINT64 }, 557 { "delegreturn", KSTAT_DATA_UINT64 }, 558 { "getattr", KSTAT_DATA_UINT64 }, 559 { "getfh", KSTAT_DATA_UINT64 }, 560 { "link", KSTAT_DATA_UINT64 }, 561 { "lock", KSTAT_DATA_UINT64 }, 562 { "lockt", KSTAT_DATA_UINT64 }, 563 { "locku", KSTAT_DATA_UINT64 }, 564 { "lookup", KSTAT_DATA_UINT64 }, 565 { "lookupp", KSTAT_DATA_UINT64 }, 566 { "nverify", KSTAT_DATA_UINT64 }, 567 { "open", KSTAT_DATA_UINT64 }, 568 { "openattr", KSTAT_DATA_UINT64 }, 569 { "open_confirm", KSTAT_DATA_UINT64 }, 570 { "open_downgrade", KSTAT_DATA_UINT64 }, 571 { "putfh", KSTAT_DATA_UINT64 }, 572 { "putpubfh", KSTAT_DATA_UINT64 }, 573 { "putrootfh", KSTAT_DATA_UINT64 }, 574 { "read", KSTAT_DATA_UINT64 }, 575 { "readdir", KSTAT_DATA_UINT64 }, 576 { "readlink", KSTAT_DATA_UINT64 }, 577 { "remove", KSTAT_DATA_UINT64 }, 578 { "rename", KSTAT_DATA_UINT64 }, 579 { "renew", KSTAT_DATA_UINT64 }, 580 { "restorefh", KSTAT_DATA_UINT64 }, 581 { "savefh", KSTAT_DATA_UINT64 }, 582 { "secinfo", KSTAT_DATA_UINT64 }, 583 { "setattr", KSTAT_DATA_UINT64 }, 584 { "setclientid", KSTAT_DATA_UINT64 }, 585 { "setclientid_confirm", KSTAT_DATA_UINT64 }, 586 { "verify", KSTAT_DATA_UINT64 }, 587 { "write", KSTAT_DATA_UINT64 } 588 }; 589 590 static void 591 nfsstat_zone_init_rfsreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp) 592 { 593 statsp->rfsreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0, 594 "rfsreqcnt_v4", rfsreqcnt_v4_tmpl, sizeof (rfsreqcnt_v4_tmpl)); 595 } 596 597 static void 598 nfsstat_zone_fini_rfsreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp) 599 { 600 nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsreqcnt_v4"); 601 kmem_free(statsp->rfsreqcnt_ptr, sizeof (rfsreqcnt_v4_tmpl)); 602 } 603 604 /* 605 * NFSv4 server stats 606 */ 607 static const kstat_named_t rfsproccnt_v4_tmpl[] = { 608 { "null", KSTAT_DATA_UINT64 }, 609 { "compound", KSTAT_DATA_UINT64 }, 610 { "reserved", KSTAT_DATA_UINT64 }, 611 { "access", KSTAT_DATA_UINT64 }, 612 { "close", KSTAT_DATA_UINT64 }, 613 { "commit", KSTAT_DATA_UINT64 }, 614 { "create", KSTAT_DATA_UINT64 }, 615 { "delegpurge", KSTAT_DATA_UINT64 }, 616 { "delegreturn", KSTAT_DATA_UINT64 }, 617 { "getattr", KSTAT_DATA_UINT64 }, 618 { "getfh", KSTAT_DATA_UINT64 }, 619 { "link", KSTAT_DATA_UINT64 }, 620 { "lock", KSTAT_DATA_UINT64 }, 621 { "lockt", KSTAT_DATA_UINT64 }, 622 { "locku", KSTAT_DATA_UINT64 }, 623 { "lookup", KSTAT_DATA_UINT64 }, 624 { "lookupp", KSTAT_DATA_UINT64 }, 625 { "nverify", KSTAT_DATA_UINT64 }, 626 { "open", KSTAT_DATA_UINT64 }, 627 { "openattr", KSTAT_DATA_UINT64 }, 628 { "open_confirm", KSTAT_DATA_UINT64 }, 629 { "open_downgrade", KSTAT_DATA_UINT64 }, 630 { "putfh", KSTAT_DATA_UINT64 }, 631 { "putpubfh", KSTAT_DATA_UINT64 }, 632 { "putrootfh", KSTAT_DATA_UINT64 }, 633 { "read", KSTAT_DATA_UINT64 }, 634 { "readdir", KSTAT_DATA_UINT64 }, 635 { "readlink", KSTAT_DATA_UINT64 }, 636 { "remove", KSTAT_DATA_UINT64 }, 637 { "rename", KSTAT_DATA_UINT64 }, 638 { "renew", KSTAT_DATA_UINT64 }, 639 { "restorefh", KSTAT_DATA_UINT64 }, 640 { "savefh", KSTAT_DATA_UINT64 }, 641 { "secinfo", KSTAT_DATA_UINT64 }, 642 { "setattr", KSTAT_DATA_UINT64 }, 643 { "setclientid", KSTAT_DATA_UINT64 }, 644 { "setclientid_confirm", KSTAT_DATA_UINT64 }, 645 { "verify", KSTAT_DATA_UINT64 }, 646 { "write", KSTAT_DATA_UINT64 }, 647 { "release_lockowner", KSTAT_DATA_UINT64 }, 648 { "illegal", KSTAT_DATA_UINT64 }, 649 }; 650 651 #define RFSPROCCNT_V4_COUNT \ 652 (sizeof (rfsproccnt_v4_tmpl) / sizeof (rfsproccnt_v4_tmpl[0])) 653 654 kstat_named_t *rfsproccnt_v4_ptr; 655 kstat_t **rfsprocio_v4_ptr; 656 657 static void 658 nfsstat_zone_init_rfsproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp) 659 { 660 statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0, 661 "rfsproccnt_v4", rfsproccnt_v4_tmpl, sizeof (rfsproccnt_v4_tmpl)); 662 663 mutex_init(&statsp->rfsprocio_lock, NULL, MUTEX_DEFAULT, NULL); 664 665 statsp->rfsprocio_ptr = rfs_kstat_io_init(zoneid, "nfs", 0, 666 "rfsprocio_v4", "rfsprocio_v4", rfsproccnt_v4_tmpl, 667 RFSPROCCNT_V4_COUNT, &statsp->rfsprocio_lock); 668 669 if (zoneid == GLOBAL_ZONEID) { 670 rfsproccnt_v4_ptr = statsp->rfsproccnt_ptr; 671 rfsprocio_v4_ptr = statsp->rfsprocio_ptr; 672 } 673 } 674 675 static void 676 nfsstat_zone_fini_rfsproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp) 677 { 678 if (zoneid == GLOBAL_ZONEID) { 679 rfsproccnt_v4_ptr = NULL; 680 rfsprocio_v4_ptr = NULL; 681 } 682 683 nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v4"); 684 kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v4_tmpl)); 685 686 rfs_kstat_io_free(statsp->rfsprocio_ptr, RFSPROCCNT_V4_COUNT); 687 688 mutex_destroy(&statsp->rfsprocio_lock); 689 } 690 691 /* 692 * NFSv4 client ACL stats 693 */ 694 static const kstat_named_t aclreqcnt_v4_tmpl[] = { 695 { "null", KSTAT_DATA_UINT64 }, 696 { "getacl", KSTAT_DATA_UINT64 }, 697 { "setacl", KSTAT_DATA_UINT64 }, 698 }; 699 700 static void 701 nfsstat_zone_init_aclreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp) 702 { 703 statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0, 704 "aclreqcnt_v4", aclreqcnt_v4_tmpl, sizeof (aclreqcnt_v4_tmpl)); 705 } 706 707 static void 708 nfsstat_zone_fini_aclreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp) 709 { 710 nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclreqcnt_v4"); 711 kmem_free(statsp->aclreqcnt_ptr, sizeof (aclreqcnt_v4_tmpl)); 712 } 713 714 /* 715 * NFSv4 server ACL stats 716 */ 717 static const kstat_named_t aclproccnt_v4_tmpl[] = { 718 { "null", KSTAT_DATA_UINT64 }, 719 { "getacl", KSTAT_DATA_UINT64 }, 720 { "setacl", KSTAT_DATA_UINT64 } 721 }; 722 723 kstat_named_t *aclproccnt_v4_ptr; 724 725 static void 726 nfsstat_zone_init_aclproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp) 727 { 728 kstat_named_t *ks_data; 729 730 ks_data = nfsstat_zone_init_common(zoneid, "nfs_acl", 0, 731 "aclproccnt_v4", aclproccnt_v4_tmpl, 732 sizeof (aclproccnt_v4_tmpl)); 733 statsp->aclproccnt_ptr = ks_data; 734 if (zoneid == GLOBAL_ZONEID) 735 aclproccnt_v4_ptr = ks_data; 736 } 737 738 static void 739 nfsstat_zone_fini_aclproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp) 740 { 741 if (zoneid == GLOBAL_ZONEID) 742 aclproccnt_v4_ptr = NULL; 743 nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v4"); 744 kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v4_tmpl)); 745 } 746 747 /* 748 * Zone initializer callback to setup the kstats. 749 */ 750 void * 751 nfsstat_zone_init(zoneid_t zoneid) 752 { 753 struct nfs_stats *nfs_stats_ptr; 754 755 nfs_stats_ptr = kmem_zalloc(sizeof (*nfs_stats_ptr), KM_SLEEP); 756 757 /* 758 * Initialize all versions of the nfs_server 759 */ 760 nfsstat_zone_init_server(zoneid, nfs_stats_ptr->nfs_stats_svstat_ptr); 761 762 /* 763 * Initialize v2 stats 764 */ 765 nfsstat_zone_init_rfsreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2); 766 nfsstat_zone_init_rfsproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2); 767 nfsstat_zone_init_aclreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2); 768 nfsstat_zone_init_aclproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2); 769 /* 770 * Initialize v3 stats 771 */ 772 nfsstat_zone_init_rfsreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3); 773 nfsstat_zone_init_rfsproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3); 774 nfsstat_zone_init_aclreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3); 775 nfsstat_zone_init_aclproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3); 776 /* 777 * Initialize v4 stats 778 */ 779 nfsstat_zone_init_rfsreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4); 780 nfsstat_zone_init_rfsproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4); 781 nfsstat_zone_init_aclreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4); 782 nfsstat_zone_init_aclproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4); 783 784 return (nfs_stats_ptr); 785 } 786 787 /* 788 * Zone destructor callback to tear down the various kstats. 789 */ 790 void 791 nfsstat_zone_fini(zoneid_t zoneid, void *data) 792 { 793 struct nfs_stats *nfs_stats_ptr = data; 794 795 /* 796 * Free nfs:0:nfs_server stats 797 */ 798 nfsstat_zone_fini_server(zoneid, nfs_stats_ptr->nfs_stats_svstat_ptr); 799 800 /* 801 * Free v2 stats 802 */ 803 nfsstat_zone_fini_rfsreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2); 804 nfsstat_zone_fini_rfsproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2); 805 nfsstat_zone_fini_aclreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2); 806 nfsstat_zone_fini_aclproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2); 807 /* 808 * Free v3 stats 809 */ 810 nfsstat_zone_fini_rfsreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3); 811 nfsstat_zone_fini_rfsproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3); 812 nfsstat_zone_fini_aclreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3); 813 nfsstat_zone_fini_aclproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3); 814 /* 815 * Free v4 stats 816 */ 817 nfsstat_zone_fini_rfsreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4); 818 nfsstat_zone_fini_rfsproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4); 819 nfsstat_zone_fini_aclreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4); 820 nfsstat_zone_fini_aclproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4); 821 822 kmem_free(nfs_stats_ptr, sizeof (*nfs_stats_ptr)); 823 } 824 825 /* 826 * Support for exp_kstats initialization and tear down 827 */ 828 struct exp_kstats * 829 exp_kstats_init(zoneid_t zoneid, int instance, const char *path, size_t len, 830 bool_t pseudo) 831 { 832 struct exp_kstats *exp_kstats; 833 834 exp_kstats = kmem_alloc(sizeof (*exp_kstats), KM_SLEEP); 835 836 mutex_init(&exp_kstats->procio_lock, NULL, MUTEX_DEFAULT, NULL); 837 838 /* 839 * Generic share kstat. 840 */ 841 exp_kstats->share_kstat = kstat_create_zone("nfs", instance, "share", 842 "misc", KSTAT_TYPE_NAMED, 843 sizeof (exp_kstats->share_kstat_data) / sizeof (kstat_named_t), 844 KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_VAR_SIZE, zoneid); 845 if (exp_kstats->share_kstat != NULL) { 846 len = strnlen(path, len); 847 exp_kstats->share_path = kmem_alloc(len + 1, KM_SLEEP); 848 bcopy(path, exp_kstats->share_path, len); 849 exp_kstats->share_path[len] = '\0'; 850 851 exp_kstats->share_kstat->ks_data = 852 &exp_kstats->share_kstat_data; 853 854 kstat_named_init(&exp_kstats->share_kstat_data.path, "path", 855 KSTAT_DATA_STRING); 856 kstat_named_setstr(&exp_kstats->share_kstat_data.path, 857 exp_kstats->share_path); 858 859 kstat_named_init(&exp_kstats->share_kstat_data.filesystem, 860 "filesystem", KSTAT_DATA_STRING); 861 kstat_named_setstr(&exp_kstats->share_kstat_data.filesystem, 862 pseudo ? "pseudo" : "real"); 863 864 exp_kstats->share_kstat->ks_lock = &exp_kstats->procio_lock; 865 kstat_install(exp_kstats->share_kstat); 866 } 867 868 /* 869 * NFS_ACL version 2 870 */ 871 exp_kstats->aclprocio_v2_ptr = rfs_kstat_io_init(zoneid, "nfs_acl", 872 instance, "share_v2", "aclprocio_v2", aclproccnt_v2_tmpl, 873 ACLPROCCNT_V2_COUNT, &exp_kstats->procio_lock); 874 875 /* 876 * NFS_ACL version 3 877 */ 878 exp_kstats->aclprocio_v3_ptr = rfs_kstat_io_init(zoneid, "nfs_acl", 879 instance, "share_v3", "aclprocio_v3", aclproccnt_v3_tmpl, 880 ACLPROCCNT_V3_COUNT, &exp_kstats->procio_lock); 881 882 /* 883 * NFS version 2 884 */ 885 exp_kstats->rfsprocio_v2_ptr = rfs_kstat_io_init(zoneid, "nfs", 886 instance, "share_v2", "rfsprocio_v2", rfsproccnt_v2_tmpl, 887 RFSPROCCNT_V2_COUNT, &exp_kstats->procio_lock); 888 889 /* 890 * NFS version 3 891 */ 892 exp_kstats->rfsprocio_v3_ptr = rfs_kstat_io_init(zoneid, "nfs", 893 instance, "share_v3", "rfsprocio_v3", rfsproccnt_v3_tmpl, 894 RFSPROCCNT_V3_COUNT, &exp_kstats->procio_lock); 895 896 /* 897 * NFS version 4 898 */ 899 exp_kstats->rfsprocio_v4_ptr = rfs_kstat_io_init(zoneid, "nfs", 900 instance, "share_v4", "rfsprocio_v4", rfsproccnt_v4_tmpl, 901 RFSPROCCNT_V4_COUNT, &exp_kstats->procio_lock); 902 903 return (exp_kstats); 904 } 905 906 void 907 exp_kstats_delete(struct exp_kstats *exp_kstats) 908 { 909 if (exp_kstats == NULL) 910 return; 911 912 /* 913 * Generic share kstat 914 */ 915 if (exp_kstats->share_kstat != NULL) { 916 kstat_delete(exp_kstats->share_kstat); 917 exp_kstats->share_kstat = NULL; 918 strfree(exp_kstats->share_path); 919 } 920 921 /* 922 * NFS_ACL kstats 923 */ 924 rfs_kstat_io_delete(exp_kstats->aclprocio_v2_ptr, ACLPROCCNT_V2_COUNT); 925 rfs_kstat_io_delete(exp_kstats->aclprocio_v3_ptr, ACLPROCCNT_V3_COUNT); 926 927 /* 928 * NFS kstats 929 */ 930 rfs_kstat_io_delete(exp_kstats->rfsprocio_v2_ptr, RFSPROCCNT_V2_COUNT); 931 rfs_kstat_io_delete(exp_kstats->rfsprocio_v3_ptr, RFSPROCCNT_V3_COUNT); 932 rfs_kstat_io_delete(exp_kstats->rfsprocio_v4_ptr, RFSPROCCNT_V4_COUNT); 933 } 934 935 void 936 exp_kstats_fini(struct exp_kstats *exp_kstats) 937 { 938 if (exp_kstats == NULL) 939 return; 940 941 /* 942 * Generic share kstat 943 */ 944 if (exp_kstats->share_kstat != NULL) { 945 kstat_delete(exp_kstats->share_kstat); 946 strfree(exp_kstats->share_path); 947 } 948 949 /* 950 * NFS_ACL kstats 951 */ 952 rfs_kstat_io_free(exp_kstats->aclprocio_v2_ptr, ACLPROCCNT_V2_COUNT); 953 rfs_kstat_io_free(exp_kstats->aclprocio_v3_ptr, ACLPROCCNT_V3_COUNT); 954 955 /* 956 * NFS kstats 957 */ 958 rfs_kstat_io_free(exp_kstats->rfsprocio_v2_ptr, RFSPROCCNT_V2_COUNT); 959 rfs_kstat_io_free(exp_kstats->rfsprocio_v3_ptr, RFSPROCCNT_V3_COUNT); 960 rfs_kstat_io_free(exp_kstats->rfsprocio_v4_ptr, RFSPROCCNT_V4_COUNT); 961 962 mutex_destroy(&exp_kstats->procio_lock); 963 964 kmem_free(exp_kstats, sizeof (*exp_kstats)); 965 } 966 967 void 968 exp_kstats_reset(struct exp_kstats *exp_kstats, const char *path, size_t len, 969 bool_t pseudo) 970 { 971 char *old; 972 char *new; 973 974 if (exp_kstats->share_kstat == NULL) 975 return; 976 977 len = strnlen(path, len); 978 new = kmem_alloc(len + 1, KM_SLEEP); 979 bcopy(path, new, len); 980 new[len] = '\0'; 981 982 mutex_enter(exp_kstats->share_kstat->ks_lock); 983 old = exp_kstats->share_path; 984 exp_kstats->share_path = new; 985 kstat_named_setstr(&exp_kstats->share_kstat_data.path, 986 exp_kstats->share_path); 987 kstat_named_setstr(&exp_kstats->share_kstat_data.filesystem, 988 pseudo ? "pseudo" : "real"); 989 mutex_exit(exp_kstats->share_kstat->ks_lock); 990 991 strfree(old); 992 } 993