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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/nfs/nfs_stats.c
          +++ new/usr/src/uts/common/fs/nfs/nfs_stats.c
↓ open down ↓ 10 lines elided ↑ open up ↑
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
       21 +
  21   22  /*
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
       24 + */
       25 +
       26 +/*
  22   27   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   28   * Use is subject to license terms.
  24   29   */
  25   30  
  26   31  #include <sys/types.h>
  27   32  #include <sys/kstat.h>
  28   33  #include <sys/zone.h>
  29   34  #include <sys/kmem.h>
  30   35  #include <sys/systm.h>
  31   36  
↓ open down ↓ 6 lines elided ↑ open up ↑
  38   43   */
  39   44  zone_key_t nfsstat_zone_key;
  40   45  
  41   46  /*
  42   47   * Convenience routine to create a named kstat associated with zoneid, named
  43   48   * module:0:name:"misc", using the provided template to initialize the names
  44   49   * and values of the stats.
  45   50   */
  46   51  static kstat_named_t *
  47   52  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)
       53 +    const char *name, const kstat_named_t *template, size_t template_size)
  50   54  {
  51   55          kstat_t *ksp;
  52   56          kstat_named_t *ks_data;
  53   57  
  54   58          ks_data = kmem_alloc(template_size, KM_SLEEP);
  55   59          bcopy(template, ks_data, template_size);
  56   60          if ((ksp = kstat_create_zone(module, vers, name, "misc",
  57   61              KSTAT_TYPE_NAMED, template_size / sizeof (kstat_named_t),
  58   62              KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, zoneid)) != NULL) {
  59   63                  ksp->ks_data = ks_data;
↓ open down ↓ 1 lines elided ↑ open up ↑
  61   65          }
  62   66          return (ks_data);
  63   67  }
  64   68  
  65   69  /*
  66   70   * Convenience routine to remove a kstat in specified zone with name
  67   71   * module:0:name.
  68   72   */
  69   73  static void
  70   74  nfsstat_zone_fini_common(zoneid_t zoneid, const char *module, int vers,
  71      -                            const char *name)
       75 +    const char *name)
  72   76  {
  73   77          kstat_delete_byname_zone(module, vers, name, zoneid);
  74   78  }
  75   79  
  76   80  /*
  77   81   * Server statistics.  These are defined here, rather than in the server
  78   82   * code, so that they can be referenced before the nfssrv kmod is loaded.
  79   83   *
  80   84   * The "calls" counter is a Contract Private interface covered by
  81   85   * PSARC/2001/357.  Please contact contract-2001-357-01@eng.sun.com before
↓ open down ↓ 38 lines elided ↑ open up ↑
 120  124          int vers;
 121  125          for (vers = NFS_VERSION; vers <= NFS_V4; vers++) {
 122  126                  if (zoneid == GLOBAL_ZONEID)
 123  127                          global_svstat_ptr[vers] = NULL;
 124  128                  nfsstat_zone_fini_common(zoneid, "nfs", vers, "nfs_server");
 125  129                  kmem_free(svstatp[vers], sizeof (svstat_tmpl));
 126  130          }
 127  131  }
 128  132  
 129  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 +/*
 130  181   * NFSv2 client stats
 131  182   */
 132  183  static const kstat_named_t rfsreqcnt_v2_tmpl[] = {
 133  184          { "null",       KSTAT_DATA_UINT64 },
 134  185          { "getattr",    KSTAT_DATA_UINT64 },
 135  186          { "setattr",    KSTAT_DATA_UINT64 },
 136  187          { "root",       KSTAT_DATA_UINT64 },
 137  188          { "lookup",     KSTAT_DATA_UINT64 },
 138  189          { "readlink",   KSTAT_DATA_UINT64 },
 139  190          { "read",       KSTAT_DATA_UINT64 },
↓ open down ↓ 41 lines elided ↑ open up ↑
 181  232          { "remove",     KSTAT_DATA_UINT64 },
 182  233          { "rename",     KSTAT_DATA_UINT64 },
 183  234          { "link",       KSTAT_DATA_UINT64 },
 184  235          { "symlink",    KSTAT_DATA_UINT64 },
 185  236          { "mkdir",      KSTAT_DATA_UINT64 },
 186  237          { "rmdir",      KSTAT_DATA_UINT64 },
 187  238          { "readdir",    KSTAT_DATA_UINT64 },
 188  239          { "statfs",     KSTAT_DATA_UINT64 }
 189  240  };
 190  241  
      242 +#define RFSPROCCNT_V2_COUNT     \
      243 +        (sizeof (rfsproccnt_v2_tmpl) / sizeof (rfsproccnt_v2_tmpl[0]))
      244 +
 191  245  kstat_named_t *rfsproccnt_v2_ptr;
      246 +kstat_t **rfsprocio_v2_ptr;
 192  247  
 193  248  static void
 194  249  nfsstat_zone_init_rfsproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 195  250  {
 196      -        kstat_named_t *ks_data;
      251 +        statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
      252 +            "rfsproccnt_v2", rfsproccnt_v2_tmpl, sizeof (rfsproccnt_v2_tmpl));
 197  253  
 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;
      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 +        }
 203  264  }
 204  265  
 205  266  static void
 206  267  nfsstat_zone_fini_rfsproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 207  268  {
 208      -        if (zoneid == GLOBAL_ZONEID)
      269 +        if (zoneid == GLOBAL_ZONEID) {
 209  270                  rfsproccnt_v2_ptr = NULL;
      271 +                rfsprocio_v2_ptr = NULL;
      272 +        }
      273 +
 210  274          nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v2");
 211  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);
 212  280  }
 213  281  
 214  282  /*
 215  283   * NFSv2 client ACL stats
 216  284   */
 217  285  static const kstat_named_t aclreqcnt_v2_tmpl[] = {
 218  286          { "null",       KSTAT_DATA_UINT64 },
 219  287          { "getacl",     KSTAT_DATA_UINT64 },
 220  288          { "setacl",     KSTAT_DATA_UINT64 },
 221  289          { "getattr",    KSTAT_DATA_UINT64 },
↓ open down ↓ 20 lines elided ↑ open up ↑
 242  310   */
 243  311  static const kstat_named_t aclproccnt_v2_tmpl[] = {
 244  312          { "null",       KSTAT_DATA_UINT64 },
 245  313          { "getacl",     KSTAT_DATA_UINT64 },
 246  314          { "setacl",     KSTAT_DATA_UINT64 },
 247  315          { "getattr",    KSTAT_DATA_UINT64 },
 248  316          { "access",     KSTAT_DATA_UINT64 },
 249  317          { "getxattrdir",        KSTAT_DATA_UINT64 }
 250  318  };
 251  319  
      320 +#define ACLPROCCNT_V2_COUNT     \
      321 +        (sizeof (aclproccnt_v2_tmpl) / sizeof (aclproccnt_v2_tmpl[0]))
      322 +
 252  323  kstat_named_t *aclproccnt_v2_ptr;
      324 +kstat_t **aclprocio_v2_ptr;
 253  325  
 254  326  static void
 255  327  nfsstat_zone_init_aclproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 256  328  {
 257      -        kstat_named_t *ks_data;
      329 +        statsp->aclproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
      330 +            "aclproccnt_v2", aclproccnt_v2_tmpl, sizeof (aclproccnt_v2_tmpl));
 258  331  
 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;
      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 +        }
 265  342  }
 266  343  
 267  344  static void
 268  345  nfsstat_zone_fini_aclproc_v2(zoneid_t zoneid, struct nfs_version_stats *statsp)
 269  346  {
 270      -        if (zoneid == GLOBAL_ZONEID)
      347 +        if (zoneid == GLOBAL_ZONEID) {
 271  348                  aclproccnt_v2_ptr = NULL;
      349 +                aclprocio_v2_ptr = NULL;
      350 +        }
      351 +
 272  352          nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v2");
 273  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);
 274  358  }
 275  359  
 276  360  /*
 277  361   * NFSv3 client stats
 278  362   */
 279  363  static const kstat_named_t rfsreqcnt_v3_tmpl[] = {
 280  364          { "null",       KSTAT_DATA_UINT64 },
 281  365          { "getattr",    KSTAT_DATA_UINT64 },
 282  366          { "setattr",    KSTAT_DATA_UINT64 },
 283  367          { "lookup",     KSTAT_DATA_UINT64 },
↓ open down ↓ 52 lines elided ↑ open up ↑
 336  420          { "rename",     KSTAT_DATA_UINT64 },
 337  421          { "link",       KSTAT_DATA_UINT64 },
 338  422          { "readdir",    KSTAT_DATA_UINT64 },
 339  423          { "readdirplus", KSTAT_DATA_UINT64 },
 340  424          { "fsstat",     KSTAT_DATA_UINT64 },
 341  425          { "fsinfo",     KSTAT_DATA_UINT64 },
 342  426          { "pathconf",   KSTAT_DATA_UINT64 },
 343  427          { "commit",     KSTAT_DATA_UINT64 }
 344  428  };
 345  429  
      430 +#define RFSPROCCNT_V3_COUNT     \
      431 +        (sizeof (rfsproccnt_v3_tmpl) / sizeof (rfsproccnt_v3_tmpl[0]))
      432 +
 346  433  kstat_named_t *rfsproccnt_v3_ptr;
      434 +kstat_t **rfsprocio_v3_ptr;
 347  435  
 348  436  static void
 349  437  nfsstat_zone_init_rfsproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 350  438  {
 351      -        kstat_named_t *ks_data;
      439 +        statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
      440 +            "rfsproccnt_v3", rfsproccnt_v3_tmpl, sizeof (rfsproccnt_v3_tmpl));
 352  441  
 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;
      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 +        }
 358  452  }
 359  453  
 360  454  static void
 361  455  nfsstat_zone_fini_rfsproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 362  456  {
 363      -        if (zoneid == GLOBAL_ZONEID)
      457 +        if (zoneid == GLOBAL_ZONEID) {
 364  458                  rfsproccnt_v3_ptr = NULL;
      459 +                rfsprocio_v3_ptr = NULL;
      460 +        }
      461 +
 365  462          nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v3");
 366  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);
 367  468  }
 368  469  
 369  470  /*
 370  471   * NFSv3 client ACL stats
 371  472   */
 372  473  static const kstat_named_t aclreqcnt_v3_tmpl[] = {
 373  474          { "null",       KSTAT_DATA_UINT64 },
 374  475          { "getacl",     KSTAT_DATA_UINT64 },
 375  476          { "setacl",     KSTAT_DATA_UINT64 },
 376  477          { "getxattrdir",        KSTAT_DATA_UINT64 }
↓ open down ↓ 16 lines elided ↑ open up ↑
 393  494  /*
 394  495   * NFSv3 server ACL stats
 395  496   */
 396  497  static const kstat_named_t aclproccnt_v3_tmpl[] = {
 397  498          { "null",       KSTAT_DATA_UINT64 },
 398  499          { "getacl",     KSTAT_DATA_UINT64 },
 399  500          { "setacl",     KSTAT_DATA_UINT64 },
 400  501          { "getxattrdir",        KSTAT_DATA_UINT64 }
 401  502  };
 402  503  
      504 +#define ACLPROCCNT_V3_COUNT     \
      505 +        (sizeof (aclproccnt_v3_tmpl) / sizeof (aclproccnt_v3_tmpl[0]))
      506 +
 403  507  kstat_named_t *aclproccnt_v3_ptr;
      508 +kstat_t **aclprocio_v3_ptr;
 404  509  
 405  510  static void
 406  511  nfsstat_zone_init_aclproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 407  512  {
 408      -        kstat_named_t *ks_data;
      513 +        statsp->aclproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs_acl", 0,
      514 +            "aclproccnt_v3", aclproccnt_v3_tmpl, sizeof (aclproccnt_v3_tmpl));
 409  515  
 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;
      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 +        }
 416  526  }
 417  527  
 418  528  static void
 419  529  nfsstat_zone_fini_aclproc_v3(zoneid_t zoneid, struct nfs_version_stats *statsp)
 420  530  {
 421      -        if (zoneid == GLOBAL_ZONEID)
      531 +        if (zoneid == GLOBAL_ZONEID) {
 422  532                  aclproccnt_v3_ptr = NULL;
      533 +                aclprocio_v3_ptr = NULL;
      534 +        }
      535 +
 423  536          nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v3");
 424  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);
 425  542  }
 426  543  
 427  544  /*
 428  545   * NFSv4 client stats
 429  546   */
 430  547  static const kstat_named_t rfsreqcnt_v4_tmpl[] = {
 431  548          { "null",       KSTAT_DATA_UINT64 },
 432  549          { "compound",   KSTAT_DATA_UINT64 },
 433  550          { "reserved",   KSTAT_DATA_UINT64 },
 434  551          { "access",     KSTAT_DATA_UINT64 },
↓ open down ↓ 88 lines elided ↑ open up ↑
 523  640          { "secinfo",    KSTAT_DATA_UINT64 },
 524  641          { "setattr",    KSTAT_DATA_UINT64 },
 525  642          { "setclientid",        KSTAT_DATA_UINT64 },
 526  643          { "setclientid_confirm",        KSTAT_DATA_UINT64 },
 527  644          { "verify",     KSTAT_DATA_UINT64 },
 528  645          { "write",      KSTAT_DATA_UINT64 },
 529  646          { "release_lockowner",  KSTAT_DATA_UINT64 },
 530  647          { "illegal",    KSTAT_DATA_UINT64 },
 531  648  };
 532  649  
      650 +#define RFSPROCCNT_V4_COUNT     \
      651 +        (sizeof (rfsproccnt_v4_tmpl) / sizeof (rfsproccnt_v4_tmpl[0]))
      652 +
 533  653  kstat_named_t *rfsproccnt_v4_ptr;
      654 +kstat_t **rfsprocio_v4_ptr;
 534  655  
 535  656  static void
 536  657  nfsstat_zone_init_rfsproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
 537  658  {
 538      -        kstat_named_t *ks_data;
      659 +        statsp->rfsproccnt_ptr = nfsstat_zone_init_common(zoneid, "nfs", 0,
      660 +            "rfsproccnt_v4", rfsproccnt_v4_tmpl, sizeof (rfsproccnt_v4_tmpl));
 539  661  
 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;
      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 +        }
 545  672  }
 546  673  
 547  674  static void
 548  675  nfsstat_zone_fini_rfsproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
 549  676  {
 550      -        if (zoneid == GLOBAL_ZONEID)
      677 +        if (zoneid == GLOBAL_ZONEID) {
 551  678                  rfsproccnt_v4_ptr = NULL;
      679 +                rfsprocio_v4_ptr = NULL;
      680 +        }
      681 +
 552  682          nfsstat_zone_fini_common(zoneid, "nfs", 0, "rfsproccnt_v4");
 553  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);
 554  688  }
 555  689  
 556  690  /*
 557  691   * NFSv4 client ACL stats
 558  692   */
 559  693  static const kstat_named_t aclreqcnt_v4_tmpl[] = {
 560  694          { "null",       KSTAT_DATA_UINT64 },
 561  695          { "getacl",     KSTAT_DATA_UINT64 },
 562  696          { "setacl",     KSTAT_DATA_UINT64 },
 563  697  };
