1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #ifndef _SYS_KSTAT_H 28*7c478bd9Sstevel@tonic-gate #define _SYS_KSTAT_H 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * Definition of general kernel statistics structures and /dev/kstat ioctls 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 40*7c478bd9Sstevel@tonic-gate extern "C" { 41*7c478bd9Sstevel@tonic-gate #endif 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate typedef int kid_t; /* unique kstat id */ 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* 46*7c478bd9Sstevel@tonic-gate * Kernel statistics driver (/dev/kstat) ioctls 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #define KSTAT_IOC_BASE ('K' << 8) 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #define KSTAT_IOC_CHAIN_ID KSTAT_IOC_BASE | 0x01 52*7c478bd9Sstevel@tonic-gate #define KSTAT_IOC_READ KSTAT_IOC_BASE | 0x02 53*7c478bd9Sstevel@tonic-gate #define KSTAT_IOC_WRITE KSTAT_IOC_BASE | 0x03 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * /dev/kstat ioctl usage (kd denotes /dev/kstat descriptor): 57*7c478bd9Sstevel@tonic-gate * 58*7c478bd9Sstevel@tonic-gate * kcid = ioctl(kd, KSTAT_IOC_CHAIN_ID, NULL); 59*7c478bd9Sstevel@tonic-gate * kcid = ioctl(kd, KSTAT_IOC_READ, kstat_t *); 60*7c478bd9Sstevel@tonic-gate * kcid = ioctl(kd, KSTAT_IOC_WRITE, kstat_t *); 61*7c478bd9Sstevel@tonic-gate */ 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #define KSTAT_STRLEN 31 /* 30 chars + NULL; must be 16 * n - 1 */ 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * The generic kstat header 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate typedef struct kstat { 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * Fields relevant to both kernel and user 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate hrtime_t ks_crtime; /* creation time (from gethrtime()) */ 74*7c478bd9Sstevel@tonic-gate struct kstat *ks_next; /* kstat chain linkage */ 75*7c478bd9Sstevel@tonic-gate kid_t ks_kid; /* unique kstat ID */ 76*7c478bd9Sstevel@tonic-gate char ks_module[KSTAT_STRLEN]; /* provider module name */ 77*7c478bd9Sstevel@tonic-gate uchar_t ks_resv; /* reserved, currently just padding */ 78*7c478bd9Sstevel@tonic-gate int ks_instance; /* provider module's instance */ 79*7c478bd9Sstevel@tonic-gate char ks_name[KSTAT_STRLEN]; /* kstat name */ 80*7c478bd9Sstevel@tonic-gate uchar_t ks_type; /* kstat data type */ 81*7c478bd9Sstevel@tonic-gate char ks_class[KSTAT_STRLEN]; /* kstat class */ 82*7c478bd9Sstevel@tonic-gate uchar_t ks_flags; /* kstat flags */ 83*7c478bd9Sstevel@tonic-gate void *ks_data; /* kstat type-specific data */ 84*7c478bd9Sstevel@tonic-gate uint_t ks_ndata; /* # of type-specific data records */ 85*7c478bd9Sstevel@tonic-gate size_t ks_data_size; /* total size of kstat data section */ 86*7c478bd9Sstevel@tonic-gate hrtime_t ks_snaptime; /* time of last data shapshot */ 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * Fields relevant to kernel only 89*7c478bd9Sstevel@tonic-gate */ 90*7c478bd9Sstevel@tonic-gate int (*ks_update)(struct kstat *, int); /* dynamic update */ 91*7c478bd9Sstevel@tonic-gate void *ks_private; /* arbitrary provider-private data */ 92*7c478bd9Sstevel@tonic-gate int (*ks_snapshot)(struct kstat *, void *, int); 93*7c478bd9Sstevel@tonic-gate void *ks_lock; /* protects this kstat's data */ 94*7c478bd9Sstevel@tonic-gate } kstat_t; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate typedef int32_t kid32_t; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate typedef struct kstat32 { 101*7c478bd9Sstevel@tonic-gate /* 102*7c478bd9Sstevel@tonic-gate * Fields relevant to both kernel and user 103*7c478bd9Sstevel@tonic-gate */ 104*7c478bd9Sstevel@tonic-gate hrtime_t ks_crtime; 105*7c478bd9Sstevel@tonic-gate caddr32_t ks_next; /* struct kstat pointer */ 106*7c478bd9Sstevel@tonic-gate kid32_t ks_kid; 107*7c478bd9Sstevel@tonic-gate char ks_module[KSTAT_STRLEN]; 108*7c478bd9Sstevel@tonic-gate uint8_t ks_resv; 109*7c478bd9Sstevel@tonic-gate int32_t ks_instance; 110*7c478bd9Sstevel@tonic-gate char ks_name[KSTAT_STRLEN]; 111*7c478bd9Sstevel@tonic-gate uint8_t ks_type; 112*7c478bd9Sstevel@tonic-gate char ks_class[KSTAT_STRLEN]; 113*7c478bd9Sstevel@tonic-gate uint8_t ks_flags; 114*7c478bd9Sstevel@tonic-gate caddr32_t ks_data; /* type-specific data */ 115*7c478bd9Sstevel@tonic-gate uint32_t ks_ndata; 116*7c478bd9Sstevel@tonic-gate size32_t ks_data_size; 117*7c478bd9Sstevel@tonic-gate hrtime_t ks_snaptime; 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * Fields relevant to kernel only (only needed here for padding) 120*7c478bd9Sstevel@tonic-gate */ 121*7c478bd9Sstevel@tonic-gate int32_t _ks_update; 122*7c478bd9Sstevel@tonic-gate caddr32_t _ks_private; 123*7c478bd9Sstevel@tonic-gate int32_t _ks_snapshot; 124*7c478bd9Sstevel@tonic-gate caddr32_t _ks_lock; 125*7c478bd9Sstevel@tonic-gate } kstat32_t; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32 */ 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate /* 130*7c478bd9Sstevel@tonic-gate * kstat structure and locking strategy 131*7c478bd9Sstevel@tonic-gate * 132*7c478bd9Sstevel@tonic-gate * Each kstat consists of a header section (a kstat_t) and a data section. 133*7c478bd9Sstevel@tonic-gate * The system maintains a set of kstats, protected by kstat_chain_lock. 134*7c478bd9Sstevel@tonic-gate * kstat_chain_lock protects all additions to/deletions from this set, 135*7c478bd9Sstevel@tonic-gate * as well as all changes to kstat headers. kstat data sections are 136*7c478bd9Sstevel@tonic-gate * *optionally* protected by the per-kstat ks_lock. If ks_lock is non-NULL, 137*7c478bd9Sstevel@tonic-gate * kstat clients (e.g. /dev/kstat) will acquire this lock for all of their 138*7c478bd9Sstevel@tonic-gate * operations on that kstat. It is up to the kstat provider to decide whether 139*7c478bd9Sstevel@tonic-gate * guaranteeing consistent data to kstat clients is sufficiently important 140*7c478bd9Sstevel@tonic-gate * to justify the locking cost. Note, however, that most statistic updates 141*7c478bd9Sstevel@tonic-gate * already occur under one of the provider's mutexes, so if the provider sets 142*7c478bd9Sstevel@tonic-gate * ks_lock to point to that mutex, then kstat data locking is free. 143*7c478bd9Sstevel@tonic-gate * 144*7c478bd9Sstevel@tonic-gate * NOTE: variable-size kstats MUST employ kstat data locking, to prevent 145*7c478bd9Sstevel@tonic-gate * data-size races with kstat clients. 146*7c478bd9Sstevel@tonic-gate * 147*7c478bd9Sstevel@tonic-gate * NOTE: ks_lock is really of type (kmutex_t *); it is declared as (void *) 148*7c478bd9Sstevel@tonic-gate * in the kstat header so that users don't have to be exposed to all of the 149*7c478bd9Sstevel@tonic-gate * kernel's lock-related data structures. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate #if defined(_KERNEL) 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate #define KSTAT_ENTER(k) \ 155*7c478bd9Sstevel@tonic-gate { kmutex_t *lp = (k)->ks_lock; if (lp) mutex_enter(lp); } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate #define KSTAT_EXIT(k) \ 158*7c478bd9Sstevel@tonic-gate { kmutex_t *lp = (k)->ks_lock; if (lp) mutex_exit(lp); } 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate #define KSTAT_UPDATE(k, rw) (*(k)->ks_update)((k), (rw)) 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate #define KSTAT_SNAPSHOT(k, buf, rw) (*(k)->ks_snapshot)((k), (buf), (rw)) 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate #endif /* defined(_KERNEL) */ 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * kstat time 168*7c478bd9Sstevel@tonic-gate * 169*7c478bd9Sstevel@tonic-gate * All times associated with kstats (e.g. creation time, snapshot time, 170*7c478bd9Sstevel@tonic-gate * kstat_timer_t and kstat_io_t timestamps, etc.) are 64-bit nanosecond values, 171*7c478bd9Sstevel@tonic-gate * as returned by gethrtime(). The accuracy of these timestamps is machine 172*7c478bd9Sstevel@tonic-gate * dependent, but the precision (units) is the same across all platforms. 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * kstat identity (KID) 177*7c478bd9Sstevel@tonic-gate * 178*7c478bd9Sstevel@tonic-gate * Each kstat is assigned a unique KID (kstat ID) when it is added to the 179*7c478bd9Sstevel@tonic-gate * global kstat chain. The KID is used as a cookie by /dev/kstat to 180*7c478bd9Sstevel@tonic-gate * request information about the corresponding kstat. There is also 181*7c478bd9Sstevel@tonic-gate * an identity associated with the entire kstat chain, kstat_chain_id, 182*7c478bd9Sstevel@tonic-gate * which is bumped each time a kstat is added or deleted. /dev/kstat uses 183*7c478bd9Sstevel@tonic-gate * the chain ID to detect changes in the kstat chain (e.g., a new disk 184*7c478bd9Sstevel@tonic-gate * coming online) between ioctl()s. 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * kstat module, kstat instance 189*7c478bd9Sstevel@tonic-gate * 190*7c478bd9Sstevel@tonic-gate * ks_module and ks_instance contain the name and instance of the module 191*7c478bd9Sstevel@tonic-gate * that created the kstat. In cases where there can only be one instance, 192*7c478bd9Sstevel@tonic-gate * ks_instance is 0. The kernel proper (/kernel/unix) uses "unix" as its 193*7c478bd9Sstevel@tonic-gate * module name. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* 197*7c478bd9Sstevel@tonic-gate * kstat name 198*7c478bd9Sstevel@tonic-gate * 199*7c478bd9Sstevel@tonic-gate * ks_name gives a meaningful name to a kstat. The full kstat namespace 200*7c478bd9Sstevel@tonic-gate * is module.instance.name, so the name only need be unique within a 201*7c478bd9Sstevel@tonic-gate * module. kstat_create() will fail if you try to create a kstat with 202*7c478bd9Sstevel@tonic-gate * an already-used (ks_module, ks_instance, ks_name) triplet. Spaces are 203*7c478bd9Sstevel@tonic-gate * allowed in kstat names, but strongly discouraged, since they hinder 204*7c478bd9Sstevel@tonic-gate * awk-style processing at user level. 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate * kstat type 209*7c478bd9Sstevel@tonic-gate * 210*7c478bd9Sstevel@tonic-gate * The kstat mechanism provides several flavors of kstat data, defined 211*7c478bd9Sstevel@tonic-gate * below. The "raw" kstat type is just treated as an array of bytes; you 212*7c478bd9Sstevel@tonic-gate * can use this to export any kind of data you want. 213*7c478bd9Sstevel@tonic-gate * 214*7c478bd9Sstevel@tonic-gate * Some kstat types allow multiple data structures per kstat, e.g. 215*7c478bd9Sstevel@tonic-gate * KSTAT_TYPE_NAMED; others do not. This is part of the spec for each 216*7c478bd9Sstevel@tonic-gate * kstat data type. 217*7c478bd9Sstevel@tonic-gate * 218*7c478bd9Sstevel@tonic-gate * User-level tools should *not* rely on the #define KSTAT_NUM_TYPES. To 219*7c478bd9Sstevel@tonic-gate * get this information, read out the standard system kstat "kstat_types". 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate #define KSTAT_TYPE_RAW 0 /* can be anything */ 223*7c478bd9Sstevel@tonic-gate /* ks_ndata >= 1 */ 224*7c478bd9Sstevel@tonic-gate #define KSTAT_TYPE_NAMED 1 /* name/value pair */ 225*7c478bd9Sstevel@tonic-gate /* ks_ndata >= 1 */ 226*7c478bd9Sstevel@tonic-gate #define KSTAT_TYPE_INTR 2 /* interrupt statistics */ 227*7c478bd9Sstevel@tonic-gate /* ks_ndata == 1 */ 228*7c478bd9Sstevel@tonic-gate #define KSTAT_TYPE_IO 3 /* I/O statistics */ 229*7c478bd9Sstevel@tonic-gate /* ks_ndata == 1 */ 230*7c478bd9Sstevel@tonic-gate #define KSTAT_TYPE_TIMER 4 /* event timer */ 231*7c478bd9Sstevel@tonic-gate /* ks_ndata >= 1 */ 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate #define KSTAT_NUM_TYPES 5 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * kstat class 237*7c478bd9Sstevel@tonic-gate * 238*7c478bd9Sstevel@tonic-gate * Each kstat can be characterized as belonging to some broad class 239*7c478bd9Sstevel@tonic-gate * of statistics, e.g. disk, tape, net, vm, streams, etc. This field 240*7c478bd9Sstevel@tonic-gate * can be used as a filter to extract related kstats. The following 241*7c478bd9Sstevel@tonic-gate * values are currently in use: disk, tape, net, controller, vm, kvm, 242*7c478bd9Sstevel@tonic-gate * hat, streams, kstat, and misc. (The kstat class encompasses things 243*7c478bd9Sstevel@tonic-gate * like kstat_types.) 244*7c478bd9Sstevel@tonic-gate */ 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * kstat flags 248*7c478bd9Sstevel@tonic-gate * 249*7c478bd9Sstevel@tonic-gate * Any of the following flags may be passed to kstat_create(). They are 250*7c478bd9Sstevel@tonic-gate * all zero by default. 251*7c478bd9Sstevel@tonic-gate * 252*7c478bd9Sstevel@tonic-gate * KSTAT_FLAG_VIRTUAL: 253*7c478bd9Sstevel@tonic-gate * 254*7c478bd9Sstevel@tonic-gate * Tells kstat_create() not to allocate memory for the 255*7c478bd9Sstevel@tonic-gate * kstat data section; instead, you will set the ks_data 256*7c478bd9Sstevel@tonic-gate * field to point to the data you wish to export. This 257*7c478bd9Sstevel@tonic-gate * provides a convenient way to export existing data 258*7c478bd9Sstevel@tonic-gate * structures. 259*7c478bd9Sstevel@tonic-gate * 260*7c478bd9Sstevel@tonic-gate * KSTAT_FLAG_VAR_SIZE: 261*7c478bd9Sstevel@tonic-gate * 262*7c478bd9Sstevel@tonic-gate * The size of the kstat you are creating will vary over time. 263*7c478bd9Sstevel@tonic-gate * For example, you may want to use the kstat mechanism to 264*7c478bd9Sstevel@tonic-gate * export a linked list. NOTE: The kstat framework does not 265*7c478bd9Sstevel@tonic-gate * manage the data section, so all variable-size kstats must be 266*7c478bd9Sstevel@tonic-gate * virtual kstats. Moreover, variable-size kstats MUST employ 267*7c478bd9Sstevel@tonic-gate * kstat data locking to prevent data-size races with kstat 268*7c478bd9Sstevel@tonic-gate * clients. See the section on "kstat snapshot" for details. 269*7c478bd9Sstevel@tonic-gate * 270*7c478bd9Sstevel@tonic-gate * KSTAT_FLAG_WRITABLE: 271*7c478bd9Sstevel@tonic-gate * 272*7c478bd9Sstevel@tonic-gate * Makes the kstat's data section writable by root. 273*7c478bd9Sstevel@tonic-gate * The ks_snapshot routine (see below) does not need to check for 274*7c478bd9Sstevel@tonic-gate * this; permission checking is handled in the kstat driver. 275*7c478bd9Sstevel@tonic-gate * 276*7c478bd9Sstevel@tonic-gate * KSTAT_FLAG_PERSISTENT: 277*7c478bd9Sstevel@tonic-gate * 278*7c478bd9Sstevel@tonic-gate * Indicates that this kstat is to be persistent over time. 279*7c478bd9Sstevel@tonic-gate * For persistent kstats, kstat_delete() simply marks the 280*7c478bd9Sstevel@tonic-gate * kstat as dormant; a subsequent kstat_create() reactivates 281*7c478bd9Sstevel@tonic-gate * the kstat. This feature is provided so that statistics 282*7c478bd9Sstevel@tonic-gate * are not lost across driver close/open (e.g., raw disk I/O 283*7c478bd9Sstevel@tonic-gate * on a disk with no mounted partitions.) 284*7c478bd9Sstevel@tonic-gate * NOTE: Persistent kstats cannot be virtual, since ks_data 285*7c478bd9Sstevel@tonic-gate * points to garbage as soon as the driver goes away. 286*7c478bd9Sstevel@tonic-gate * 287*7c478bd9Sstevel@tonic-gate * The following flags are maintained by the kstat framework: 288*7c478bd9Sstevel@tonic-gate * 289*7c478bd9Sstevel@tonic-gate * KSTAT_FLAG_DORMANT: 290*7c478bd9Sstevel@tonic-gate * 291*7c478bd9Sstevel@tonic-gate * For persistent kstats, indicates that the kstat is in the 292*7c478bd9Sstevel@tonic-gate * dormant state (e.g., the corresponding device is closed). 293*7c478bd9Sstevel@tonic-gate * 294*7c478bd9Sstevel@tonic-gate * KSTAT_FLAG_INVALID: 295*7c478bd9Sstevel@tonic-gate * 296*7c478bd9Sstevel@tonic-gate * This flag is set when a kstat is in a transitional state, 297*7c478bd9Sstevel@tonic-gate * e.g. between kstat_create() and kstat_install(). 298*7c478bd9Sstevel@tonic-gate * kstat clients must not attempt to access the kstat's data 299*7c478bd9Sstevel@tonic-gate * if this flag is set. 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate #define KSTAT_FLAG_VIRTUAL 0x01 303*7c478bd9Sstevel@tonic-gate #define KSTAT_FLAG_VAR_SIZE 0x02 304*7c478bd9Sstevel@tonic-gate #define KSTAT_FLAG_WRITABLE 0x04 305*7c478bd9Sstevel@tonic-gate #define KSTAT_FLAG_PERSISTENT 0x08 306*7c478bd9Sstevel@tonic-gate #define KSTAT_FLAG_DORMANT 0x10 307*7c478bd9Sstevel@tonic-gate #define KSTAT_FLAG_INVALID 0x20 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* 310*7c478bd9Sstevel@tonic-gate * Dynamic update support 311*7c478bd9Sstevel@tonic-gate * 312*7c478bd9Sstevel@tonic-gate * The kstat mechanism allows for an optional ks_update function to update 313*7c478bd9Sstevel@tonic-gate * kstat data. This is useful for drivers where the underlying device 314*7c478bd9Sstevel@tonic-gate * keeps cheap hardware stats, but extraction is expensive. Instead of 315*7c478bd9Sstevel@tonic-gate * constantly keeping the kstat data section up to date, you can supply a 316*7c478bd9Sstevel@tonic-gate * ks_update function which updates the kstat's data section on demand. 317*7c478bd9Sstevel@tonic-gate * To take advantage of this feature, simply set the ks_update field before 318*7c478bd9Sstevel@tonic-gate * calling kstat_install(). 319*7c478bd9Sstevel@tonic-gate * 320*7c478bd9Sstevel@tonic-gate * The ks_update function, if supplied, must have the following structure: 321*7c478bd9Sstevel@tonic-gate * 322*7c478bd9Sstevel@tonic-gate * int 323*7c478bd9Sstevel@tonic-gate * foo_kstat_update(kstat_t *ksp, int rw) 324*7c478bd9Sstevel@tonic-gate * { 325*7c478bd9Sstevel@tonic-gate * if (rw == KSTAT_WRITE) { 326*7c478bd9Sstevel@tonic-gate * ... update the native stats from ksp->ks_data; 327*7c478bd9Sstevel@tonic-gate * return EACCES if you don't support this 328*7c478bd9Sstevel@tonic-gate * } else { 329*7c478bd9Sstevel@tonic-gate * ... update ksp->ks_data from the native stats 330*7c478bd9Sstevel@tonic-gate * } 331*7c478bd9Sstevel@tonic-gate * } 332*7c478bd9Sstevel@tonic-gate * 333*7c478bd9Sstevel@tonic-gate * The ks_update return codes are: 0 for success, EACCES if you don't allow 334*7c478bd9Sstevel@tonic-gate * KSTAT_WRITE, and EIO for any other type of error. 335*7c478bd9Sstevel@tonic-gate * 336*7c478bd9Sstevel@tonic-gate * In general, the ks_update function may need to refer to provider-private 337*7c478bd9Sstevel@tonic-gate * data; for example, it may need a pointer to the provider's raw statistics. 338*7c478bd9Sstevel@tonic-gate * The ks_private field is available for this purpose. Its use is entirely 339*7c478bd9Sstevel@tonic-gate * at the provider's discretion. 340*7c478bd9Sstevel@tonic-gate * 341*7c478bd9Sstevel@tonic-gate * All variable-size kstats MUST supply a ks_update routine, which computes 342*7c478bd9Sstevel@tonic-gate * and sets ks_data_size (and ks_ndata if that is meaningful), since these 343*7c478bd9Sstevel@tonic-gate * are needed to perform kstat snapshots (see below). 344*7c478bd9Sstevel@tonic-gate * 345*7c478bd9Sstevel@tonic-gate * No kstat locking should be done inside the ks_update routine. The caller 346*7c478bd9Sstevel@tonic-gate * will already be holding the kstat's ks_lock (to ensure consistent data). 347*7c478bd9Sstevel@tonic-gate */ 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate #define KSTAT_READ 0 350*7c478bd9Sstevel@tonic-gate #define KSTAT_WRITE 1 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Kstat snapshot 354*7c478bd9Sstevel@tonic-gate * 355*7c478bd9Sstevel@tonic-gate * In order to get a consistent view of a kstat's data, clients must obey 356*7c478bd9Sstevel@tonic-gate * the kstat's locking strategy. However, these clients may need to perform 357*7c478bd9Sstevel@tonic-gate * operations on the data which could cause a fault (e.g. copyout()), or 358*7c478bd9Sstevel@tonic-gate * operations which are simply expensive. Doing so could cause deadlock 359*7c478bd9Sstevel@tonic-gate * (e.g. if you're holding a disk's kstat lock which is ultimately required 360*7c478bd9Sstevel@tonic-gate * to resolve a copyout() fault), performance degradation (since the providers' 361*7c478bd9Sstevel@tonic-gate * activity is serialized at the kstat lock), device timing problems, etc. 362*7c478bd9Sstevel@tonic-gate * 363*7c478bd9Sstevel@tonic-gate * To avoid these problems, kstat data is provided via snapshots. Taking 364*7c478bd9Sstevel@tonic-gate * a snapshot is a simple process: allocate a wired-down kernel buffer, 365*7c478bd9Sstevel@tonic-gate * acquire the kstat's data lock, copy the data into the buffer ("take the 366*7c478bd9Sstevel@tonic-gate * snapshot"), and release the lock. This ensures that the kstat's data lock 367*7c478bd9Sstevel@tonic-gate * will be held as briefly as possible, and that no faults will occur while 368*7c478bd9Sstevel@tonic-gate * the lock is held. 369*7c478bd9Sstevel@tonic-gate * 370*7c478bd9Sstevel@tonic-gate * Normally, the snapshot is taken by default_kstat_snapshot(), which 371*7c478bd9Sstevel@tonic-gate * timestamps the data (sets ks_snaptime), copies it, and does a little 372*7c478bd9Sstevel@tonic-gate * massaging to deal with incomplete transactions on i/o kstats. However, 373*7c478bd9Sstevel@tonic-gate * this routine only works for kstats with contiguous data (the typical case). 374*7c478bd9Sstevel@tonic-gate * If you create a kstat whose data is, say, a linked list, you must provide 375*7c478bd9Sstevel@tonic-gate * your own ks_snapshot routine. The routine you supply must have the 376*7c478bd9Sstevel@tonic-gate * following prototype (replace "foo" with something appropriate): 377*7c478bd9Sstevel@tonic-gate * 378*7c478bd9Sstevel@tonic-gate * int foo_kstat_snapshot(kstat_t *ksp, void *buf, int rw); 379*7c478bd9Sstevel@tonic-gate * 380*7c478bd9Sstevel@tonic-gate * The minimal snapshot routine -- one which copies contiguous data that 381*7c478bd9Sstevel@tonic-gate * doesn't need any massaging -- would be this: 382*7c478bd9Sstevel@tonic-gate * 383*7c478bd9Sstevel@tonic-gate * ksp->ks_snaptime = gethrtime(); 384*7c478bd9Sstevel@tonic-gate * if (rw == KSTAT_WRITE) 385*7c478bd9Sstevel@tonic-gate * bcopy(buf, ksp->ks_data, ksp->ks_data_size); 386*7c478bd9Sstevel@tonic-gate * else 387*7c478bd9Sstevel@tonic-gate * bcopy(ksp->ks_data, buf, ksp->ks_data_size); 388*7c478bd9Sstevel@tonic-gate * return (0); 389*7c478bd9Sstevel@tonic-gate * 390*7c478bd9Sstevel@tonic-gate * A more illuminating example is taking a snapshot of a linked list: 391*7c478bd9Sstevel@tonic-gate * 392*7c478bd9Sstevel@tonic-gate * ksp->ks_snaptime = gethrtime(); 393*7c478bd9Sstevel@tonic-gate * if (rw == KSTAT_WRITE) 394*7c478bd9Sstevel@tonic-gate * return (EACCES); ... See below ... 395*7c478bd9Sstevel@tonic-gate * for (foo = first_foo; foo; foo = foo->next) { 396*7c478bd9Sstevel@tonic-gate * bcopy((char *) foo, (char *) buf, sizeof (struct foo)); 397*7c478bd9Sstevel@tonic-gate * buf = ((struct foo *) buf) + 1; 398*7c478bd9Sstevel@tonic-gate * } 399*7c478bd9Sstevel@tonic-gate * return (0); 400*7c478bd9Sstevel@tonic-gate * 401*7c478bd9Sstevel@tonic-gate * In the example above, we have decided that we don't want to allow 402*7c478bd9Sstevel@tonic-gate * KSTAT_WRITE access, so we return EACCES if this is attempted. 403*7c478bd9Sstevel@tonic-gate * 404*7c478bd9Sstevel@tonic-gate * The key points are: 405*7c478bd9Sstevel@tonic-gate * 406*7c478bd9Sstevel@tonic-gate * (1) ks_snaptime must be set (via gethrtime()) to timestamp the data. 407*7c478bd9Sstevel@tonic-gate * (2) Data gets copied from the kstat to the buffer on KSTAT_READ, 408*7c478bd9Sstevel@tonic-gate * and from the buffer to the kstat on KSTAT_WRITE. 409*7c478bd9Sstevel@tonic-gate * (3) ks_snapshot return values are: 0 for success, EACCES if you 410*7c478bd9Sstevel@tonic-gate * don't allow KSTAT_WRITE, and EIO for any other type of error. 411*7c478bd9Sstevel@tonic-gate * 412*7c478bd9Sstevel@tonic-gate * Named kstats (see section on "Named statistics" below) containing long 413*7c478bd9Sstevel@tonic-gate * strings (KSTAT_DATA_STRING) need special handling. The kstat driver 414*7c478bd9Sstevel@tonic-gate * assumes that all strings are copied into the buffer after the array of 415*7c478bd9Sstevel@tonic-gate * named kstats, and the pointers (KSTAT_NAMED_STR_PTR()) are updated to point 416*7c478bd9Sstevel@tonic-gate * into the copy within the buffer. The default snapshot routine does this, 417*7c478bd9Sstevel@tonic-gate * but overriding routines should contain at least the following: 418*7c478bd9Sstevel@tonic-gate * 419*7c478bd9Sstevel@tonic-gate * if (rw == KSTAT_READ) { 420*7c478bd9Sstevel@tonic-gate * kstat_named_t *knp = buf; 421*7c478bd9Sstevel@tonic-gate * char *end = knp + ksp->ks_ndata; 422*7c478bd9Sstevel@tonic-gate * uint_t i; 423*7c478bd9Sstevel@tonic-gate * 424*7c478bd9Sstevel@tonic-gate * ... Do the regular copy ... 425*7c478bd9Sstevel@tonic-gate * bcopy(ksp->ks_data, buf, sizeof (kstat_named_t) * ksp->ks_ndata); 426*7c478bd9Sstevel@tonic-gate * 427*7c478bd9Sstevel@tonic-gate * for (i = 0; i < ksp->ks_ndata; i++, knp++) { 428*7c478bd9Sstevel@tonic-gate * if (knp[i].data_type == KSTAT_DATA_STRING && 429*7c478bd9Sstevel@tonic-gate * KSTAT_NAMED_STR_PTR(knp) != NULL) { 430*7c478bd9Sstevel@tonic-gate * bcopy(KSTAT_NAMED_STR_PTR(knp), end, 431*7c478bd9Sstevel@tonic-gate * KSTAT_NAMED_STR_BUFLEN(knp)); 432*7c478bd9Sstevel@tonic-gate * KSTAT_NAMED_STR_PTR(knp) = end; 433*7c478bd9Sstevel@tonic-gate * end += KSTAT_NAMED_STR_BUFLEN(knp); 434*7c478bd9Sstevel@tonic-gate * } 435*7c478bd9Sstevel@tonic-gate * } 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /* 439*7c478bd9Sstevel@tonic-gate * Named statistics. 440*7c478bd9Sstevel@tonic-gate * 441*7c478bd9Sstevel@tonic-gate * List of arbitrary name=value statistics. 442*7c478bd9Sstevel@tonic-gate */ 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate typedef struct kstat_named { 445*7c478bd9Sstevel@tonic-gate char name[KSTAT_STRLEN]; /* name of counter */ 446*7c478bd9Sstevel@tonic-gate uchar_t data_type; /* data type */ 447*7c478bd9Sstevel@tonic-gate union { 448*7c478bd9Sstevel@tonic-gate char c[16]; /* enough for 128-bit ints */ 449*7c478bd9Sstevel@tonic-gate int32_t i32; 450*7c478bd9Sstevel@tonic-gate uint32_t ui32; 451*7c478bd9Sstevel@tonic-gate struct { 452*7c478bd9Sstevel@tonic-gate union { 453*7c478bd9Sstevel@tonic-gate char *ptr; /* NULL-term string */ 454*7c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && defined(_MULTI_DATAMODEL) 455*7c478bd9Sstevel@tonic-gate caddr32_t ptr32; 456*7c478bd9Sstevel@tonic-gate #endif 457*7c478bd9Sstevel@tonic-gate char __pad[8]; /* 64-bit padding */ 458*7c478bd9Sstevel@tonic-gate } addr; 459*7c478bd9Sstevel@tonic-gate uint32_t len; /* # bytes for strlen + '\0' */ 460*7c478bd9Sstevel@tonic-gate } string; 461*7c478bd9Sstevel@tonic-gate /* 462*7c478bd9Sstevel@tonic-gate * The int64_t and uint64_t types are not valid for a maximally conformant 463*7c478bd9Sstevel@tonic-gate * 32-bit compilation environment (cc -Xc) using compilers prior to the 464*7c478bd9Sstevel@tonic-gate * introduction of C99 conforming compiler (reference ISO/IEC 9899:1990). 465*7c478bd9Sstevel@tonic-gate * In these cases, the visibility of i64 and ui64 is only permitted for 466*7c478bd9Sstevel@tonic-gate * 64-bit compilation environments or 32-bit non-maximally conformant 467*7c478bd9Sstevel@tonic-gate * C89 or C90 ANSI C compilation environments (cc -Xt and cc -Xa). In the 468*7c478bd9Sstevel@tonic-gate * C99 ANSI C compilation environment, the long long type is supported. 469*7c478bd9Sstevel@tonic-gate * The _INT64_TYPE is defined by the implementation (see sys/int_types.h). 470*7c478bd9Sstevel@tonic-gate */ 471*7c478bd9Sstevel@tonic-gate #if defined(_INT64_TYPE) 472*7c478bd9Sstevel@tonic-gate int64_t i64; 473*7c478bd9Sstevel@tonic-gate uint64_t ui64; 474*7c478bd9Sstevel@tonic-gate #endif 475*7c478bd9Sstevel@tonic-gate long l; 476*7c478bd9Sstevel@tonic-gate ulong_t ul; 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate /* These structure members are obsolete */ 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate longlong_t ll; 481*7c478bd9Sstevel@tonic-gate u_longlong_t ull; 482*7c478bd9Sstevel@tonic-gate float f; 483*7c478bd9Sstevel@tonic-gate double d; 484*7c478bd9Sstevel@tonic-gate } value; /* value of counter */ 485*7c478bd9Sstevel@tonic-gate } kstat_named_t; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_CHAR 0 488*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_INT32 1 489*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_UINT32 2 490*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_INT64 3 491*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_UINT64 4 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate #if !defined(_LP64) 494*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_LONG KSTAT_DATA_INT32 495*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_ULONG KSTAT_DATA_UINT32 496*7c478bd9Sstevel@tonic-gate #else 497*7c478bd9Sstevel@tonic-gate #if !defined(_KERNEL) 498*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_LONG KSTAT_DATA_INT64 499*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_ULONG KSTAT_DATA_UINT64 500*7c478bd9Sstevel@tonic-gate #else 501*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_LONG 7 /* only visible to the kernel */ 502*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_ULONG 8 /* only visible to the kernel */ 503*7c478bd9Sstevel@tonic-gate #endif /* !_KERNEL */ 504*7c478bd9Sstevel@tonic-gate #endif /* !_LP64 */ 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate /* 507*7c478bd9Sstevel@tonic-gate * Statistics exporting named kstats with long strings (KSTAT_DATA_STRING) 508*7c478bd9Sstevel@tonic-gate * may not make the assumption that ks_data_size is equal to (ks_ndata * sizeof 509*7c478bd9Sstevel@tonic-gate * (kstat_named_t)). ks_data_size in these cases is equal to the sum of the 510*7c478bd9Sstevel@tonic-gate * amount of space required to store the strings (ie, the sum of 511*7c478bd9Sstevel@tonic-gate * KSTAT_NAMED_STR_BUFLEN() for all KSTAT_DATA_STRING statistics) plus the 512*7c478bd9Sstevel@tonic-gate * space required to store the kstat_named_t's. 513*7c478bd9Sstevel@tonic-gate * 514*7c478bd9Sstevel@tonic-gate * The default update routine will update ks_data_size automatically for 515*7c478bd9Sstevel@tonic-gate * variable-length kstats containing long strings (using the default update 516*7c478bd9Sstevel@tonic-gate * routine only makes sense if the string is the only thing that is changing 517*7c478bd9Sstevel@tonic-gate * in size, and ks_ndata is constant). Fixed-length kstats containing long 518*7c478bd9Sstevel@tonic-gate * strings must explicitly change ks_data_size (after creation but before 519*7c478bd9Sstevel@tonic-gate * initialization) to reflect the correct amount of space required for the 520*7c478bd9Sstevel@tonic-gate * long strings and the kstat_named_t's. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_STRING 9 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate /* These types are obsolete */ 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_LONGLONG KSTAT_DATA_INT64 527*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_ULONGLONG KSTAT_DATA_UINT64 528*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_FLOAT 5 529*7c478bd9Sstevel@tonic-gate #define KSTAT_DATA_DOUBLE 6 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate #define KSTAT_NAMED_PTR(kptr) ((kstat_named_t *)(kptr)->ks_data) 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate /* 534*7c478bd9Sstevel@tonic-gate * Retrieve the pointer of the string contained in the given named kstat. 535*7c478bd9Sstevel@tonic-gate */ 536*7c478bd9Sstevel@tonic-gate #define KSTAT_NAMED_STR_PTR(knptr) ((knptr)->value.string.addr.ptr) 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate /* 539*7c478bd9Sstevel@tonic-gate * Retrieve the length of the buffer required to store the string in the given 540*7c478bd9Sstevel@tonic-gate * named kstat. 541*7c478bd9Sstevel@tonic-gate */ 542*7c478bd9Sstevel@tonic-gate #define KSTAT_NAMED_STR_BUFLEN(knptr) ((knptr)->value.string.len) 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate /* 545*7c478bd9Sstevel@tonic-gate * Interrupt statistics. 546*7c478bd9Sstevel@tonic-gate * 547*7c478bd9Sstevel@tonic-gate * An interrupt is a hard interrupt (sourced from the hardware device 548*7c478bd9Sstevel@tonic-gate * itself), a soft interrupt (induced by the system via the use of 549*7c478bd9Sstevel@tonic-gate * some system interrupt source), a watchdog interrupt (induced by 550*7c478bd9Sstevel@tonic-gate * a periodic timer call), spurious (an interrupt entry point was 551*7c478bd9Sstevel@tonic-gate * entered but there was no interrupt condition to service), 552*7c478bd9Sstevel@tonic-gate * or multiple service (an interrupt condition was detected and 553*7c478bd9Sstevel@tonic-gate * serviced just prior to returning from any of the other types). 554*7c478bd9Sstevel@tonic-gate * 555*7c478bd9Sstevel@tonic-gate * Measurement of the spurious class of interrupts is useful for 556*7c478bd9Sstevel@tonic-gate * autovectored devices in order to pinpoint any interrupt latency 557*7c478bd9Sstevel@tonic-gate * problems in a particular system configuration. 558*7c478bd9Sstevel@tonic-gate * 559*7c478bd9Sstevel@tonic-gate * Devices that have more than one interrupt of the same 560*7c478bd9Sstevel@tonic-gate * type should use multiple structures. 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate #define KSTAT_INTR_HARD 0 564*7c478bd9Sstevel@tonic-gate #define KSTAT_INTR_SOFT 1 565*7c478bd9Sstevel@tonic-gate #define KSTAT_INTR_WATCHDOG 2 566*7c478bd9Sstevel@tonic-gate #define KSTAT_INTR_SPURIOUS 3 567*7c478bd9Sstevel@tonic-gate #define KSTAT_INTR_MULTSVC 4 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate #define KSTAT_NUM_INTRS 5 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate typedef struct kstat_intr { 572*7c478bd9Sstevel@tonic-gate uint_t intrs[KSTAT_NUM_INTRS]; /* interrupt counters */ 573*7c478bd9Sstevel@tonic-gate } kstat_intr_t; 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate #define KSTAT_INTR_PTR(kptr) ((kstat_intr_t *)(kptr)->ks_data) 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate /* 578*7c478bd9Sstevel@tonic-gate * I/O statistics. 579*7c478bd9Sstevel@tonic-gate */ 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate typedef struct kstat_io { 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate /* 584*7c478bd9Sstevel@tonic-gate * Basic counters. 585*7c478bd9Sstevel@tonic-gate * 586*7c478bd9Sstevel@tonic-gate * The counters should be updated at the end of service 587*7c478bd9Sstevel@tonic-gate * (e.g., just prior to calling biodone()). 588*7c478bd9Sstevel@tonic-gate */ 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate u_longlong_t nread; /* number of bytes read */ 591*7c478bd9Sstevel@tonic-gate u_longlong_t nwritten; /* number of bytes written */ 592*7c478bd9Sstevel@tonic-gate uint_t reads; /* number of read operations */ 593*7c478bd9Sstevel@tonic-gate uint_t writes; /* number of write operations */ 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate /* 596*7c478bd9Sstevel@tonic-gate * Accumulated time and queue length statistics. 597*7c478bd9Sstevel@tonic-gate * 598*7c478bd9Sstevel@tonic-gate * Accumulated time statistics are kept as a running sum 599*7c478bd9Sstevel@tonic-gate * of "active" time. Queue length statistics are kept as a 600*7c478bd9Sstevel@tonic-gate * running sum of the product of queue length and elapsed time 601*7c478bd9Sstevel@tonic-gate * at that length -- i.e., a Riemann sum for queue length 602*7c478bd9Sstevel@tonic-gate * integrated against time. (You can also think of the active time 603*7c478bd9Sstevel@tonic-gate * as a Riemann sum, for the boolean function (queue_length > 0) 604*7c478bd9Sstevel@tonic-gate * integrated against time, or you can think of it as the 605*7c478bd9Sstevel@tonic-gate * Lebesgue measure of the set on which queue_length > 0.) 606*7c478bd9Sstevel@tonic-gate * 607*7c478bd9Sstevel@tonic-gate * ^ 608*7c478bd9Sstevel@tonic-gate * | _________ 609*7c478bd9Sstevel@tonic-gate * 8 | i4 | 610*7c478bd9Sstevel@tonic-gate * | | | 611*7c478bd9Sstevel@tonic-gate * Queue 6 | | 612*7c478bd9Sstevel@tonic-gate * Length | _________ | | 613*7c478bd9Sstevel@tonic-gate * 4 | i2 |_______| | 614*7c478bd9Sstevel@tonic-gate * | | i3 | 615*7c478bd9Sstevel@tonic-gate * 2_______| | 616*7c478bd9Sstevel@tonic-gate * | i1 | 617*7c478bd9Sstevel@tonic-gate * |_______________________________| 618*7c478bd9Sstevel@tonic-gate * Time-> t1 t2 t3 t4 619*7c478bd9Sstevel@tonic-gate * 620*7c478bd9Sstevel@tonic-gate * At each change of state (entry or exit from the queue), 621*7c478bd9Sstevel@tonic-gate * we add the elapsed time (since the previous state change) 622*7c478bd9Sstevel@tonic-gate * to the active time if the queue length was non-zero during 623*7c478bd9Sstevel@tonic-gate * that interval; and we add the product of the elapsed time 624*7c478bd9Sstevel@tonic-gate * times the queue length to the running length*time sum. 625*7c478bd9Sstevel@tonic-gate * 626*7c478bd9Sstevel@tonic-gate * This method is generalizable to measuring residency 627*7c478bd9Sstevel@tonic-gate * in any defined system: instead of queue lengths, think 628*7c478bd9Sstevel@tonic-gate * of "outstanding RPC calls to server X". 629*7c478bd9Sstevel@tonic-gate * 630*7c478bd9Sstevel@tonic-gate * A large number of I/O subsystems have at least two basic 631*7c478bd9Sstevel@tonic-gate * "lists" of transactions they manage: one for transactions 632*7c478bd9Sstevel@tonic-gate * that have been accepted for processing but for which processing 633*7c478bd9Sstevel@tonic-gate * has yet to begin, and one for transactions which are actively 634*7c478bd9Sstevel@tonic-gate * being processed (but not done). For this reason, two cumulative 635*7c478bd9Sstevel@tonic-gate * time statistics are defined here: wait (pre-service) time, 636*7c478bd9Sstevel@tonic-gate * and run (service) time. 637*7c478bd9Sstevel@tonic-gate * 638*7c478bd9Sstevel@tonic-gate * All times are 64-bit nanoseconds (hrtime_t), as returned by 639*7c478bd9Sstevel@tonic-gate * gethrtime(). 640*7c478bd9Sstevel@tonic-gate * 641*7c478bd9Sstevel@tonic-gate * The units of cumulative busy time are accumulated nanoseconds. 642*7c478bd9Sstevel@tonic-gate * The units of cumulative length*time products are elapsed time 643*7c478bd9Sstevel@tonic-gate * times queue length. 644*7c478bd9Sstevel@tonic-gate * 645*7c478bd9Sstevel@tonic-gate * Updates to the fields below are performed implicitly by calls to 646*7c478bd9Sstevel@tonic-gate * these five functions: 647*7c478bd9Sstevel@tonic-gate * 648*7c478bd9Sstevel@tonic-gate * kstat_waitq_enter() 649*7c478bd9Sstevel@tonic-gate * kstat_waitq_exit() 650*7c478bd9Sstevel@tonic-gate * kstat_runq_enter() 651*7c478bd9Sstevel@tonic-gate * kstat_runq_exit() 652*7c478bd9Sstevel@tonic-gate * 653*7c478bd9Sstevel@tonic-gate * kstat_waitq_to_runq() (see below) 654*7c478bd9Sstevel@tonic-gate * kstat_runq_back_to_waitq() (see below) 655*7c478bd9Sstevel@tonic-gate * 656*7c478bd9Sstevel@tonic-gate * Since kstat_waitq_exit() is typically followed immediately 657*7c478bd9Sstevel@tonic-gate * by kstat_runq_enter(), there is a single kstat_waitq_to_runq() 658*7c478bd9Sstevel@tonic-gate * function which performs both operations. This is a performance 659*7c478bd9Sstevel@tonic-gate * win since only one timestamp is required. 660*7c478bd9Sstevel@tonic-gate * 661*7c478bd9Sstevel@tonic-gate * In some instances, it may be necessary to move a request from 662*7c478bd9Sstevel@tonic-gate * the run queue back to the wait queue, e.g. for write throttling. 663*7c478bd9Sstevel@tonic-gate * For these situations, call kstat_runq_back_to_waitq(). 664*7c478bd9Sstevel@tonic-gate * 665*7c478bd9Sstevel@tonic-gate * These fields should never be updated by any other means. 666*7c478bd9Sstevel@tonic-gate */ 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate hrtime_t wtime; /* cumulative wait (pre-service) time */ 669*7c478bd9Sstevel@tonic-gate hrtime_t wlentime; /* cumulative wait length*time product */ 670*7c478bd9Sstevel@tonic-gate hrtime_t wlastupdate; /* last time wait queue changed */ 671*7c478bd9Sstevel@tonic-gate hrtime_t rtime; /* cumulative run (service) time */ 672*7c478bd9Sstevel@tonic-gate hrtime_t rlentime; /* cumulative run length*time product */ 673*7c478bd9Sstevel@tonic-gate hrtime_t rlastupdate; /* last time run queue changed */ 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate uint_t wcnt; /* count of elements in wait state */ 676*7c478bd9Sstevel@tonic-gate uint_t rcnt; /* count of elements in run state */ 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate } kstat_io_t; 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate #define KSTAT_IO_PTR(kptr) ((kstat_io_t *)(kptr)->ks_data) 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate /* 683*7c478bd9Sstevel@tonic-gate * Event timer statistics - cumulative elapsed time and number of events. 684*7c478bd9Sstevel@tonic-gate * 685*7c478bd9Sstevel@tonic-gate * Updates to these fields are performed implicitly by calls to 686*7c478bd9Sstevel@tonic-gate * kstat_timer_start() and kstat_timer_stop(). 687*7c478bd9Sstevel@tonic-gate */ 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate typedef struct kstat_timer { 690*7c478bd9Sstevel@tonic-gate char name[KSTAT_STRLEN]; /* event name */ 691*7c478bd9Sstevel@tonic-gate uchar_t resv; /* reserved */ 692*7c478bd9Sstevel@tonic-gate u_longlong_t num_events; /* number of events */ 693*7c478bd9Sstevel@tonic-gate hrtime_t elapsed_time; /* cumulative elapsed time */ 694*7c478bd9Sstevel@tonic-gate hrtime_t min_time; /* shortest event duration */ 695*7c478bd9Sstevel@tonic-gate hrtime_t max_time; /* longest event duration */ 696*7c478bd9Sstevel@tonic-gate hrtime_t start_time; /* previous event start time */ 697*7c478bd9Sstevel@tonic-gate hrtime_t stop_time; /* previous event stop time */ 698*7c478bd9Sstevel@tonic-gate } kstat_timer_t; 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate #define KSTAT_TIMER_PTR(kptr) ((kstat_timer_t *)(kptr)->ks_data) 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate #if defined(_KERNEL) 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate extern kid_t kstat_chain_id; /* bumped at each state change */ 707*7c478bd9Sstevel@tonic-gate extern void kstat_init(void); /* initialize kstat framework */ 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate /* 710*7c478bd9Sstevel@tonic-gate * Adding and deleting kstats. 711*7c478bd9Sstevel@tonic-gate * 712*7c478bd9Sstevel@tonic-gate * The typical sequence to add a kstat is: 713*7c478bd9Sstevel@tonic-gate * 714*7c478bd9Sstevel@tonic-gate * ksp = kstat_create(module, instance, name, class, type, ndata, flags); 715*7c478bd9Sstevel@tonic-gate * if (ksp) { 716*7c478bd9Sstevel@tonic-gate * ... provider initialization, if necessary 717*7c478bd9Sstevel@tonic-gate * kstat_install(ksp); 718*7c478bd9Sstevel@tonic-gate * } 719*7c478bd9Sstevel@tonic-gate * 720*7c478bd9Sstevel@tonic-gate * There are three logically distinct steps here: 721*7c478bd9Sstevel@tonic-gate * 722*7c478bd9Sstevel@tonic-gate * Step 1: System Initialization (kstat_create) 723*7c478bd9Sstevel@tonic-gate * 724*7c478bd9Sstevel@tonic-gate * kstat_create() performs system initialization. kstat_create() 725*7c478bd9Sstevel@tonic-gate * allocates memory for the entire kstat (header plus data), initializes 726*7c478bd9Sstevel@tonic-gate * all header fields, initializes the data section to all zeroes, assigns 727*7c478bd9Sstevel@tonic-gate * a unique KID, and puts the kstat onto the system's kstat chain. 728*7c478bd9Sstevel@tonic-gate * The returned kstat is marked invalid (KSTAT_FLAG_INVALID is set), 729*7c478bd9Sstevel@tonic-gate * because the provider (caller) has not yet had a chance to initialize 730*7c478bd9Sstevel@tonic-gate * the data section. 731*7c478bd9Sstevel@tonic-gate * 732*7c478bd9Sstevel@tonic-gate * By default, kstats are exported to all zones on the system. A kstat may be 733*7c478bd9Sstevel@tonic-gate * created via kstat_create_zone() to specify a zone to which the statistics 734*7c478bd9Sstevel@tonic-gate * should be exported. kstat_zone_add() may be used to specify additional 735*7c478bd9Sstevel@tonic-gate * zones to which the statistics are to be exported. 736*7c478bd9Sstevel@tonic-gate * 737*7c478bd9Sstevel@tonic-gate * Step 2: Provider Initialization 738*7c478bd9Sstevel@tonic-gate * 739*7c478bd9Sstevel@tonic-gate * The provider performs any necessary initialization of the data section, 740*7c478bd9Sstevel@tonic-gate * e.g. setting the name fields in a KSTAT_TYPE_NAMED. Virtual kstats set 741*7c478bd9Sstevel@tonic-gate * the ks_data field at this time. The provider may also set the ks_update, 742*7c478bd9Sstevel@tonic-gate * ks_snapshot, ks_private, and ks_lock fields if necessary. 743*7c478bd9Sstevel@tonic-gate * 744*7c478bd9Sstevel@tonic-gate * Step 3: Installation (kstat_install) 745*7c478bd9Sstevel@tonic-gate * 746*7c478bd9Sstevel@tonic-gate * Once the kstat is completely initialized, kstat_install() clears the 747*7c478bd9Sstevel@tonic-gate * INVALID flag, thus making the kstat accessible to the outside world. 748*7c478bd9Sstevel@tonic-gate * kstat_install() also clears the DORMANT flag for persistent kstats. 749*7c478bd9Sstevel@tonic-gate * 750*7c478bd9Sstevel@tonic-gate * Removing a kstat from the system 751*7c478bd9Sstevel@tonic-gate * 752*7c478bd9Sstevel@tonic-gate * kstat_delete(ksp) removes ksp from the kstat chain and frees all 753*7c478bd9Sstevel@tonic-gate * associated system resources. NOTE: When you call kstat_delete(), 754*7c478bd9Sstevel@tonic-gate * you must NOT be holding that kstat's ks_lock. Otherwise, you may 755*7c478bd9Sstevel@tonic-gate * deadlock with a kstat reader. 756*7c478bd9Sstevel@tonic-gate * 757*7c478bd9Sstevel@tonic-gate * Persistent kstats 758*7c478bd9Sstevel@tonic-gate * 759*7c478bd9Sstevel@tonic-gate * From the provider's point of view, persistence is transparent. The only 760*7c478bd9Sstevel@tonic-gate * difference between ephemeral (normal) kstats and persistent kstats 761*7c478bd9Sstevel@tonic-gate * is that you pass KSTAT_FLAG_PERSISTENT to kstat_create(). Magically, 762*7c478bd9Sstevel@tonic-gate * this has the effect of making your data visible even when you're 763*7c478bd9Sstevel@tonic-gate * not home. Persistence is important to tools like iostat, which want 764*7c478bd9Sstevel@tonic-gate * to get a meaningful picture of disk activity. Without persistence, 765*7c478bd9Sstevel@tonic-gate * raw disk i/o statistics could never accumulate: they would come and 766*7c478bd9Sstevel@tonic-gate * go with each open/close of the raw device. 767*7c478bd9Sstevel@tonic-gate * 768*7c478bd9Sstevel@tonic-gate * The magic of persistence works by slightly altering the behavior of 769*7c478bd9Sstevel@tonic-gate * kstat_create() and kstat_delete(). The first call to kstat_create() 770*7c478bd9Sstevel@tonic-gate * creates a new kstat, as usual. However, kstat_delete() does not 771*7c478bd9Sstevel@tonic-gate * actually delete the kstat: it performs one final update of the data 772*7c478bd9Sstevel@tonic-gate * (i.e., calls the ks_update routine), marks the kstat as dormant, and 773*7c478bd9Sstevel@tonic-gate * sets the ks_lock, ks_update, ks_private, and ks_snapshot fields back 774*7c478bd9Sstevel@tonic-gate * to their default values (since they might otherwise point to garbage, 775*7c478bd9Sstevel@tonic-gate * e.g. if the provider is going away). kstat clients can still access 776*7c478bd9Sstevel@tonic-gate * the dormant kstat just like a live kstat; they just continue to see 777*7c478bd9Sstevel@tonic-gate * the final data values as long as the kstat remains dormant. 778*7c478bd9Sstevel@tonic-gate * All subsequent kstat_create() calls simply find the already-existing, 779*7c478bd9Sstevel@tonic-gate * dormant kstat and return a pointer to it, without altering any fields. 780*7c478bd9Sstevel@tonic-gate * The provider then performs its usual initialization sequence, and 781*7c478bd9Sstevel@tonic-gate * calls kstat_install(). kstat_install() uses the old data values to 782*7c478bd9Sstevel@tonic-gate * initialize the native data (i.e., ks_update is called with KSTAT_WRITE), 783*7c478bd9Sstevel@tonic-gate * thus making it seem like you were never gone. 784*7c478bd9Sstevel@tonic-gate */ 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate extern kstat_t *kstat_create(char *, int, char *, char *, uchar_t, 787*7c478bd9Sstevel@tonic-gate uint_t, uchar_t); 788*7c478bd9Sstevel@tonic-gate extern kstat_t *kstat_create_zone(char *, int, char *, char *, uchar_t, 789*7c478bd9Sstevel@tonic-gate uint_t, uchar_t, zoneid_t); 790*7c478bd9Sstevel@tonic-gate extern void kstat_install(kstat_t *); 791*7c478bd9Sstevel@tonic-gate extern void kstat_delete(kstat_t *); 792*7c478bd9Sstevel@tonic-gate extern void kstat_named_setstr(kstat_named_t *knp, const char *src); 793*7c478bd9Sstevel@tonic-gate extern void kstat_set_string(char *, char *); 794*7c478bd9Sstevel@tonic-gate extern void kstat_delete_byname(char *, int, char *); 795*7c478bd9Sstevel@tonic-gate extern void kstat_delete_byname_zone(char *, int, char *, zoneid_t); 796*7c478bd9Sstevel@tonic-gate extern void kstat_named_init(kstat_named_t *, char *, uchar_t); 797*7c478bd9Sstevel@tonic-gate extern void kstat_timer_init(kstat_timer_t *, char *); 798*7c478bd9Sstevel@tonic-gate extern void kstat_waitq_enter(kstat_io_t *); 799*7c478bd9Sstevel@tonic-gate extern void kstat_waitq_exit(kstat_io_t *); 800*7c478bd9Sstevel@tonic-gate extern void kstat_runq_enter(kstat_io_t *); 801*7c478bd9Sstevel@tonic-gate extern void kstat_runq_exit(kstat_io_t *); 802*7c478bd9Sstevel@tonic-gate extern void kstat_waitq_to_runq(kstat_io_t *); 803*7c478bd9Sstevel@tonic-gate extern void kstat_runq_back_to_waitq(kstat_io_t *); 804*7c478bd9Sstevel@tonic-gate extern void kstat_timer_start(kstat_timer_t *); 805*7c478bd9Sstevel@tonic-gate extern void kstat_timer_stop(kstat_timer_t *); 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate extern void kstat_zone_add(kstat_t *, zoneid_t); 808*7c478bd9Sstevel@tonic-gate extern void kstat_zone_remove(kstat_t *, zoneid_t); 809*7c478bd9Sstevel@tonic-gate extern int kstat_zone_find(kstat_t *, zoneid_t); 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate extern kstat_t *kstat_hold_bykid(kid_t kid, zoneid_t); 812*7c478bd9Sstevel@tonic-gate extern kstat_t *kstat_hold_byname(char *, int, char *, zoneid_t); 813*7c478bd9Sstevel@tonic-gate extern void kstat_rele(kstat_t *); 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate #endif /* defined(_KERNEL) */ 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 818*7c478bd9Sstevel@tonic-gate } 819*7c478bd9Sstevel@tonic-gate #endif 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate #endif /* _SYS_KSTAT_H */ 822