Print this page
NEX-16731 Panic in exp_kstats_reset() if exp_kstats is NULL
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-16917 Need to reduce the impact of NFS per-share kstats on failover
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-6778 NFS kstats leak and cause system to hang
Revert "NEX-4261 Per-client NFS server IOPS, bandwidth, and latency kstats"
This reverts commit 586c3ab1927647487f01c337ddc011c642575a52.
Revert "NEX-5354 Aggregated IOPS, bandwidth, and latency kstats for NFS server"
This reverts commit c91d7614da8618ef48018102b077f60ecbbac8c2.
Revert "NEX-5667 nfssrv_stats_flags does not work for aggregated kstats"
This reverts commit 3dcf42618be7dd5f408c327f429c81e07ca08e74.
Revert "NEX-5750 Time values for aggregated NFS server kstats should be normalized"
This reverts commit 1f4d4f901153b0191027969fa4a8064f9d3b9ee1.
Revert "NEX-5942 Panic in rfs4_minorvers_mismatch() with NFSv4.1 client"
This reverts commit 40766417094a162f5e4cc8786c0fa0a7e5871cd9.
Revert "NEX-5752 NFS server: namespace collision in kstats"
This reverts commit ae81e668db86050da8e483264acb0cce0444a132.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-4261 Per-client NFS server IOPS, bandwidth, and latency kstats
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-3097 IOPS, bandwidth, and latency kstats for NFS server
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
   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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/kstat.h>
  28 #include <sys/zone.h>
  29 #include <sys/kmem.h>
  30 #include <sys/systm.h>
  31 
  32 #include <nfs/nfs.h>
  33 #include <nfs/nfs4_kprot.h>
  34 
  35 /*
  36  * Key to retrieve per-zone data corresponding to NFS kstats consumed by
  37  * nfsstat(1m).
  38  */
  39 zone_key_t nfsstat_zone_key;
  40 
  41 /*
  42  * Convenience routine to create a named kstat associated with zoneid, named
  43  * module:0:name:"misc", using the provided template to initialize the names
  44  * and values of the stats.
  45  */
  46 static kstat_named_t *
  47 nfsstat_zone_init_common(zoneid_t zoneid, const char *module, int vers,
  48                             const char *name, const kstat_named_t *template,
  49                             size_t template_size)
  50 {
  51         kstat_t *ksp;
  52         kstat_named_t *ks_data;
  53 
  54         ks_data = kmem_alloc(template_size, KM_SLEEP);
  55         bcopy(template, ks_data, template_size);
  56         if ((ksp = kstat_create_zone(module, vers, name, "misc",
  57             KSTAT_TYPE_NAMED, template_size / sizeof (kstat_named_t),
  58             KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, zoneid)) != NULL) {
  59                 ksp->ks_data = ks_data;
  60                 kstat_install(ksp);
  61         }
  62         return (ks_data);
  63 }
  64 
  65 /*
  66  * Convenience routine to remove a kstat in specified zone with name
  67  * module:0:name.
  68  */
  69 static void


 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 },


 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 },


 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 },


 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)


 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);


 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 }
   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 2018 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, size_t template_size)

  54 {
  55         kstat_t *ksp;
  56         kstat_named_t *ks_data;
  57 
  58         ks_data = kmem_alloc(template_size, KM_SLEEP);
  59         bcopy(template, ks_data, template_size);
  60         if ((ksp = kstat_create_zone(module, vers, name, "misc",
  61             KSTAT_TYPE_NAMED, template_size / sizeof (kstat_named_t),
  62             KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, zoneid)) != NULL) {
  63                 ksp->ks_data = ks_data;
  64                 kstat_install(ksp);
  65         }
  66         return (ks_data);
  67 }
  68 
  69 /*
  70  * Convenience routine to remove a kstat in specified zone with name
  71  * module:0:name.
  72  */
  73 static void


 114                 svstatp[vers] = nfsstat_zone_init_common(zoneid, "nfs", vers,
 115                     "nfs_server", svstat_tmpl, sizeof (svstat_tmpl));
 116                 if (zoneid == GLOBAL_ZONEID)
 117                         global_svstat_ptr[vers] = svstatp[vers];
 118         }
 119 }
 120 
 121 static void
 122 nfsstat_zone_fini_server(zoneid_t zoneid, kstat_named_t **svstatp)
 123 {
 124         int vers;
 125         for (vers = NFS_VERSION; vers <= NFS_V4; vers++) {
 126                 if (zoneid == GLOBAL_ZONEID)
 127                         global_svstat_ptr[vers] = NULL;
 128                 nfsstat_zone_fini_common(zoneid, "nfs", vers, "nfs_server");
 129                 kmem_free(svstatp[vers], sizeof (svstat_tmpl));
 130         }
 131 }
 132 
 133 /*
 134  * Support functions for the kstat_io alloc/free
 135  */
 136 static kstat_t **
 137 rfs_kstat_io_init(zoneid_t zoneid, const char *module, int instance,
 138     const char *name, const char *class, const kstat_named_t *tmpl, int count,
 139     kmutex_t *lock)
 140 {
 141         int i;
 142         kstat_t **ret = kmem_alloc(count * sizeof (*ret), KM_SLEEP);
 143 
 144         for (i = 0; i < count; i++) {
 145                 char namebuf[KSTAT_STRLEN];
 146 
 147                 (void) snprintf(namebuf, sizeof (namebuf), "%s_%s", name,
 148                     tmpl[i].name);
 149                 ret[i] = kstat_create_zone(module, instance, namebuf, class,
 150                     KSTAT_TYPE_IO, 1, 0, zoneid);
 151                 if (ret[i] != NULL) {
 152                         ret[i]->ks_lock = lock;
 153                         kstat_install(ret[i]);
 154                 }
 155         }
 156 
 157         return (ret);
 158 }
 159 
 160 static void
 161 rfs_kstat_io_delete(kstat_t **ks, int count)
 162 {
 163         int i;
 164 
 165         for (i = 0; i < count; i++) {
 166                 if (ks[i] != NULL) {
 167                         kstat_delete(ks[i]);
 168                         ks[i] = NULL;
 169                 }
 170         }
 171 }
 172 
 173 static void
 174 rfs_kstat_io_free(kstat_t **ks, int count)
 175 {
 176         rfs_kstat_io_delete(ks, count);
 177         kmem_free(ks, count * sizeof (*ks));
 178 }
 179 
 180 /*
 181  * NFSv2 client stats
 182  */
 183 static const kstat_named_t rfsreqcnt_v2_tmpl[] = {
 184         { "null",       KSTAT_DATA_UINT64 },
 185         { "getattr",    KSTAT_DATA_UINT64 },
 186         { "setattr",    KSTAT_DATA_UINT64 },
 187         { "root",       KSTAT_DATA_UINT64 },
 188         { "lookup",     KSTAT_DATA_UINT64 },
 189         { "readlink",   KSTAT_DATA_UINT64 },
 190         { "read",       KSTAT_DATA_UINT64 },
 191         { "wrcache",    KSTAT_DATA_UINT64 },
 192         { "write",      KSTAT_DATA_UINT64 },
 193         { "create",     KSTAT_DATA_UINT64 },
 194         { "remove",     KSTAT_DATA_UINT64 },
 195         { "rename",     KSTAT_DATA_UINT64 },
 196         { "link",       KSTAT_DATA_UINT64 },
 197         { "symlink",    KSTAT_DATA_UINT64 },
 198         { "mkdir",      KSTAT_DATA_UINT64 },
 199         { "rmdir",      KSTAT_DATA_UINT64 },
 200         { "readdir",    KSTAT_DATA_UINT64 },


 222         { "null",       KSTAT_DATA_UINT64 },
 223         { "getattr",    KSTAT_DATA_UINT64 },
 224         { "setattr",    KSTAT_DATA_UINT64 },
 225         { "root",       KSTAT_DATA_UINT64 },
 226         { "lookup",     KSTAT_DATA_UINT64 },
 227         { "readlink",   KSTAT_DATA_UINT64 },
 228         { "read",       KSTAT_DATA_UINT64 },
 229         { "wrcache",    KSTAT_DATA_UINT64 },
 230         { "write",      KSTAT_DATA_UINT64 },
 231         { "create",     KSTAT_DATA_UINT64 },
 232         { "remove",     KSTAT_DATA_UINT64 },
 233         { "rename",     KSTAT_DATA_UINT64 },
 234         { "link",       KSTAT_DATA_UINT64 },
 235         { "symlink",    KSTAT_DATA_UINT64 },
 236         { "mkdir",      KSTAT_DATA_UINT64 },
 237         { "rmdir",      KSTAT_DATA_UINT64 },
 238         { "readdir",    KSTAT_DATA_UINT64 },
 239         { "statfs",     KSTAT_DATA_UINT64 }
 240 };
 241 
 242 #define RFSPROCCNT_V2_COUNT     \
 243         (sizeof (rfsproccnt_v2_tmpl) / sizeof (rfsproccnt_v2_tmpl[0]))
 244 
 245 kstat_named_t *rfsproccnt_v2_ptr;
 246 kstat_t **rfsprocio_v2_ptr;
 247 
 248 static void
 249 nfsstat_zone_init_rfsproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 250 {
 251         statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
 252             "rfsproccnt_v2", rfsproccnt_v2_tmpl, sizeof (rfsproccnt_v2_tmpl));
 253 
 254         mutex_init(&statsp->rfsprocio_lock, NULL, MUTEX_DEFAULT, NULL);
 255 
 256         statsp->rfsprocio_ptr = rfs_kstat_io_init(zoneid, "nfs", 0,
 257             "rfsprocio_v2", "rfsprocio_v2", rfsproccnt_v2_tmpl,
 258             RFSPROCCNT_V2_COUNT, &statsp->rfsprocio_lock);
 259 
 260         if (zoneid == GLOBAL_ZONEID) {
 261                 rfsproccnt_v2_ptr = statsp->rfsproccnt_ptr;
 262                 rfsprocio_v2_ptr = statsp->rfsprocio_ptr;
 263         }
 264 }
 265 
 266 static void
 267 nfsstat_zone_fini_rfsproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 268 {
 269         if (zoneid == GLOBAL_ZONEID) {
 270                 rfsproccnt_v2_ptr = NULL;
 271                 rfsprocio_v2_ptr = NULL;
 272         }
 273 
 274         nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v2");
 275         kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v2_tmpl));
 276 
 277         rfs_kstat_io_free(statsp->rfsprocio_ptr, RFSPROCCNT_V2_COUNT);
 278 
 279         mutex_destroy(&statsp->rfsprocio_lock);
 280 }
 281 
 282 /*
 283  * NFSv2 client ACL stats
 284  */
 285 static const kstat_named_t aclreqcnt_v2_tmpl[] = {
 286         { "null",       KSTAT_DATA_UINT64 },
 287         { "getacl",     KSTAT_DATA_UINT64 },
 288         { "setacl",     KSTAT_DATA_UINT64 },
 289         { "getattr",    KSTAT_DATA_UINT64 },
 290         { "access",     KSTAT_DATA_UINT64 },
 291         { "getxattrdir",        KSTAT_DATA_UINT64 }
 292 };
 293 
 294 static void
 295 nfsstat_zone_init_aclreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 296 {
 297         statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
 298             "aclreqcnt_v2", aclreqcnt_v2_tmpl, sizeof (aclreqcnt_v2_tmpl));
 299 }
 300 
 301 static void
 302 nfsstat_zone_fini_aclreq_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 303 {
 304         nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclreqcnt_v2");
 305         kmem_free(statsp->aclreqcnt_ptr, sizeof (aclreqcnt_v2_tmpl));
 306 }
 307 
 308 /*
 309  * NFSv2 server ACL stats
 310  */
 311 static const kstat_named_t aclproccnt_v2_tmpl[] = {
 312         { "null",       KSTAT_DATA_UINT64 },
 313         { "getacl",     KSTAT_DATA_UINT64 },
 314         { "setacl",     KSTAT_DATA_UINT64 },
 315         { "getattr",    KSTAT_DATA_UINT64 },
 316         { "access",     KSTAT_DATA_UINT64 },
 317         { "getxattrdir",        KSTAT_DATA_UINT64 }
 318 };
 319 
 320 #define ACLPROCCNT_V2_COUNT     \
 321         (sizeof (aclproccnt_v2_tmpl) / sizeof (aclproccnt_v2_tmpl[0]))
 322 
 323 kstat_named_t *aclproccnt_v2_ptr;
 324 kstat_t **aclprocio_v2_ptr;
 325 
 326 static void
 327 nfsstat_zone_init_aclproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 328 {
 329         statsp->aclproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
 330             "aclproccnt_v2", aclproccnt_v2_tmpl, sizeof (aclproccnt_v2_tmpl));
 331 
 332         mutex_init(&statsp->aclprocio_lock, NULL, MUTEX_DEFAULT, NULL);
 333 
 334         statsp->aclprocio_ptr = rfs_kstat_io_init(zoneid, "nfs_acl", 0,
 335             "aclprocio_v2", "aclprocio_v2", aclproccnt_v2_tmpl,
 336             ACLPROCCNT_V2_COUNT, &statsp->aclprocio_lock);
 337 
 338         if (zoneid == GLOBAL_ZONEID) {
 339                 aclproccnt_v2_ptr = statsp->aclproccnt_ptr;
 340                 aclprocio_v2_ptr = statsp->aclprocio_ptr;
 341         }
 342 }
 343 
 344 static void
 345 nfsstat_zone_fini_aclproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 346 {
 347         if (zoneid == GLOBAL_ZONEID) {
 348                 aclproccnt_v2_ptr = NULL;
 349                 aclprocio_v2_ptr = NULL;
 350         }
 351 
 352         nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v2");
 353         kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v2_tmpl));
 354 
 355         rfs_kstat_io_free(statsp->aclprocio_ptr, ACLPROCCNT_V2_COUNT);
 356 
 357         mutex_destroy(&statsp->aclprocio_lock);
 358 }
 359 
 360 /*
 361  * NFSv3 client stats
 362  */
 363 static const kstat_named_t rfsreqcnt_v3_tmpl[] = {
 364         { "null",       KSTAT_DATA_UINT64 },
 365         { "getattr",    KSTAT_DATA_UINT64 },
 366         { "setattr",    KSTAT_DATA_UINT64 },
 367         { "lookup",     KSTAT_DATA_UINT64 },
 368         { "access",     KSTAT_DATA_UINT64 },
 369         { "readlink",   KSTAT_DATA_UINT64 },
 370         { "read",       KSTAT_DATA_UINT64 },
 371         { "write",      KSTAT_DATA_UINT64 },
 372         { "create",     KSTAT_DATA_UINT64 },
 373         { "mkdir",      KSTAT_DATA_UINT64 },
 374         { "symlink",    KSTAT_DATA_UINT64 },
 375         { "mknod",      KSTAT_DATA_UINT64 },
 376         { "remove",     KSTAT_DATA_UINT64 },
 377         { "rmdir",      KSTAT_DATA_UINT64 },


 410         { "access",     KSTAT_DATA_UINT64 },
 411         { "readlink",   KSTAT_DATA_UINT64 },
 412         { "read",       KSTAT_DATA_UINT64 },
 413         { "write",      KSTAT_DATA_UINT64 },
 414         { "create",     KSTAT_DATA_UINT64 },
 415         { "mkdir",      KSTAT_DATA_UINT64 },
 416         { "symlink",    KSTAT_DATA_UINT64 },
 417         { "mknod",      KSTAT_DATA_UINT64 },
 418         { "remove",     KSTAT_DATA_UINT64 },
 419         { "rmdir",      KSTAT_DATA_UINT64 },
 420         { "rename",     KSTAT_DATA_UINT64 },
 421         { "link",       KSTAT_DATA_UINT64 },
 422         { "readdir",    KSTAT_DATA_UINT64 },
 423         { "readdirplus", KSTAT_DATA_UINT64 },
 424         { "fsstat",     KSTAT_DATA_UINT64 },
 425         { "fsinfo",     KSTAT_DATA_UINT64 },
 426         { "pathconf",   KSTAT_DATA_UINT64 },
 427         { "commit",     KSTAT_DATA_UINT64 }
 428 };
 429 
 430 #define RFSPROCCNT_V3_COUNT     \
 431         (sizeof (rfsproccnt_v3_tmpl) / sizeof (rfsproccnt_v3_tmpl[0]))
 432 
 433 kstat_named_t *rfsproccnt_v3_ptr;
 434 kstat_t **rfsprocio_v3_ptr;
 435 
 436 static void
 437 nfsstat_zone_init_rfsproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 438 {
 439         statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
 440             "rfsproccnt_v3", rfsproccnt_v3_tmpl, sizeof (rfsproccnt_v3_tmpl));
 441 
 442         mutex_init(&statsp->rfsprocio_lock, NULL, MUTEX_DEFAULT, NULL);
 443 
 444         statsp->rfsprocio_ptr = rfs_kstat_io_init(zoneid, "nfs", 0,
 445             "rfsprocio_v3", "rfsprocio_v3", rfsproccnt_v3_tmpl,
 446             RFSPROCCNT_V3_COUNT, &statsp->rfsprocio_lock);
 447 
 448         if (zoneid == GLOBAL_ZONEID) {
 449                 rfsproccnt_v3_ptr = statsp->rfsproccnt_ptr;
 450                 rfsprocio_v3_ptr = statsp->rfsprocio_ptr;
 451         }
 452 }
 453 
 454 static void
 455 nfsstat_zone_fini_rfsproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 456 {
 457         if (zoneid == GLOBAL_ZONEID) {
 458                 rfsproccnt_v3_ptr = NULL;
 459                 rfsprocio_v3_ptr = NULL;
 460         }
 461 
 462         nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v3");
 463         kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v3_tmpl));
 464 
 465         rfs_kstat_io_free(statsp->rfsprocio_ptr, RFSPROCCNT_V3_COUNT);
 466 
 467         mutex_destroy(&statsp->rfsprocio_lock);
 468 }
 469 
 470 /*
 471  * NFSv3 client ACL stats
 472  */
 473 static const kstat_named_t aclreqcnt_v3_tmpl[] = {
 474         { "null",       KSTAT_DATA_UINT64 },
 475         { "getacl",     KSTAT_DATA_UINT64 },
 476         { "setacl",     KSTAT_DATA_UINT64 },
 477         { "getxattrdir",        KSTAT_DATA_UINT64 }
 478 };
 479 
 480 static void
 481 nfsstat_zone_init_aclreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 482 {
 483         statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
 484             "aclreqcnt_v3", aclreqcnt_v3_tmpl, sizeof (aclreqcnt_v3_tmpl));
 485 }
 486 
 487 static void
 488 nfsstat_zone_fini_aclreq_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 489 {
 490         nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclreqcnt_v3");
 491         kmem_free(statsp->aclreqcnt_ptr, sizeof (aclreqcnt_v3_tmpl));
 492 }
 493 
 494 /*
 495  * NFSv3 server ACL stats
 496  */
 497 static const kstat_named_t aclproccnt_v3_tmpl[] = {
 498         { "null",       KSTAT_DATA_UINT64 },
 499         { "getacl",     KSTAT_DATA_UINT64 },
 500         { "setacl",     KSTAT_DATA_UINT64 },
 501         { "getxattrdir",        KSTAT_DATA_UINT64 }
 502 };
 503 
 504 #define ACLPROCCNT_V3_COUNT     \
 505         (sizeof (aclproccnt_v3_tmpl) / sizeof (aclproccnt_v3_tmpl[0]))
 506 
 507 kstat_named_t *aclproccnt_v3_ptr;
 508 kstat_t **aclprocio_v3_ptr;
 509 
 510 static void
 511 nfsstat_zone_init_aclproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 512 {
 513         statsp->aclproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
 514             "aclproccnt_v3", aclproccnt_v3_tmpl, sizeof (aclproccnt_v3_tmpl));
 515 
 516         mutex_init(&statsp->aclprocio_lock, NULL, MUTEX_DEFAULT, NULL);
 517 
 518         statsp->aclprocio_ptr = rfs_kstat_io_init(zoneid, "nfs_acl", 0,
 519             "aclprocio_v3", "aclprocio_v3", aclproccnt_v3_tmpl,
 520             ACLPROCCNT_V3_COUNT, &statsp->aclprocio_lock);
 521 
 522         if (zoneid == GLOBAL_ZONEID) {
 523                 aclproccnt_v3_ptr = statsp->aclproccnt_ptr;
 524                 aclprocio_v3_ptr = statsp->aclprocio_ptr;
 525         }
 526 }
 527 
 528 static void
 529 nfsstat_zone_fini_aclproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 530 {
 531         if (zoneid == GLOBAL_ZONEID) {
 532                 aclproccnt_v3_ptr = NULL;
 533                 aclprocio_v3_ptr = NULL;
 534         }
 535 
 536         nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v3");
 537         kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v3_tmpl));
 538 
 539         rfs_kstat_io_free(statsp->aclprocio_ptr, ACLPROCCNT_V3_COUNT);
 540 
 541         mutex_destroy(&statsp->aclprocio_lock);
 542 }
 543 
 544 /*
 545  * NFSv4 client stats
 546  */
 547 static const kstat_named_t rfsreqcnt_v4_tmpl[] = {
 548         { "null",       KSTAT_DATA_UINT64 },
 549         { "compound",   KSTAT_DATA_UINT64 },
 550         { "reserved",   KSTAT_DATA_UINT64 },
 551         { "access",     KSTAT_DATA_UINT64 },
 552         { "close",      KSTAT_DATA_UINT64 },
 553         { "commit",     KSTAT_DATA_UINT64 },
 554         { "create",     KSTAT_DATA_UINT64 },
 555         { "delegpurge", KSTAT_DATA_UINT64 },
 556         { "delegreturn",        KSTAT_DATA_UINT64 },
 557         { "getattr",    KSTAT_DATA_UINT64 },
 558         { "getfh",      KSTAT_DATA_UINT64 },
 559         { "link",       KSTAT_DATA_UINT64 },
 560         { "lock",       KSTAT_DATA_UINT64 },
 561         { "lockt",      KSTAT_DATA_UINT64 },


 630         { "putpubfh",   KSTAT_DATA_UINT64 },
 631         { "putrootfh",  KSTAT_DATA_UINT64 },
 632         { "read",       KSTAT_DATA_UINT64 },
 633         { "readdir",    KSTAT_DATA_UINT64 },
 634         { "readlink",   KSTAT_DATA_UINT64 },
 635         { "remove",     KSTAT_DATA_UINT64 },
 636         { "rename",     KSTAT_DATA_UINT64 },
 637         { "renew",      KSTAT_DATA_UINT64 },
 638         { "restorefh",  KSTAT_DATA_UINT64 },
 639         { "savefh",     KSTAT_DATA_UINT64 },
 640         { "secinfo",    KSTAT_DATA_UINT64 },
 641         { "setattr",    KSTAT_DATA_UINT64 },
 642         { "setclientid",        KSTAT_DATA_UINT64 },
 643         { "setclientid_confirm",        KSTAT_DATA_UINT64 },
 644         { "verify",     KSTAT_DATA_UINT64 },
 645         { "write",      KSTAT_DATA_UINT64 },
 646         { "release_lockowner",  KSTAT_DATA_UINT64 },
 647         { "illegal",    KSTAT_DATA_UINT64 },
 648 };
 649 
 650 #define RFSPROCCNT_V4_COUNT     \
 651         (sizeof (rfsproccnt_v4_tmpl) / sizeof (rfsproccnt_v4_tmpl[0]))
 652 
 653 kstat_named_t *rfsproccnt_v4_ptr;
 654 kstat_t **rfsprocio_v4_ptr;
 655 
 656 static void
 657 nfsstat_zone_init_rfsproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
 658 {
 659         statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
 660             "rfsproccnt_v4", rfsproccnt_v4_tmpl, sizeof (rfsproccnt_v4_tmpl));
 661 
 662         mutex_init(&statsp->rfsprocio_lock, NULL, MUTEX_DEFAULT, NULL);
 663 
 664         statsp->rfsprocio_ptr = rfs_kstat_io_init(zoneid, "nfs", 0,
 665             "rfsprocio_v4", "rfsprocio_v4", rfsproccnt_v4_tmpl,
 666             RFSPROCCNT_V4_COUNT, &statsp->rfsprocio_lock);
 667 
 668         if (zoneid == GLOBAL_ZONEID) {
 669                 rfsproccnt_v4_ptr = statsp->rfsproccnt_ptr;
 670                 rfsprocio_v4_ptr = statsp->rfsprocio_ptr;
 671         }
 672 }
 673 
 674 static void
 675 nfsstat_zone_fini_rfsproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
 676 {
 677         if (zoneid == GLOBAL_ZONEID) {
 678                 rfsproccnt_v4_ptr = NULL;
 679                 rfsprocio_v4_ptr = NULL;
 680         }
 681 
 682         nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v4");
 683         kmem_free(statsp->rfsproccnt_ptr, sizeof (rfsproccnt_v4_tmpl));
 684 
 685         rfs_kstat_io_free(statsp->rfsprocio_ptr, RFSPROCCNT_V4_COUNT);
 686 
 687         mutex_destroy(&statsp->rfsprocio_lock);
 688 }
 689 
 690 /*
 691  * NFSv4 client ACL stats
 692  */
 693 static const kstat_named_t aclreqcnt_v4_tmpl[] = {
 694         { "null",       KSTAT_DATA_UINT64 },
 695         { "getacl",     KSTAT_DATA_UINT64 },
 696         { "setacl",     KSTAT_DATA_UINT64 },
 697 };
 698 
 699 static void
 700 nfsstat_zone_init_aclreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
 701 {
 702         statsp->aclreqcnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
 703             "aclreqcnt_v4", aclreqcnt_v4_tmpl, sizeof (aclreqcnt_v4_tmpl));
 704 }
 705 
 706 static void
 707 nfsstat_zone_fini_aclreq_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)


 726 {
 727         kstat_named_t *ks_data;
 728 
 729         ks_data = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
 730             "aclproccnt_v4", aclproccnt_v4_tmpl,
 731             sizeof (aclproccnt_v4_tmpl));
 732         statsp->aclproccnt_ptr = ks_data;
 733         if (zoneid == GLOBAL_ZONEID)
 734                 aclproccnt_v4_ptr = ks_data;
 735 }
 736 
 737 static void
 738 nfsstat_zone_fini_aclproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
 739 {
 740         if (zoneid == GLOBAL_ZONEID)
 741                 aclproccnt_v4_ptr = NULL;
 742         nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v4");
 743         kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v4_tmpl));
 744 }
 745 
 746 
 747 /*
 748  * NFS server per share kstats (exp_kstats)
 749  * kstats are collected per share for NFSv3 & NFSv4 read and write operations.
 750  */
 751 #define NFSSRV_SHR_READ         0
 752 #define NFSSRV_SHR_WRITE        1
 753 
 754 static const kstat_named_t rfsshr_tmpl[] = {
 755         { "read",       KSTAT_DATA_UINT64 },    /* NFSSRV_SHR_READ */
 756         { "write",      KSTAT_DATA_UINT64 }     /* NFSSRV_SHR_WRITE */
 757 };
 758 #define RFSSHARE_COUNT  \
 759         (sizeof (rfsshr_tmpl) / sizeof (rfsshr_tmpl[0]))
 760 
 761 /*
 762  * Zone initializer callback to setup the kstats.
 763  */
 764 void *
 765 nfsstat_zone_init(zoneid_t zoneid)
 766 {
 767         struct nfs_stats *nfs_stats_ptr;
 768 
 769         nfs_stats_ptr = kmem_zalloc(sizeof (*nfs_stats_ptr), KM_SLEEP);
 770 
 771         /*
 772          * Initialize all versions of the nfs_server
 773          */
 774         nfsstat_zone_init_server(zoneid, nfs_stats_ptr->nfs_stats_svstat_ptr);
 775 
 776         /*
 777          * Initialize v2 stats
 778          */
 779         nfsstat_zone_init_rfsreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
 780         nfsstat_zone_init_rfsproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
 781         nfsstat_zone_init_aclreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);


 817         nfsstat_zone_fini_rfsreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
 818         nfsstat_zone_fini_rfsproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
 819         nfsstat_zone_fini_aclreq_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
 820         nfsstat_zone_fini_aclproc_v2(zoneid, &nfs_stats_ptr->nfs_stats_v2);
 821         /*
 822          * Free v3 stats
 823          */
 824         nfsstat_zone_fini_rfsreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
 825         nfsstat_zone_fini_rfsproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
 826         nfsstat_zone_fini_aclreq_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
 827         nfsstat_zone_fini_aclproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
 828         /*
 829          * Free v4 stats
 830          */
 831         nfsstat_zone_fini_rfsreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
 832         nfsstat_zone_fini_rfsproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
 833         nfsstat_zone_fini_aclreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
 834         nfsstat_zone_fini_aclproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
 835 
 836         kmem_free(nfs_stats_ptr, sizeof (*nfs_stats_ptr));
 837 }
 838 
 839 /*
 840  * Support for exp_kstats initialization and tear down
 841  */
 842 struct exp_kstats *
 843 exp_kstats_init(zoneid_t zoneid, int instance, const char *path, size_t len,
 844     bool_t pseudo)
 845 {
 846         struct exp_kstats *exp_kstats;
 847 
 848         exp_kstats = kmem_alloc(sizeof (*exp_kstats), KM_SLEEP);
 849 
 850         mutex_init(&exp_kstats->procio_lock, NULL, MUTEX_DEFAULT, NULL);
 851 
 852         /*
 853          * Generic share kstat.
 854          */
 855         exp_kstats->share_kstat = kstat_create_zone("nfs", instance, "share",
 856             "misc", KSTAT_TYPE_NAMED,
 857             sizeof (exp_kstats->share_kstat_data) / sizeof (kstat_named_t),
 858             KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_VAR_SIZE, zoneid);
 859         if (exp_kstats->share_kstat != NULL) {
 860                 len = strnlen(path, len);
 861                 exp_kstats->share_path = kmem_alloc(len + 1, KM_SLEEP);
 862                 bcopy(path, exp_kstats->share_path, len);
 863                 exp_kstats->share_path[len] = '\0';
 864 
 865                 exp_kstats->share_kstat->ks_data =
 866                     &exp_kstats->share_kstat_data;
 867 
 868                 kstat_named_init(&exp_kstats->share_kstat_data.path, "path",
 869                     KSTAT_DATA_STRING);
 870                 kstat_named_setstr(&exp_kstats->share_kstat_data.path,
 871                     exp_kstats->share_path);
 872 
 873                 kstat_named_init(&exp_kstats->share_kstat_data.filesystem,
 874                     "filesystem", KSTAT_DATA_STRING);
 875                 kstat_named_setstr(&exp_kstats->share_kstat_data.filesystem,
 876                     pseudo ? "pseudo" : "real");
 877 
 878                 exp_kstats->share_kstat->ks_lock = &exp_kstats->procio_lock;
 879                 kstat_install(exp_kstats->share_kstat);
 880         }
 881 
 882         /* NFS version 3 */
 883         exp_kstats->rfsshr_v3_ptr = rfs_kstat_io_init(zoneid, "nfs",
 884             instance, "share_v3", "rfsprocio_v3", rfsshr_tmpl,
 885             RFSSHARE_COUNT, &exp_kstats->procio_lock);
 886 
 887         /* NFS version 4 */
 888         exp_kstats->rfsshr_v4_ptr = rfs_kstat_io_init(zoneid, "nfs",
 889             instance, "share_v4", "rfsprocio_v4", rfsshr_tmpl,
 890             RFSSHARE_COUNT, &exp_kstats->procio_lock);
 891 
 892         return (exp_kstats);
 893 }
 894 
 895 void
 896 exp_kstats_delete(struct exp_kstats *exp_kstats)
 897 {
 898         if (exp_kstats == NULL)
 899                 return;
 900 
 901         /* Generic share kstat */
 902         if (exp_kstats->share_kstat != NULL) {
 903                 kstat_delete(exp_kstats->share_kstat);
 904                 exp_kstats->share_kstat = NULL;
 905                 strfree(exp_kstats->share_path);
 906         }
 907 
 908         rfs_kstat_io_delete(exp_kstats->rfsshr_v3_ptr, RFSSHARE_COUNT);
 909         rfs_kstat_io_delete(exp_kstats->rfsshr_v4_ptr, RFSSHARE_COUNT);
 910 
 911 }
 912 
 913 void
 914 exp_kstats_fini(struct exp_kstats *exp_kstats)
 915 {
 916         if (exp_kstats == NULL)
 917                 return;
 918 
 919         /* Generic share kstat */
 920         if (exp_kstats->share_kstat != NULL) {
 921                 kstat_delete(exp_kstats->share_kstat);
 922                 strfree(exp_kstats->share_path);
 923         }
 924 
 925         rfs_kstat_io_free(exp_kstats->rfsshr_v3_ptr, RFSSHARE_COUNT);
 926         rfs_kstat_io_free(exp_kstats->rfsshr_v4_ptr, RFSSHARE_COUNT);
 927 
 928         mutex_destroy(&exp_kstats->procio_lock);
 929 
 930         kmem_free(exp_kstats, sizeof (*exp_kstats));
 931 }
 932 
 933 void
 934 exp_kstats_reset(struct exp_kstats *exp_kstats, const char *path, size_t len,
 935     bool_t pseudo)
 936 {
 937         char *old;
 938         char *new;
 939 
 940         if ((exp_kstats == NULL) || (exp_kstats->share_kstat == NULL))
 941                 return;
 942 
 943         len = strnlen(path, len);
 944         new = kmem_alloc(len + 1, KM_SLEEP);
 945         bcopy(path, new, len);
 946         new[len] = '\0';
 947 
 948         mutex_enter(exp_kstats->share_kstat->ks_lock);
 949         old = exp_kstats->share_path;
 950         exp_kstats->share_path = new;
 951         kstat_named_setstr(&exp_kstats->share_kstat_data.path,
 952             exp_kstats->share_path);
 953         kstat_named_setstr(&exp_kstats->share_kstat_data.filesystem,
 954             pseudo ? "pseudo" : "real");
 955         mutex_exit(exp_kstats->share_kstat->ks_lock);
 956 
 957         strfree(old);
 958 }
 959 
 960 kstat_t *
 961 /* LINTED E_FUNC_ARG_UNUSED */
 962 exp_kstats_v2(struct exp_kstats *exp_kstats, uint_t op)
 963 {
 964         /* No NFS v2 per-share kstats */
 965         return (NULL);
 966 }
 967 
 968 kstat_t *
 969 exp_kstats_v3(struct exp_kstats *exp_kstats, uint_t op)
 970 {
 971         if (exp_kstats == NULL)
 972                 return (NULL);
 973 
 974         /* per share kstats for selected operations (read, write) only */
 975         switch (op) {
 976         case NFSPROC3_READ:
 977                 return (exp_kstats->rfsshr_v3_ptr[NFSSRV_SHR_READ]);
 978         case NFSPROC3_WRITE:
 979                 return (exp_kstats->rfsshr_v3_ptr[NFSSRV_SHR_WRITE]);
 980         default:
 981                 return (NULL);
 982         }
 983 }
 984 
 985 kstat_t *
 986 exp_kstats_v4(struct exp_kstats *exp_kstats, uint_t op)
 987 {
 988         if (exp_kstats == NULL)
 989                 return (NULL);
 990 
 991         /* per share kstats for selected operations (read, write) only */
 992         switch (op) {
 993         case OP_READ:
 994                 return (exp_kstats->rfsshr_v4_ptr[NFSSRV_SHR_READ]);
 995         case OP_WRITE:
 996                 return (exp_kstats->rfsshr_v4_ptr[NFSSRV_SHR_WRITE]);
 997         default:
 998                 return (NULL);
 999         }
1000 }