↓ open down ↓ 38 lines elided ↑ open up ↑
 602  736  
 603  737  static void
 604  738  nfsstat_zone_fini_aclproc_v4(zoneid_t zoneid, struct nfs_version_stats *statsp)
 605  739  {
 606  740          if (zoneid == GLOBAL_ZONEID)
 607  741                  aclproccnt_v4_ptr = NULL;
 608  742          nfsstat_zone_fini_common(zoneid, "nfs_acl", 0, "aclproccnt_v4");
 609  743          kmem_free(statsp->aclproccnt_ptr, sizeof (aclproccnt_v4_tmpl));
 610  744  }
 611  745  
      746 +
 612  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 +/*
 613  762   * Zone initializer callback to setup the kstats.
 614  763   */
 615  764  void *
 616  765  nfsstat_zone_init(zoneid_t zoneid)
 617  766  {
 618  767          struct nfs_stats *nfs_stats_ptr;
 619  768  
 620  769          nfs_stats_ptr = kmem_zalloc(sizeof (*nfs_stats_ptr), KM_SLEEP);
 621  770  
 622  771          /*
↓ open down ↓ 55 lines elided ↑ open up ↑
 678  827          nfsstat_zone_fini_aclproc_v3(zoneid, &nfs_stats_ptr->nfs_stats_v3);
 679  828          /*
 680  829           * Free v4 stats
 681  830           */
 682  831          nfsstat_zone_fini_rfsreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
 683  832          nfsstat_zone_fini_rfsproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
 684  833          nfsstat_zone_fini_aclreq_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
 685  834          nfsstat_zone_fini_aclproc_v4(zoneid, &nfs_stats_ptr->nfs_stats_v4);
 686  835  
 687  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 +        }
 688 1000  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX