Logo Search packages:      
Sourcecode: zfs-fuse version File versions  Download package

kstat.h

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef     _SYS_KSTAT_H
#define     _SYS_KSTAT_H

/* #pragma ident  "%Z%%M%     %I%   %E% SMI" */

/*
 * Definition of general kernel statistics structures and /dev/kstat ioctls
 */

#include <sys/types.h>
#include <sys/time.h>

#ifdef      __cplusplus
extern "C" {
#endif

typedef int kid_t;            /* unique kstat id */

/*
 * Kernel statistics driver (/dev/kstat) ioctls
 */

#define     KSTAT_IOC_BASE          ('K' << 8)

#define     KSTAT_IOC_CHAIN_ID      KSTAT_IOC_BASE | 0x01
#define     KSTAT_IOC_READ          KSTAT_IOC_BASE | 0x02
#define     KSTAT_IOC_WRITE         KSTAT_IOC_BASE | 0x03

/*
 * /dev/kstat ioctl usage (kd denotes /dev/kstat descriptor):
 *
 *    kcid = ioctl(kd, KSTAT_IOC_CHAIN_ID, NULL);
 *    kcid = ioctl(kd, KSTAT_IOC_READ, kstat_t *);
 *    kcid = ioctl(kd, KSTAT_IOC_WRITE, kstat_t *);
 */

#define     KSTAT_STRLEN      31    /* 30 chars + NULL; must be 16 * n - 1 */

/*
 * The generic kstat header
 */

typedef struct kstat {
      /*
       * Fields relevant to both kernel and user
       */
      hrtime_t    ks_crtime;  /* creation time (from gethrtime()) */
      struct kstat      *ks_next;   /* kstat chain linkage */
      kid_t       ks_kid;           /* unique kstat ID */
      char        ks_module[KSTAT_STRLEN]; /* provider module name */
      uchar_t           ks_resv;    /* reserved, currently just padding */
      int         ks_instance;      /* provider module's instance */
      char        ks_name[KSTAT_STRLEN]; /* kstat name */
      uchar_t           ks_type;    /* kstat data type */
      char        ks_class[KSTAT_STRLEN]; /* kstat class */
      uchar_t           ks_flags;   /* kstat flags */
      void        *ks_data;   /* kstat type-specific data */
      uint_t            ks_ndata;   /* # of type-specific data records */
      size_t            ks_data_size;     /* total size of kstat data section */
      hrtime_t    ks_snaptime;      /* time of last data shapshot */
      /*
       * Fields relevant to kernel only
       */
      int         (*ks_update)(struct kstat *, int); /* dynamic update */
      void        *ks_private;      /* arbitrary provider-private data */
      int         (*ks_snapshot)(struct kstat *, void *, int);
      void        *ks_lock;   /* protects this kstat's data */
} kstat_t;

#ifdef _SYSCALL32

typedef int32_t kid32_t;

typedef struct kstat32 {
      /*
       * Fields relevant to both kernel and user
       */
      hrtime_t    ks_crtime;
      caddr32_t   ks_next;          /* struct kstat pointer */
      kid32_t           ks_kid;
      char        ks_module[KSTAT_STRLEN];
      uint8_t           ks_resv;
      int32_t           ks_instance;
      char        ks_name[KSTAT_STRLEN];
      uint8_t           ks_type;
      char        ks_class[KSTAT_STRLEN];
      uint8_t           ks_flags;
      caddr32_t   ks_data;          /* type-specific data */
      uint32_t    ks_ndata;
      size32_t    ks_data_size;
      hrtime_t    ks_snaptime;
      /*
       * Fields relevant to kernel only (only needed here for padding)
       */
      int32_t           _ks_update;
      caddr32_t   _ks_private;
      int32_t           _ks_snapshot;
      caddr32_t   _ks_lock;
} kstat32_t;

#endif      /* _SYSCALL32 */

/*
 * kstat structure and locking strategy
 *
 * Each kstat consists of a header section (a kstat_t) and a data section.
 * The system maintains a set of kstats, protected by kstat_chain_lock.
 * kstat_chain_lock protects all additions to/deletions from this set,
 * as well as all changes to kstat headers.  kstat data sections are
 * *optionally* protected by the per-kstat ks_lock.  If ks_lock is non-NULL,
 * kstat clients (e.g. /dev/kstat) will acquire this lock for all of their
 * operations on that kstat.  It is up to the kstat provider to decide whether
 * guaranteeing consistent data to kstat clients is sufficiently important
 * to justify the locking cost.  Note, however, that most statistic updates
 * already occur under one of the provider's mutexes, so if the provider sets
 * ks_lock to point to that mutex, then kstat data locking is free.
 *
 * NOTE: variable-size kstats MUST employ kstat data locking, to prevent
 * data-size races with kstat clients.
 *
 * NOTE: ks_lock is really of type (kmutex_t *); it is declared as (void *)
 * in the kstat header so that users don't have to be exposed to all of the
 * kernel's lock-related data structures.
 */

#if   defined(_KERNEL)

#define     KSTAT_ENTER(k)    \
      { kmutex_t *lp = (k)->ks_lock; if (lp) mutex_enter(lp); }

#define     KSTAT_EXIT(k)     \
      { kmutex_t *lp = (k)->ks_lock; if (lp) mutex_exit(lp); }

#define     KSTAT_UPDATE(k, rw)           (*(k)->ks_update)((k), (rw))

#define     KSTAT_SNAPSHOT(k, buf, rw)    (*(k)->ks_snapshot)((k), (buf), (rw))

#endif      /* defined(_KERNEL) */

/*
 * kstat time
 *
 * All times associated with kstats (e.g. creation time, snapshot time,
 * kstat_timer_t and kstat_io_t timestamps, etc.) are 64-bit nanosecond values,
 * as returned by gethrtime().  The accuracy of these timestamps is machine
 * dependent, but the precision (units) is the same across all platforms.
 */

/*
 * kstat identity (KID)
 *
 * Each kstat is assigned a unique KID (kstat ID) when it is added to the
 * global kstat chain.  The KID is used as a cookie by /dev/kstat to
 * request information about the corresponding kstat.  There is also
 * an identity associated with the entire kstat chain, kstat_chain_id,
 * which is bumped each time a kstat is added or deleted.  /dev/kstat uses
 * the chain ID to detect changes in the kstat chain (e.g., a new disk
 * coming online) between ioctl()s.
 */

/*
 * kstat module, kstat instance
 *
 * ks_module and ks_instance contain the name and instance of the module
 * that created the kstat.  In cases where there can only be one instance,
 * ks_instance is 0.  The kernel proper (/kernel/unix) uses "unix" as its
 * module name.
 */

/*
 * kstat name
 *
 * ks_name gives a meaningful name to a kstat.  The full kstat namespace
 * is module.instance.name, so the name only need be unique within a
 * module.  kstat_create() will fail if you try to create a kstat with
 * an already-used (ks_module, ks_instance, ks_name) triplet.  Spaces are
 * allowed in kstat names, but strongly discouraged, since they hinder
 * awk-style processing at user level.
 */

/*
 * kstat type
 *
 * The kstat mechanism provides several flavors of kstat data, defined
 * below.  The "raw" kstat type is just treated as an array of bytes; you
 * can use this to export any kind of data you want.
 *
 * Some kstat types allow multiple data structures per kstat, e.g.
 * KSTAT_TYPE_NAMED; others do not.  This is part of the spec for each
 * kstat data type.
 *
 * User-level tools should *not* rely on the #define KSTAT_NUM_TYPES.  To
 * get this information, read out the standard system kstat "kstat_types".
 */

#define     KSTAT_TYPE_RAW          0     /* can be anything */
                              /* ks_ndata >= 1 */
#define     KSTAT_TYPE_NAMED  1     /* name/value pair */
                              /* ks_ndata >= 1 */
#define     KSTAT_TYPE_INTR         2     /* interrupt statistics */
                              /* ks_ndata == 1 */
#define     KSTAT_TYPE_IO           3     /* I/O statistics */
                              /* ks_ndata == 1 */
#define     KSTAT_TYPE_TIMER  4     /* event timer */
                              /* ks_ndata >= 1 */

#define     KSTAT_NUM_TYPES         5

/*
 * kstat class
 *
 * Each kstat can be characterized as belonging to some broad class
 * of statistics, e.g. disk, tape, net, vm, streams, etc.  This field
 * can be used as a filter to extract related kstats.  The following
 * values are currently in use: disk, tape, net, controller, vm, kvm,
 * hat, streams, kstat, and misc.  (The kstat class encompasses things
 * like kstat_types.)
 */

/*
 * kstat flags
 *
 * Any of the following flags may be passed to kstat_create().  They are
 * all zero by default.
 *
 *    KSTAT_FLAG_VIRTUAL:
 *
 *          Tells kstat_create() not to allocate memory for the
 *          kstat data section; instead, you will set the ks_data
 *          field to point to the data you wish to export.  This
 *          provides a convenient way to export existing data
 *          structures.
 *
 *    KSTAT_FLAG_VAR_SIZE:
 *
 *          The size of the kstat you are creating will vary over time.
 *          For example, you may want to use the kstat mechanism to
 *          export a linked list.  NOTE: The kstat framework does not
 *          manage the data section, so all variable-size kstats must be
 *          virtual kstats.  Moreover, variable-size kstats MUST employ
 *          kstat data locking to prevent data-size races with kstat
 *          clients.  See the section on "kstat snapshot" for details.
 *
 *    KSTAT_FLAG_WRITABLE:
 *
 *          Makes the kstat's data section writable by root.
 *          The ks_snapshot routine (see below) does not need to check for
 *          this; permission checking is handled in the kstat driver.
 *
 *    KSTAT_FLAG_PERSISTENT:
 *
 *          Indicates that this kstat is to be persistent over time.
 *          For persistent kstats, kstat_delete() simply marks the
 *          kstat as dormant; a subsequent kstat_create() reactivates
 *          the kstat.  This feature is provided so that statistics
 *          are not lost across driver close/open (e.g., raw disk I/O
 *          on a disk with no mounted partitions.)
 *          NOTE: Persistent kstats cannot be virtual, since ks_data
 *          points to garbage as soon as the driver goes away.
 *
 * The following flags are maintained by the kstat framework:
 *
 *    KSTAT_FLAG_DORMANT:
 *
 *          For persistent kstats, indicates that the kstat is in the
 *          dormant state (e.g., the corresponding device is closed).
 *
 *    KSTAT_FLAG_INVALID:
 *
 *          This flag is set when a kstat is in a transitional state,
 *          e.g. between kstat_create() and kstat_install().
 *          kstat clients must not attempt to access the kstat's data
 *          if this flag is set.
 */

#define     KSTAT_FLAG_VIRTUAL            0x01
#define     KSTAT_FLAG_VAR_SIZE           0x02
#define     KSTAT_FLAG_WRITABLE           0x04
#define     KSTAT_FLAG_PERSISTENT         0x08
#define     KSTAT_FLAG_DORMANT            0x10
#define     KSTAT_FLAG_INVALID            0x20

/*
 * Dynamic update support
 *
 * The kstat mechanism allows for an optional ks_update function to update
 * kstat data.  This is useful for drivers where the underlying device
 * keeps cheap hardware stats, but extraction is expensive.  Instead of
 * constantly keeping the kstat data section up to date, you can supply a
 * ks_update function which updates the kstat's data section on demand.
 * To take advantage of this feature, simply set the ks_update field before
 * calling kstat_install().
 *
 * The ks_update function, if supplied, must have the following structure:
 *
 *    int
 *    foo_kstat_update(kstat_t *ksp, int rw)
 *    {
 *          if (rw == KSTAT_WRITE) {
 *                ... update the native stats from ksp->ks_data;
 *                      return EACCES if you don't support this
 *          } else {
 *                ... update ksp->ks_data from the native stats
 *          }
 *    }
 *
 * The ks_update return codes are: 0 for success, EACCES if you don't allow
 * KSTAT_WRITE, and EIO for any other type of error.
 *
 * In general, the ks_update function may need to refer to provider-private
 * data; for example, it may need a pointer to the provider's raw statistics.
 * The ks_private field is available for this purpose.  Its use is entirely
 * at the provider's discretion.
 *
 * All variable-size kstats MUST supply a ks_update routine, which computes
 * and sets ks_data_size (and ks_ndata if that is meaningful), since these
 * are needed to perform kstat snapshots (see below).
 *
 * No kstat locking should be done inside the ks_update routine.  The caller
 * will already be holding the kstat's ks_lock (to ensure consistent data).
 */

#define     KSTAT_READ  0
#define     KSTAT_WRITE 1

/*
 * Kstat snapshot
 *
 * In order to get a consistent view of a kstat's data, clients must obey
 * the kstat's locking strategy.  However, these clients may need to perform
 * operations on the data which could cause a fault (e.g. copyout()), or
 * operations which are simply expensive.  Doing so could cause deadlock
 * (e.g. if you're holding a disk's kstat lock which is ultimately required
 * to resolve a copyout() fault), performance degradation (since the providers'
 * activity is serialized at the kstat lock), device timing problems, etc.
 *
 * To avoid these problems, kstat data is provided via snapshots.  Taking
 * a snapshot is a simple process: allocate a wired-down kernel buffer,
 * acquire the kstat's data lock, copy the data into the buffer ("take the
 * snapshot"), and release the lock.  This ensures that the kstat's data lock
 * will be held as briefly as possible, and that no faults will occur while
 * the lock is held.
 *
 * Normally, the snapshot is taken by default_kstat_snapshot(), which
 * timestamps the data (sets ks_snaptime), copies it, and does a little
 * massaging to deal with incomplete transactions on i/o kstats.  However,
 * this routine only works for kstats with contiguous data (the typical case).
 * If you create a kstat whose data is, say, a linked list, you must provide
 * your own ks_snapshot routine.  The routine you supply must have the
 * following prototype (replace "foo" with something appropriate):
 *
 *    int foo_kstat_snapshot(kstat_t *ksp, void *buf, int rw);
 *
 * The minimal snapshot routine -- one which copies contiguous data that
 * doesn't need any massaging -- would be this:
 *
 *    ksp->ks_snaptime = gethrtime();
 *    if (rw == KSTAT_WRITE)
 *          bcopy(buf, ksp->ks_data, ksp->ks_data_size);
 *    else
 *          bcopy(ksp->ks_data, buf, ksp->ks_data_size);
 *    return (0);
 *
 * A more illuminating example is taking a snapshot of a linked list:
 *
 *    ksp->ks_snaptime = gethrtime();
 *    if (rw == KSTAT_WRITE)
 *          return (EACCES);        ... See below ...
 *    for (foo = first_foo; foo; foo = foo->next) {
 *          bcopy((char *) foo, (char *) buf, sizeof (struct foo));
 *          buf = ((struct foo *) buf) + 1;
 *    }
 *    return (0);
 *
 * In the example above, we have decided that we don't want to allow
 * KSTAT_WRITE access, so we return EACCES if this is attempted.
 *
 * The key points are:
 *
 *    (1) ks_snaptime must be set (via gethrtime()) to timestamp the data.
 *    (2) Data gets copied from the kstat to the buffer on KSTAT_READ,
 *          and from the buffer to the kstat on KSTAT_WRITE.
 *    (3) ks_snapshot return values are: 0 for success, EACCES if you
 *          don't allow KSTAT_WRITE, and EIO for any other type of error.
 *
 * Named kstats (see section on "Named statistics" below) containing long
 * strings (KSTAT_DATA_STRING) need special handling.  The kstat driver
 * assumes that all strings are copied into the buffer after the array of
 * named kstats, and the pointers (KSTAT_NAMED_STR_PTR()) are updated to point
 * into the copy within the buffer. The default snapshot routine does this,
 * but overriding routines should contain at least the following:
 *
 * if (rw == KSTAT_READ) {
 *    kstat_named_t *knp = buf;
 *    char *end = knp + ksp->ks_ndata;
 *    uint_t i;
 *
 *    ... Do the regular copy ...
 *    bcopy(ksp->ks_data, buf, sizeof (kstat_named_t) * ksp->ks_ndata);
 *
 *    for (i = 0; i < ksp->ks_ndata; i++, knp++) {
 *          if (knp[i].data_type == KSTAT_DATA_STRING &&
 *              KSTAT_NAMED_STR_PTR(knp) != NULL) {
 *                bcopy(KSTAT_NAMED_STR_PTR(knp), end,
 *                    KSTAT_NAMED_STR_BUFLEN(knp));
 *                KSTAT_NAMED_STR_PTR(knp) = end;
 *                end += KSTAT_NAMED_STR_BUFLEN(knp);
 *          }
 *    }
 */

/*
 * Named statistics.
 *
 * List of arbitrary name=value statistics.
 */

typedef struct kstat_named {
      char  name[KSTAT_STRLEN];     /* name of counter */
      uchar_t     data_type;        /* data type */
      union {
            char        c[16];      /* enough for 128-bit ints */
            int32_t           i32;
            uint32_t    ui32;
            struct {
                  union {
                        char        *ptr; /* NULL-term string */
#if defined(_KERNEL) && defined(_MULTI_DATAMODEL)
                        caddr32_t   ptr32;
#endif
                        char        __pad[8]; /* 64-bit padding */
                  } addr;
                  uint32_t    len;  /* # bytes for strlen + '\0' */
            } str;
/*
 * The int64_t and uint64_t types are not valid for a maximally conformant
 * 32-bit compilation environment (cc -Xc) using compilers prior to the
 * introduction of C99 conforming compiler (reference ISO/IEC 9899:1990).
 * In these cases, the visibility of i64 and ui64 is only permitted for
 * 64-bit compilation environments or 32-bit non-maximally conformant
 * C89 or C90 ANSI C compilation environments (cc -Xt and cc -Xa). In the
 * C99 ANSI C compilation environment, the long long type is supported.
 * The _INT64_TYPE is defined by the implementation (see sys/int_types.h).
 */
#if defined(_INT64_TYPE)
            int64_t           i64;
            uint64_t    ui64;
#endif
            long        l;
            ulong_t           ul;

            /* These structure members are obsolete */

            longlong_t  ll;
            u_longlong_t      ull;
            float       f;
            double            d;
      } value;                /* value of counter */
} kstat_named_t;

#define     KSTAT_DATA_CHAR         0
#define     KSTAT_DATA_INT32  1
#define     KSTAT_DATA_UINT32 2
#define     KSTAT_DATA_INT64  3
#define     KSTAT_DATA_UINT64 4

#if !defined(_LP64)
#define     KSTAT_DATA_LONG         KSTAT_DATA_INT32
#define     KSTAT_DATA_ULONG  KSTAT_DATA_UINT32
#else
#if !defined(_KERNEL)
#define     KSTAT_DATA_LONG         KSTAT_DATA_INT64
#define     KSTAT_DATA_ULONG  KSTAT_DATA_UINT64
#else
#define     KSTAT_DATA_LONG         7     /* only visible to the kernel */
#define     KSTAT_DATA_ULONG  8     /* only visible to the kernel */
#endif      /* !_KERNEL */
#endif      /* !_LP64 */

/*
 * Statistics exporting named kstats with long strings (KSTAT_DATA_STRING)
 * may not make the assumption that ks_data_size is equal to (ks_ndata * sizeof
 * (kstat_named_t)).  ks_data_size in these cases is equal to the sum of the
 * amount of space required to store the strings (ie, the sum of
 * KSTAT_NAMED_STR_BUFLEN() for all KSTAT_DATA_STRING statistics) plus the
 * space required to store the kstat_named_t's.
 *
 * The default update routine will update ks_data_size automatically for
 * variable-length kstats containing long strings (using the default update
 * routine only makes sense if the string is the only thing that is changing
 * in size, and ks_ndata is constant).  Fixed-length kstats containing long
 * strings must explicitly change ks_data_size (after creation but before
 * initialization) to reflect the correct amount of space required for the
 * long strings and the kstat_named_t's.
 */
#define     KSTAT_DATA_STRING 9

/* These types are obsolete */

#define     KSTAT_DATA_LONGLONG     KSTAT_DATA_INT64
#define     KSTAT_DATA_ULONGLONG    KSTAT_DATA_UINT64
#define     KSTAT_DATA_FLOAT  5
#define     KSTAT_DATA_DOUBLE 6

#define     KSTAT_NAMED_PTR(kptr)   ((kstat_named_t *)(kptr)->ks_data)

/*
 * Retrieve the pointer of the string contained in the given named kstat.
 */
#define     KSTAT_NAMED_STR_PTR(knptr) ((knptr)->value.str.addr.ptr)

/*
 * Retrieve the length of the buffer required to store the string in the given
 * named kstat.
 */
#define     KSTAT_NAMED_STR_BUFLEN(knptr) ((knptr)->value.str.len)

/*
 * Interrupt statistics.
 *
 * An interrupt is a hard interrupt (sourced from the hardware device
 * itself), a soft interrupt (induced by the system via the use of
 * some system interrupt source), a watchdog interrupt (induced by
 * a periodic timer call), spurious (an interrupt entry point was
 * entered but there was no interrupt condition to service),
 * or multiple service (an interrupt condition was detected and
 * serviced just prior to returning from any of the other types).
 *
 * Measurement of the spurious class of interrupts is useful for
 * autovectored devices in order to pinpoint any interrupt latency
 * problems in a particular system configuration.
 *
 * Devices that have more than one interrupt of the same
 * type should use multiple structures.
 */

#define     KSTAT_INTR_HARD               0
#define     KSTAT_INTR_SOFT               1
#define     KSTAT_INTR_WATCHDOG           2
#define     KSTAT_INTR_SPURIOUS           3
#define     KSTAT_INTR_MULTSVC            4

#define     KSTAT_NUM_INTRS               5

typedef struct kstat_intr {
      uint_t      intrs[KSTAT_NUM_INTRS]; /* interrupt counters */
} kstat_intr_t;

#define     KSTAT_INTR_PTR(kptr)    ((kstat_intr_t *)(kptr)->ks_data)

/*
 * I/O statistics.
 */

typedef struct kstat_io {

      /*
       * Basic counters.
       *
       * The counters should be updated at the end of service
       * (e.g., just prior to calling biodone()).
       */

      u_longlong_t      nread;            /* number of bytes read */
      u_longlong_t      nwritten;   /* number of bytes written */
      uint_t            reads;            /* number of read operations */
      uint_t            writes;           /* number of write operations */

      /*
       * Accumulated time and queue length statistics.
       *
       * Accumulated time statistics are kept as a running sum
       * of "active" time.  Queue length statistics are kept as a
       * running sum of the product of queue length and elapsed time
       * at that length -- i.e., a Riemann sum for queue length
       * integrated against time.  (You can also think of the active time
       * as a Riemann sum, for the boolean function (queue_length > 0)
       * integrated against time, or you can think of it as the
       * Lebesgue measure of the set on which queue_length > 0.)
       *
       *          ^
       *          |                 _________
       *          8                 | i4  |
       *          |                 |     |
       *    Queue 6                 |     |
       *    Length      |     _________   |     |
       *          4     | i2  |_______|   |
       *          |     |         i3            |
       *          2_______|               |
       *          |    i1                       |
       *          |_______________________________|
       *          Time->      t1    t2    t3    t4
       *
       * At each change of state (entry or exit from the queue),
       * we add the elapsed time (since the previous state change)
       * to the active time if the queue length was non-zero during
       * that interval; and we add the product of the elapsed time
       * times the queue length to the running length*time sum.
       *
       * This method is generalizable to measuring residency
       * in any defined system: instead of queue lengths, think
       * of "outstanding RPC calls to server X".
       *
       * A large number of I/O subsystems have at least two basic
       * "lists" of transactions they manage: one for transactions
       * that have been accepted for processing but for which processing
       * has yet to begin, and one for transactions which are actively
       * being processed (but not done). For this reason, two cumulative
       * time statistics are defined here: wait (pre-service) time,
       * and run (service) time.
       *
       * All times are 64-bit nanoseconds (hrtime_t), as returned by
       * gethrtime().
       *
       * The units of cumulative busy time are accumulated nanoseconds.
       * The units of cumulative length*time products are elapsed time
       * times queue length.
       *
       * Updates to the fields below are performed implicitly by calls to
       * these five functions:
       *
       *    kstat_waitq_enter()
       *    kstat_waitq_exit()
       *    kstat_runq_enter()
       *    kstat_runq_exit()
       *
       *    kstat_waitq_to_runq()         (see below)
       *    kstat_runq_back_to_waitq()    (see below)
       *
       * Since kstat_waitq_exit() is typically followed immediately
       * by kstat_runq_enter(), there is a single kstat_waitq_to_runq()
       * function which performs both operations.  This is a performance
       * win since only one timestamp is required.
       *
       * In some instances, it may be necessary to move a request from
       * the run queue back to the wait queue, e.g. for write throttling.
       * For these situations, call kstat_runq_back_to_waitq().
       *
       * These fields should never be updated by any other means.
       */

      hrtime_t wtime;         /* cumulative wait (pre-service) time */
      hrtime_t wlentime;      /* cumulative wait length*time product */
      hrtime_t wlastupdate;   /* last time wait queue changed */
      hrtime_t rtime;         /* cumulative run (service) time */
      hrtime_t rlentime;      /* cumulative run length*time product */
      hrtime_t rlastupdate;   /* last time run queue changed */

      uint_t      wcnt;       /* count of elements in wait state */
      uint_t      rcnt;       /* count of elements in run state */

} kstat_io_t;

#define     KSTAT_IO_PTR(kptr)      ((kstat_io_t *)(kptr)->ks_data)

/*
 * Event timer statistics - cumulative elapsed time and number of events.
 *
 * Updates to these fields are performed implicitly by calls to
 * kstat_timer_start() and kstat_timer_stop().
 */

typedef struct kstat_timer {
      char        name[KSTAT_STRLEN];     /* event name */
      uchar_t           resv;             /* reserved */
      u_longlong_t      num_events;       /* number of events */
      hrtime_t    elapsed_time;           /* cumulative elapsed time */
      hrtime_t    min_time;         /* shortest event duration */
      hrtime_t    max_time;         /* longest event duration */
      hrtime_t    start_time;       /* previous event start time */
      hrtime_t    stop_time;        /* previous event stop time */
} kstat_timer_t;

#define     KSTAT_TIMER_PTR(kptr)   ((kstat_timer_t *)(kptr)->ks_data)

#if   defined(_KERNEL)

#include <sys/t_lock.h>

extern kid_t      kstat_chain_id;         /* bumped at each state change */
extern void kstat_init(void); /* initialize kstat framework */

/*
 * Adding and deleting kstats.
 *
 * The typical sequence to add a kstat is:
 *
 *    ksp = kstat_create(module, instance, name, class, type, ndata, flags);
 *    if (ksp) {
 *          ... provider initialization, if necessary
 *          kstat_install(ksp);
 *    }
 *
 * There are three logically distinct steps here:
 *
 * Step 1: System Initialization (kstat_create)
 *
 * kstat_create() performs system initialization.  kstat_create()
 * allocates memory for the entire kstat (header plus data), initializes
 * all header fields, initializes the data section to all zeroes, assigns
 * a unique KID, and puts the kstat onto the system's kstat chain.
 * The returned kstat is marked invalid (KSTAT_FLAG_INVALID is set),
 * because the provider (caller) has not yet had a chance to initialize
 * the data section.
 *
 * By default, kstats are exported to all zones on the system.  A kstat may be
 * created via kstat_create_zone() to specify a zone to which the statistics
 * should be exported.  kstat_zone_add() may be used to specify additional
 * zones to which the statistics are to be exported.
 *
 * Step 2: Provider Initialization
 *
 * The provider performs any necessary initialization of the data section,
 * e.g. setting the name fields in a KSTAT_TYPE_NAMED.  Virtual kstats set
 * the ks_data field at this time.  The provider may also set the ks_update,
 * ks_snapshot, ks_private, and ks_lock fields if necessary.
 *
 * Step 3: Installation (kstat_install)
 *
 * Once the kstat is completely initialized, kstat_install() clears the
 * INVALID flag, thus making the kstat accessible to the outside world.
 * kstat_install() also clears the DORMANT flag for persistent kstats.
 *
 * Removing a kstat from the system
 *
 * kstat_delete(ksp) removes ksp from the kstat chain and frees all
 * associated system resources.  NOTE: When you call kstat_delete(),
 * you must NOT be holding that kstat's ks_lock.  Otherwise, you may
 * deadlock with a kstat reader.
 *
 * Persistent kstats
 *
 * From the provider's point of view, persistence is transparent.  The only
 * difference between ephemeral (normal) kstats and persistent kstats
 * is that you pass KSTAT_FLAG_PERSISTENT to kstat_create().  Magically,
 * this has the effect of making your data visible even when you're
 * not home.  Persistence is important to tools like iostat, which want
 * to get a meaningful picture of disk activity.  Without persistence,
 * raw disk i/o statistics could never accumulate: they would come and
 * go with each open/close of the raw device.
 *
 * The magic of persistence works by slightly altering the behavior of
 * kstat_create() and kstat_delete().  The first call to kstat_create()
 * creates a new kstat, as usual.  However, kstat_delete() does not
 * actually delete the kstat: it performs one final update of the data
 * (i.e., calls the ks_update routine), marks the kstat as dormant, and
 * sets the ks_lock, ks_update, ks_private, and ks_snapshot fields back
 * to their default values (since they might otherwise point to garbage,
 * e.g. if the provider is going away).  kstat clients can still access
 * the dormant kstat just like a live kstat; they just continue to see
 * the final data values as long as the kstat remains dormant.
 * All subsequent kstat_create() calls simply find the already-existing,
 * dormant kstat and return a pointer to it, without altering any fields.
 * The provider then performs its usual initialization sequence, and
 * calls kstat_install().  kstat_install() uses the old data values to
 * initialize the native data (i.e., ks_update is called with KSTAT_WRITE),
 * thus making it seem like you were never gone.
 */

extern kstat_t *kstat_create(const char *, int, const char *, const char *,
    uchar_t, uint_t, uchar_t);
extern kstat_t *kstat_create_zone(const char *, int, const char *,
    const char *, uchar_t, uint_t, uchar_t, zoneid_t);
extern void kstat_install(kstat_t *);
extern void kstat_delete(kstat_t *);
extern void kstat_named_setstr(kstat_named_t *knp, const char *src);
extern void kstat_set_string(char *, const char *);
extern void kstat_delete_byname(const char *, int, const char *);
extern void kstat_delete_byname_zone(const char *, int, const char *, zoneid_t);
extern void kstat_named_init(kstat_named_t *, const char *, uchar_t);
extern void kstat_timer_init(kstat_timer_t *, const char *);
extern void kstat_waitq_enter(kstat_io_t *);
extern void kstat_waitq_exit(kstat_io_t *);
extern void kstat_runq_enter(kstat_io_t *);
extern void kstat_runq_exit(kstat_io_t *);
extern void kstat_waitq_to_runq(kstat_io_t *);
extern void kstat_runq_back_to_waitq(kstat_io_t *);
extern void kstat_timer_start(kstat_timer_t *);
extern void kstat_timer_stop(kstat_timer_t *);

extern void kstat_zone_add(kstat_t *, zoneid_t);
extern void kstat_zone_remove(kstat_t *, zoneid_t);
extern int kstat_zone_find(kstat_t *, zoneid_t);

extern kstat_t *kstat_hold_bykid(kid_t kid, zoneid_t);
extern kstat_t *kstat_hold_byname(const char *, int, const char *, zoneid_t);
extern void kstat_rele(kstat_t *);

#endif      /* defined(_KERNEL) */

#ifdef      __cplusplus
}
#endif

#endif      /* _SYS_KSTAT_H */

Generated by  Doxygen 1.6.0   Back to index