xref: /illumos-gate/usr/src/uts/common/sys/kstat.h (revision c0e96d86)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5d624471bSelowe  * Common Development and Distribution License (the "License").
6d624471bSelowe  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22d624471bSelowe  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24b819cea2SGordon Ross  *
25*c0e96d86SHans Rosenfeld  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #ifndef	_SYS_KSTAT_H
297c478bd9Sstevel@tonic-gate #define	_SYS_KSTAT_H
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Definition of general kernel statistics structures and /dev/kstat ioctls
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <sys/types.h>
367c478bd9Sstevel@tonic-gate #include <sys/time.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
397c478bd9Sstevel@tonic-gate extern "C" {
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate typedef int	kid_t;		/* unique kstat id */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * Kernel statistics driver (/dev/kstat) ioctls
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #define	KSTAT_IOC_BASE		('K' << 8)
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #define	KSTAT_IOC_CHAIN_ID	KSTAT_IOC_BASE | 0x01
517c478bd9Sstevel@tonic-gate #define	KSTAT_IOC_READ		KSTAT_IOC_BASE | 0x02
527c478bd9Sstevel@tonic-gate #define	KSTAT_IOC_WRITE		KSTAT_IOC_BASE | 0x03
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * /dev/kstat ioctl usage (kd denotes /dev/kstat descriptor):
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  *	kcid = ioctl(kd, KSTAT_IOC_CHAIN_ID, NULL);
587c478bd9Sstevel@tonic-gate  *	kcid = ioctl(kd, KSTAT_IOC_READ, kstat_t *);
597c478bd9Sstevel@tonic-gate  *	kcid = ioctl(kd, KSTAT_IOC_WRITE, kstat_t *);
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #define	KSTAT_STRLEN	31	/* 30 chars + NULL; must be 16 * n - 1 */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * The generic kstat header
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate typedef struct kstat {
697c478bd9Sstevel@tonic-gate 	/*
707c478bd9Sstevel@tonic-gate 	 * Fields relevant to both kernel and user
717c478bd9Sstevel@tonic-gate 	 */
727c478bd9Sstevel@tonic-gate 	hrtime_t	ks_crtime;	/* creation time (from gethrtime()) */
737c478bd9Sstevel@tonic-gate 	struct kstat	*ks_next;	/* kstat chain linkage */
747c478bd9Sstevel@tonic-gate 	kid_t		ks_kid;		/* unique kstat ID */
757c478bd9Sstevel@tonic-gate 	char		ks_module[KSTAT_STRLEN]; /* provider module name */
767c478bd9Sstevel@tonic-gate 	uchar_t		ks_resv;	/* reserved, currently just padding */
777c478bd9Sstevel@tonic-gate 	int		ks_instance;	/* provider module's instance */
787c478bd9Sstevel@tonic-gate 	char		ks_name[KSTAT_STRLEN]; /* kstat name */
797c478bd9Sstevel@tonic-gate 	uchar_t		ks_type;	/* kstat data type */
807c478bd9Sstevel@tonic-gate 	char		ks_class[KSTAT_STRLEN]; /* kstat class */
817c478bd9Sstevel@tonic-gate 	uchar_t		ks_flags;	/* kstat flags */
827c478bd9Sstevel@tonic-gate 	void		*ks_data;	/* kstat type-specific data */
837c478bd9Sstevel@tonic-gate 	uint_t		ks_ndata;	/* # of type-specific data records */
847c478bd9Sstevel@tonic-gate 	size_t		ks_data_size;	/* total size of kstat data section */
857c478bd9Sstevel@tonic-gate 	hrtime_t	ks_snaptime;	/* time of last data shapshot */
867c478bd9Sstevel@tonic-gate 	/*
877c478bd9Sstevel@tonic-gate 	 * Fields relevant to kernel only
887c478bd9Sstevel@tonic-gate 	 */
897c478bd9Sstevel@tonic-gate 	int		(*ks_update)(struct kstat *, int); /* dynamic update */
907c478bd9Sstevel@tonic-gate 	void		*ks_private;	/* arbitrary provider-private data */
917c478bd9Sstevel@tonic-gate 	int		(*ks_snapshot)(struct kstat *, void *, int);
927c478bd9Sstevel@tonic-gate 	void		*ks_lock;	/* protects this kstat's data */
937c478bd9Sstevel@tonic-gate } kstat_t;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate typedef int32_t kid32_t;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate typedef struct kstat32 {
1007c478bd9Sstevel@tonic-gate 	/*
1017c478bd9Sstevel@tonic-gate 	 * Fields relevant to both kernel and user
1027c478bd9Sstevel@tonic-gate 	 */
1037c478bd9Sstevel@tonic-gate 	hrtime_t	ks_crtime;
1047c478bd9Sstevel@tonic-gate 	caddr32_t	ks_next;		/* struct kstat pointer */
1057c478bd9Sstevel@tonic-gate 	kid32_t		ks_kid;
1067c478bd9Sstevel@tonic-gate 	char		ks_module[KSTAT_STRLEN];
1077c478bd9Sstevel@tonic-gate 	uint8_t		ks_resv;
1087c478bd9Sstevel@tonic-gate 	int32_t		ks_instance;
1097c478bd9Sstevel@tonic-gate 	char		ks_name[KSTAT_STRLEN];
1107c478bd9Sstevel@tonic-gate 	uint8_t		ks_type;
1117c478bd9Sstevel@tonic-gate 	char		ks_class[KSTAT_STRLEN];
1127c478bd9Sstevel@tonic-gate 	uint8_t		ks_flags;
1137c478bd9Sstevel@tonic-gate 	caddr32_t	ks_data;		/* type-specific data */
1147c478bd9Sstevel@tonic-gate 	uint32_t	ks_ndata;
1157c478bd9Sstevel@tonic-gate 	size32_t	ks_data_size;
1167c478bd9Sstevel@tonic-gate 	hrtime_t	ks_snaptime;
1177c478bd9Sstevel@tonic-gate 	/*
1187c478bd9Sstevel@tonic-gate 	 * Fields relevant to kernel only (only needed here for padding)
1197c478bd9Sstevel@tonic-gate 	 */
1207c478bd9Sstevel@tonic-gate 	int32_t		_ks_update;
1217c478bd9Sstevel@tonic-gate 	caddr32_t	_ks_private;
1227c478bd9Sstevel@tonic-gate 	int32_t		_ks_snapshot;
1237c478bd9Sstevel@tonic-gate 	caddr32_t	_ks_lock;
1247c478bd9Sstevel@tonic-gate } kstat32_t;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate /*
1297c478bd9Sstevel@tonic-gate  * kstat structure and locking strategy
1307c478bd9Sstevel@tonic-gate  *
1317c478bd9Sstevel@tonic-gate  * Each kstat consists of a header section (a kstat_t) and a data section.
1327c478bd9Sstevel@tonic-gate  * The system maintains a set of kstats, protected by kstat_chain_lock.
1337c478bd9Sstevel@tonic-gate  * kstat_chain_lock protects all additions to/deletions from this set,
1347c478bd9Sstevel@tonic-gate  * as well as all changes to kstat headers.  kstat data sections are
1357c478bd9Sstevel@tonic-gate  * *optionally* protected by the per-kstat ks_lock.  If ks_lock is non-NULL,
1367c478bd9Sstevel@tonic-gate  * kstat clients (e.g. /dev/kstat) will acquire this lock for all of their
1377c478bd9Sstevel@tonic-gate  * operations on that kstat.  It is up to the kstat provider to decide whether
1387c478bd9Sstevel@tonic-gate  * guaranteeing consistent data to kstat clients is sufficiently important
1397c478bd9Sstevel@tonic-gate  * to justify the locking cost.  Note, however, that most statistic updates
1407c478bd9Sstevel@tonic-gate  * already occur under one of the provider's mutexes, so if the provider sets
1417c478bd9Sstevel@tonic-gate  * ks_lock to point to that mutex, then kstat data locking is free.
1427c478bd9Sstevel@tonic-gate  *
1437c478bd9Sstevel@tonic-gate  * NOTE: variable-size kstats MUST employ kstat data locking, to prevent
1447c478bd9Sstevel@tonic-gate  * data-size races with kstat clients.
1457c478bd9Sstevel@tonic-gate  *
1467c478bd9Sstevel@tonic-gate  * NOTE: ks_lock is really of type (kmutex_t *); it is declared as (void *)
1477c478bd9Sstevel@tonic-gate  * in the kstat header so that users don't have to be exposed to all of the
1487c478bd9Sstevel@tonic-gate  * kernel's lock-related data structures.
1497c478bd9Sstevel@tonic-gate  */
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate #if	defined(_KERNEL)
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate #define	KSTAT_ENTER(k)	\
1547c478bd9Sstevel@tonic-gate 	{ kmutex_t *lp = (k)->ks_lock; if (lp) mutex_enter(lp); }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate #define	KSTAT_EXIT(k)	\
1577c478bd9Sstevel@tonic-gate 	{ kmutex_t *lp = (k)->ks_lock; if (lp) mutex_exit(lp); }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate #define	KSTAT_UPDATE(k, rw)		(*(k)->ks_update)((k), (rw))
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate #define	KSTAT_SNAPSHOT(k, buf, rw)	(*(k)->ks_snapshot)((k), (buf), (rw))
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate #endif	/* defined(_KERNEL) */
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate /*
1667c478bd9Sstevel@tonic-gate  * kstat time
1677c478bd9Sstevel@tonic-gate  *
1687c478bd9Sstevel@tonic-gate  * All times associated with kstats (e.g. creation time, snapshot time,
1697c478bd9Sstevel@tonic-gate  * kstat_timer_t and kstat_io_t timestamps, etc.) are 64-bit nanosecond values,
1707c478bd9Sstevel@tonic-gate  * as returned by gethrtime().  The accuracy of these timestamps is machine
1717c478bd9Sstevel@tonic-gate  * dependent, but the precision (units) is the same across all platforms.
1727c478bd9Sstevel@tonic-gate  */
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate  * kstat identity (KID)
1767c478bd9Sstevel@tonic-gate  *
1777c478bd9Sstevel@tonic-gate  * Each kstat is assigned a unique KID (kstat ID) when it is added to the
1787c478bd9Sstevel@tonic-gate  * global kstat chain.  The KID is used as a cookie by /dev/kstat to
1797c478bd9Sstevel@tonic-gate  * request information about the corresponding kstat.  There is also
1807c478bd9Sstevel@tonic-gate  * an identity associated with the entire kstat chain, kstat_chain_id,
1817c478bd9Sstevel@tonic-gate  * which is bumped each time a kstat is added or deleted.  /dev/kstat uses
1827c478bd9Sstevel@tonic-gate  * the chain ID to detect changes in the kstat chain (e.g., a new disk
1837c478bd9Sstevel@tonic-gate  * coming online) between ioctl()s.
1847c478bd9Sstevel@tonic-gate  */
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate  * kstat module, kstat instance
1887c478bd9Sstevel@tonic-gate  *
1897c478bd9Sstevel@tonic-gate  * ks_module and ks_instance contain the name and instance of the module
1907c478bd9Sstevel@tonic-gate  * that created the kstat.  In cases where there can only be one instance,
1917c478bd9Sstevel@tonic-gate  * ks_instance is 0.  The kernel proper (/kernel/unix) uses "unix" as its
1927c478bd9Sstevel@tonic-gate  * module name.
1937c478bd9Sstevel@tonic-gate  */
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate  * kstat name
1977c478bd9Sstevel@tonic-gate  *
1987c478bd9Sstevel@tonic-gate  * ks_name gives a meaningful name to a kstat.  The full kstat namespace
1997c478bd9Sstevel@tonic-gate  * is module.instance.name, so the name only need be unique within a
2007c478bd9Sstevel@tonic-gate  * module.  kstat_create() will fail if you try to create a kstat with
2017c478bd9Sstevel@tonic-gate  * an already-used (ks_module, ks_instance, ks_name) triplet.  Spaces are
2027c478bd9Sstevel@tonic-gate  * allowed in kstat names, but strongly discouraged, since they hinder
2037c478bd9Sstevel@tonic-gate  * awk-style processing at user level.
2047c478bd9Sstevel@tonic-gate  */
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate  * kstat type
2087c478bd9Sstevel@tonic-gate  *
2097c478bd9Sstevel@tonic-gate  * The kstat mechanism provides several flavors of kstat data, defined
2107c478bd9Sstevel@tonic-gate  * below.  The "raw" kstat type is just treated as an array of bytes; you
2117c478bd9Sstevel@tonic-gate  * can use this to export any kind of data you want.
2127c478bd9Sstevel@tonic-gate  *
2137c478bd9Sstevel@tonic-gate  * Some kstat types allow multiple data structures per kstat, e.g.
2147c478bd9Sstevel@tonic-gate  * KSTAT_TYPE_NAMED; others do not.  This is part of the spec for each
2157c478bd9Sstevel@tonic-gate  * kstat data type.
2167c478bd9Sstevel@tonic-gate  *
2177c478bd9Sstevel@tonic-gate  * User-level tools should *not* rely on the #define KSTAT_NUM_TYPES.  To
2187c478bd9Sstevel@tonic-gate  * get this information, read out the standard system kstat "kstat_types".
2197c478bd9Sstevel@tonic-gate  */
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate #define	KSTAT_TYPE_RAW		0	/* can be anything */
2227c478bd9Sstevel@tonic-gate 					/* ks_ndata >= 1 */
2237c478bd9Sstevel@tonic-gate #define	KSTAT_TYPE_NAMED	1	/* name/value pair */
2247c478bd9Sstevel@tonic-gate 					/* ks_ndata >= 1 */
2257c478bd9Sstevel@tonic-gate #define	KSTAT_TYPE_INTR		2	/* interrupt statistics */
2267c478bd9Sstevel@tonic-gate 					/* ks_ndata == 1 */
2277c478bd9Sstevel@tonic-gate #define	KSTAT_TYPE_IO		3	/* I/O statistics */
2287c478bd9Sstevel@tonic-gate 					/* ks_ndata == 1 */
2297c478bd9Sstevel@tonic-gate #define	KSTAT_TYPE_TIMER	4	/* event timer */
2307c478bd9Sstevel@tonic-gate 					/* ks_ndata >= 1 */
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate #define	KSTAT_NUM_TYPES		5
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate  * kstat class
2367c478bd9Sstevel@tonic-gate  *
2377c478bd9Sstevel@tonic-gate  * Each kstat can be characterized as belonging to some broad class
2387c478bd9Sstevel@tonic-gate  * of statistics, e.g. disk, tape, net, vm, streams, etc.  This field
2397c478bd9Sstevel@tonic-gate  * can be used as a filter to extract related kstats.  The following
2407c478bd9Sstevel@tonic-gate  * values are currently in use: disk, tape, net, controller, vm, kvm,
2417c478bd9Sstevel@tonic-gate  * hat, streams, kstat, and misc.  (The kstat class encompasses things
2427c478bd9Sstevel@tonic-gate  * like kstat_types.)
2437c478bd9Sstevel@tonic-gate  */
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate  * kstat flags
2477c478bd9Sstevel@tonic-gate  *
2487c478bd9Sstevel@tonic-gate  * Any of the following flags may be passed to kstat_create().  They are
2497c478bd9Sstevel@tonic-gate  * all zero by default.
2507c478bd9Sstevel@tonic-gate  *
2517c478bd9Sstevel@tonic-gate  *	KSTAT_FLAG_VIRTUAL:
2527c478bd9Sstevel@tonic-gate  *
2537c478bd9Sstevel@tonic-gate  *		Tells kstat_create() not to allocate memory for the
2547c478bd9Sstevel@tonic-gate  *		kstat data section; instead, you will set the ks_data
2557c478bd9Sstevel@tonic-gate  *		field to point to the data you wish to export.  This
2567c478bd9Sstevel@tonic-gate  *		provides a convenient way to export existing data
2577c478bd9Sstevel@tonic-gate  *		structures.
2587c478bd9Sstevel@tonic-gate  *
2597c478bd9Sstevel@tonic-gate  *	KSTAT_FLAG_VAR_SIZE:
2607c478bd9Sstevel@tonic-gate  *
2617c478bd9Sstevel@tonic-gate  *		The size of the kstat you are creating will vary over time.
2627c478bd9Sstevel@tonic-gate  *		For example, you may want to use the kstat mechanism to
2637c478bd9Sstevel@tonic-gate  *		export a linked list.  NOTE: The kstat framework does not
2647c478bd9Sstevel@tonic-gate  *		manage the data section, so all variable-size kstats must be
2657c478bd9Sstevel@tonic-gate  *		virtual kstats.  Moreover, variable-size kstats MUST employ
2667c478bd9Sstevel@tonic-gate  *		kstat data locking to prevent data-size races with kstat
2677c478bd9Sstevel@tonic-gate  *		clients.  See the section on "kstat snapshot" for details.
2687c478bd9Sstevel@tonic-gate  *
2697c478bd9Sstevel@tonic-gate  *	KSTAT_FLAG_WRITABLE:
2707c478bd9Sstevel@tonic-gate  *
2717c478bd9Sstevel@tonic-gate  *		Makes the kstat's data section writable by root.
2727c478bd9Sstevel@tonic-gate  *		The ks_snapshot routine (see below) does not need to check for
2737c478bd9Sstevel@tonic-gate  *		this; permission checking is handled in the kstat driver.
2747c478bd9Sstevel@tonic-gate  *
2757c478bd9Sstevel@tonic-gate  *	KSTAT_FLAG_PERSISTENT:
2767c478bd9Sstevel@tonic-gate  *
2777c478bd9Sstevel@tonic-gate  *		Indicates that this kstat is to be persistent over time.
2787c478bd9Sstevel@tonic-gate  *		For persistent kstats, kstat_delete() simply marks the
2797c478bd9Sstevel@tonic-gate  *		kstat as dormant; a subsequent kstat_create() reactivates
2807c478bd9Sstevel@tonic-gate  *		the kstat.  This feature is provided so that statistics
2817c478bd9Sstevel@tonic-gate  *		are not lost across driver close/open (e.g., raw disk I/O
2827c478bd9Sstevel@tonic-gate  *		on a disk with no mounted partitions.)
2837c478bd9Sstevel@tonic-gate  *		NOTE: Persistent kstats cannot be virtual, since ks_data
2847c478bd9Sstevel@tonic-gate  *		points to garbage as soon as the driver goes away.
2857c478bd9Sstevel@tonic-gate  *
2867c478bd9Sstevel@tonic-gate  * The following flags are maintained by the kstat framework:
2877c478bd9Sstevel@tonic-gate  *
2887c478bd9Sstevel@tonic-gate  *	KSTAT_FLAG_DORMANT:
2897c478bd9Sstevel@tonic-gate  *
2907c478bd9Sstevel@tonic-gate  *		For persistent kstats, indicates that the kstat is in the
2917c478bd9Sstevel@tonic-gate  *		dormant state (e.g., the corresponding device is closed).
2927c478bd9Sstevel@tonic-gate  *
2937c478bd9Sstevel@tonic-gate  *	KSTAT_FLAG_INVALID:
2947c478bd9Sstevel@tonic-gate  *
2957c478bd9Sstevel@tonic-gate  *		This flag is set when a kstat is in a transitional state,
2967c478bd9Sstevel@tonic-gate  *		e.g. between kstat_create() and kstat_install().
2977c478bd9Sstevel@tonic-gate  *		kstat clients must not attempt to access the kstat's data
2987c478bd9Sstevel@tonic-gate  *		if this flag is set.
299*c0e96d86SHans Rosenfeld  *
300*c0e96d86SHans Rosenfeld  *	KSTAT_FLAG_LONGSTRINGS:
301*c0e96d86SHans Rosenfeld  *
302*c0e96d86SHans Rosenfeld  *		Indicates that this kstat contains long strings (which
303*c0e96d86SHans Rosenfeld  *		are stored outside of the kstat data section). When copied
304*c0e96d86SHans Rosenfeld  *		out to user space the string data will be held in the data
305*c0e96d86SHans Rosenfeld  *		section provided by the user.
3067c478bd9Sstevel@tonic-gate  */
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate #define	KSTAT_FLAG_VIRTUAL		0x01
3097c478bd9Sstevel@tonic-gate #define	KSTAT_FLAG_VAR_SIZE		0x02
3107c478bd9Sstevel@tonic-gate #define	KSTAT_FLAG_WRITABLE		0x04
3117c478bd9Sstevel@tonic-gate #define	KSTAT_FLAG_PERSISTENT		0x08
3127c478bd9Sstevel@tonic-gate #define	KSTAT_FLAG_DORMANT		0x10
3137c478bd9Sstevel@tonic-gate #define	KSTAT_FLAG_INVALID		0x20
314*c0e96d86SHans Rosenfeld #define	KSTAT_FLAG_LONGSTRINGS		0x40
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate /*
3177c478bd9Sstevel@tonic-gate  * Dynamic update support
3187c478bd9Sstevel@tonic-gate  *
3197c478bd9Sstevel@tonic-gate  * The kstat mechanism allows for an optional ks_update function to update
3207c478bd9Sstevel@tonic-gate  * kstat data.  This is useful for drivers where the underlying device
3217c478bd9Sstevel@tonic-gate  * keeps cheap hardware stats, but extraction is expensive.  Instead of
3227c478bd9Sstevel@tonic-gate  * constantly keeping the kstat data section up to date, you can supply a
3237c478bd9Sstevel@tonic-gate  * ks_update function which updates the kstat's data section on demand.
3247c478bd9Sstevel@tonic-gate  * To take advantage of this feature, simply set the ks_update field before
3257c478bd9Sstevel@tonic-gate  * calling kstat_install().
3267c478bd9Sstevel@tonic-gate  *
3277c478bd9Sstevel@tonic-gate  * The ks_update function, if supplied, must have the following structure:
3287c478bd9Sstevel@tonic-gate  *
3297c478bd9Sstevel@tonic-gate  *	int
3307c478bd9Sstevel@tonic-gate  *	foo_kstat_update(kstat_t *ksp, int rw)
3317c478bd9Sstevel@tonic-gate  *	{
3327c478bd9Sstevel@tonic-gate  *		if (rw == KSTAT_WRITE) {
3337c478bd9Sstevel@tonic-gate  *			... update the native stats from ksp->ks_data;
3347c478bd9Sstevel@tonic-gate  *				return EACCES if you don't support this
3357c478bd9Sstevel@tonic-gate  *		} else {
3367c478bd9Sstevel@tonic-gate  *			... update ksp->ks_data from the native stats
3377c478bd9Sstevel@tonic-gate  *		}
3387c478bd9Sstevel@tonic-gate  *	}
3397c478bd9Sstevel@tonic-gate  *
3407c478bd9Sstevel@tonic-gate  * The ks_update return codes are: 0 for success, EACCES if you don't allow
3417c478bd9Sstevel@tonic-gate  * KSTAT_WRITE, and EIO for any other type of error.
3427c478bd9Sstevel@tonic-gate  *
3437c478bd9Sstevel@tonic-gate  * In general, the ks_update function may need to refer to provider-private
3447c478bd9Sstevel@tonic-gate  * data; for example, it may need a pointer to the provider's raw statistics.
3457c478bd9Sstevel@tonic-gate  * The ks_private field is available for this purpose.  Its use is entirely
3467c478bd9Sstevel@tonic-gate  * at the provider's discretion.
3477c478bd9Sstevel@tonic-gate  *
3487c478bd9Sstevel@tonic-gate  * All variable-size kstats MUST supply a ks_update routine, which computes
3497c478bd9Sstevel@tonic-gate  * and sets ks_data_size (and ks_ndata if that is meaningful), since these
3507c478bd9Sstevel@tonic-gate  * are needed to perform kstat snapshots (see below).
3517c478bd9Sstevel@tonic-gate  *
3527c478bd9Sstevel@tonic-gate  * No kstat locking should be done inside the ks_update routine.  The caller
3537c478bd9Sstevel@tonic-gate  * will already be holding the kstat's ks_lock (to ensure consistent data).
3547c478bd9Sstevel@tonic-gate  */
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate #define	KSTAT_READ	0
3577c478bd9Sstevel@tonic-gate #define	KSTAT_WRITE	1
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate  * Kstat snapshot
3617c478bd9Sstevel@tonic-gate  *
3627c478bd9Sstevel@tonic-gate  * In order to get a consistent view of a kstat's data, clients must obey
3637c478bd9Sstevel@tonic-gate  * the kstat's locking strategy.  However, these clients may need to perform
3647c478bd9Sstevel@tonic-gate  * operations on the data which could cause a fault (e.g. copyout()), or
3657c478bd9Sstevel@tonic-gate  * operations which are simply expensive.  Doing so could cause deadlock
3667c478bd9Sstevel@tonic-gate  * (e.g. if you're holding a disk's kstat lock which is ultimately required
3677c478bd9Sstevel@tonic-gate  * to resolve a copyout() fault), performance degradation (since the providers'
3687c478bd9Sstevel@tonic-gate  * activity is serialized at the kstat lock), device timing problems, etc.
3697c478bd9Sstevel@tonic-gate  *
3707c478bd9Sstevel@tonic-gate  * To avoid these problems, kstat data is provided via snapshots.  Taking
3717c478bd9Sstevel@tonic-gate  * a snapshot is a simple process: allocate a wired-down kernel buffer,
3727c478bd9Sstevel@tonic-gate  * acquire the kstat's data lock, copy the data into the buffer ("take the
3737c478bd9Sstevel@tonic-gate  * snapshot"), and release the lock.  This ensures that the kstat's data lock
3747c478bd9Sstevel@tonic-gate  * will be held as briefly as possible, and that no faults will occur while
3757c478bd9Sstevel@tonic-gate  * the lock is held.
3767c478bd9Sstevel@tonic-gate  *
3777c478bd9Sstevel@tonic-gate  * Normally, the snapshot is taken by default_kstat_snapshot(), which
3787c478bd9Sstevel@tonic-gate  * timestamps the data (sets ks_snaptime), copies it, and does a little
3797c478bd9Sstevel@tonic-gate  * massaging to deal with incomplete transactions on i/o kstats.  However,
3807c478bd9Sstevel@tonic-gate  * this routine only works for kstats with contiguous data (the typical case).
3817c478bd9Sstevel@tonic-gate  * If you create a kstat whose data is, say, a linked list, you must provide
3827c478bd9Sstevel@tonic-gate  * your own ks_snapshot routine.  The routine you supply must have the
3837c478bd9Sstevel@tonic-gate  * following prototype (replace "foo" with something appropriate):
3847c478bd9Sstevel@tonic-gate  *
3857c478bd9Sstevel@tonic-gate  *	int foo_kstat_snapshot(kstat_t *ksp, void *buf, int rw);
3867c478bd9Sstevel@tonic-gate  *
3877c478bd9Sstevel@tonic-gate  * The minimal snapshot routine -- one which copies contiguous data that
3887c478bd9Sstevel@tonic-gate  * doesn't need any massaging -- would be this:
3897c478bd9Sstevel@tonic-gate  *
3907c478bd9Sstevel@tonic-gate  *	ksp->ks_snaptime = gethrtime();
3917c478bd9Sstevel@tonic-gate  *	if (rw == KSTAT_WRITE)
3927c478bd9Sstevel@tonic-gate  *		bcopy(buf, ksp->ks_data, ksp->ks_data_size);
3937c478bd9Sstevel@tonic-gate  *	else
3947c478bd9Sstevel@tonic-gate  *		bcopy(ksp->ks_data, buf, ksp->ks_data_size);
3957c478bd9Sstevel@tonic-gate  *	return (0);
3967c478bd9Sstevel@tonic-gate  *
3977c478bd9Sstevel@tonic-gate  * A more illuminating example is taking a snapshot of a linked list:
3987c478bd9Sstevel@tonic-gate  *
3997c478bd9Sstevel@tonic-gate  *	ksp->ks_snaptime = gethrtime();
4007c478bd9Sstevel@tonic-gate  *	if (rw == KSTAT_WRITE)
4017c478bd9Sstevel@tonic-gate  *		return (EACCES);		... See below ...
4027c478bd9Sstevel@tonic-gate  *	for (foo = first_foo; foo; foo = foo->next) {
4037c478bd9Sstevel@tonic-gate  *		bcopy((char *) foo, (char *) buf, sizeof (struct foo));
4047c478bd9Sstevel@tonic-gate  *		buf = ((struct foo *) buf) + 1;
4057c478bd9Sstevel@tonic-gate  *	}
4067c478bd9Sstevel@tonic-gate  *	return (0);
4077c478bd9Sstevel@tonic-gate  *
4087c478bd9Sstevel@tonic-gate  * In the example above, we have decided that we don't want to allow
4097c478bd9Sstevel@tonic-gate  * KSTAT_WRITE access, so we return EACCES if this is attempted.
4107c478bd9Sstevel@tonic-gate  *
4117c478bd9Sstevel@tonic-gate  * The key points are:
4127c478bd9Sstevel@tonic-gate  *
4137c478bd9Sstevel@tonic-gate  *	(1) ks_snaptime must be set (via gethrtime()) to timestamp the data.
4147c478bd9Sstevel@tonic-gate  *	(2) Data gets copied from the kstat to the buffer on KSTAT_READ,
4157c478bd9Sstevel@tonic-gate  *		and from the buffer to the kstat on KSTAT_WRITE.
4167c478bd9Sstevel@tonic-gate  *	(3) ks_snapshot return values are: 0 for success, EACCES if you
4177c478bd9Sstevel@tonic-gate  *		don't allow KSTAT_WRITE, and EIO for any other type of error.
4187c478bd9Sstevel@tonic-gate  *
4197c478bd9Sstevel@tonic-gate  * Named kstats (see section on "Named statistics" below) containing long
4207c478bd9Sstevel@tonic-gate  * strings (KSTAT_DATA_STRING) need special handling.  The kstat driver
4217c478bd9Sstevel@tonic-gate  * assumes that all strings are copied into the buffer after the array of
4227c478bd9Sstevel@tonic-gate  * named kstats, and the pointers (KSTAT_NAMED_STR_PTR()) are updated to point
4237c478bd9Sstevel@tonic-gate  * into the copy within the buffer. The default snapshot routine does this,
4247c478bd9Sstevel@tonic-gate  * but overriding routines should contain at least the following:
4257c478bd9Sstevel@tonic-gate  *
4267c478bd9Sstevel@tonic-gate  * if (rw == KSTAT_READ) {
4277c478bd9Sstevel@tonic-gate  * 	kstat_named_t *knp = buf;
4287c478bd9Sstevel@tonic-gate  * 	char *end = knp + ksp->ks_ndata;
4297c478bd9Sstevel@tonic-gate  * 	uint_t i;
4307c478bd9Sstevel@tonic-gate  *
4317c478bd9Sstevel@tonic-gate  * 	... Do the regular copy ...
4327c478bd9Sstevel@tonic-gate  * 	bcopy(ksp->ks_data, buf, sizeof (kstat_named_t) * ksp->ks_ndata);
4337c478bd9Sstevel@tonic-gate  *
4347c478bd9Sstevel@tonic-gate  * 	for (i = 0; i < ksp->ks_ndata; i++, knp++) {
4357c478bd9Sstevel@tonic-gate  *		if (knp[i].data_type == KSTAT_DATA_STRING &&
4367c478bd9Sstevel@tonic-gate  *		    KSTAT_NAMED_STR_PTR(knp) != NULL) {
4377c478bd9Sstevel@tonic-gate  *			bcopy(KSTAT_NAMED_STR_PTR(knp), end,
4387c478bd9Sstevel@tonic-gate  *			    KSTAT_NAMED_STR_BUFLEN(knp));
4397c478bd9Sstevel@tonic-gate  *			KSTAT_NAMED_STR_PTR(knp) = end;
4407c478bd9Sstevel@tonic-gate  *			end += KSTAT_NAMED_STR_BUFLEN(knp);
4417c478bd9Sstevel@tonic-gate  *		}
4427c478bd9Sstevel@tonic-gate  *	}
4437c478bd9Sstevel@tonic-gate  */
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate /*
4467c478bd9Sstevel@tonic-gate  * Named statistics.
4477c478bd9Sstevel@tonic-gate  *
4487c478bd9Sstevel@tonic-gate  * List of arbitrary name=value statistics.
4497c478bd9Sstevel@tonic-gate  */
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate typedef struct kstat_named {
4527c478bd9Sstevel@tonic-gate 	char	name[KSTAT_STRLEN];	/* name of counter */
4537c478bd9Sstevel@tonic-gate 	uchar_t	data_type;		/* data type */
4547c478bd9Sstevel@tonic-gate 	union {
4557c478bd9Sstevel@tonic-gate 		char		c[16];	/* enough for 128-bit ints */
4567c478bd9Sstevel@tonic-gate 		int32_t		i32;
4577c478bd9Sstevel@tonic-gate 		uint32_t	ui32;
4587c478bd9Sstevel@tonic-gate 		struct {
4597c478bd9Sstevel@tonic-gate 			union {
4607c478bd9Sstevel@tonic-gate 				char 		*ptr;	/* NULL-term string */
4617c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && defined(_MULTI_DATAMODEL)
4627c478bd9Sstevel@tonic-gate 				caddr32_t	ptr32;
4637c478bd9Sstevel@tonic-gate #endif
4647c478bd9Sstevel@tonic-gate 				char 		__pad[8]; /* 64-bit padding */
4657c478bd9Sstevel@tonic-gate 			} addr;
4667c478bd9Sstevel@tonic-gate 			uint32_t	len;	/* # bytes for strlen + '\0' */
467a1b5e537Sbmc 		} str;
4687c478bd9Sstevel@tonic-gate /*
4697c478bd9Sstevel@tonic-gate  * The int64_t and uint64_t types are not valid for a maximally conformant
4707c478bd9Sstevel@tonic-gate  * 32-bit compilation environment (cc -Xc) using compilers prior to the
4717c478bd9Sstevel@tonic-gate  * introduction of C99 conforming compiler (reference ISO/IEC 9899:1990).
4727c478bd9Sstevel@tonic-gate  * In these cases, the visibility of i64 and ui64 is only permitted for
4737c478bd9Sstevel@tonic-gate  * 64-bit compilation environments or 32-bit non-maximally conformant
4747c478bd9Sstevel@tonic-gate  * C89 or C90 ANSI C compilation environments (cc -Xt and cc -Xa). In the
4757c478bd9Sstevel@tonic-gate  * C99 ANSI C compilation environment, the long long type is supported.
4767c478bd9Sstevel@tonic-gate  * The _INT64_TYPE is defined by the implementation (see sys/int_types.h).
4777c478bd9Sstevel@tonic-gate  */
4787c478bd9Sstevel@tonic-gate #if defined(_INT64_TYPE)
4797c478bd9Sstevel@tonic-gate 		int64_t		i64;
4807c478bd9Sstevel@tonic-gate 		uint64_t	ui64;
4817c478bd9Sstevel@tonic-gate #endif
4827c478bd9Sstevel@tonic-gate 		long		l;
4837c478bd9Sstevel@tonic-gate 		ulong_t		ul;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 		/* These structure members are obsolete */
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 		longlong_t	ll;
4887c478bd9Sstevel@tonic-gate 		u_longlong_t	ull;
4897c478bd9Sstevel@tonic-gate 		float		f;
4907c478bd9Sstevel@tonic-gate 		double		d;
4917c478bd9Sstevel@tonic-gate 	} value;			/* value of counter */
4927c478bd9Sstevel@tonic-gate } kstat_named_t;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_CHAR		0
4957c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_INT32	1
4967c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_UINT32	2
4977c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_INT64	3
4987c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_UINT64	4
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate #if !defined(_LP64)
5017c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_LONG		KSTAT_DATA_INT32
5027c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_ULONG	KSTAT_DATA_UINT32
5037c478bd9Sstevel@tonic-gate #else
5047c478bd9Sstevel@tonic-gate #if !defined(_KERNEL)
5057c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_LONG		KSTAT_DATA_INT64
5067c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_ULONG	KSTAT_DATA_UINT64
5077c478bd9Sstevel@tonic-gate #else
5087c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_LONG		7	/* only visible to the kernel */
5097c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_ULONG	8	/* only visible to the kernel */
5107c478bd9Sstevel@tonic-gate #endif	/* !_KERNEL */
5117c478bd9Sstevel@tonic-gate #endif	/* !_LP64 */
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate /*
5147c478bd9Sstevel@tonic-gate  * Statistics exporting named kstats with long strings (KSTAT_DATA_STRING)
5157c478bd9Sstevel@tonic-gate  * may not make the assumption that ks_data_size is equal to (ks_ndata * sizeof
5167c478bd9Sstevel@tonic-gate  * (kstat_named_t)).  ks_data_size in these cases is equal to the sum of the
5177c478bd9Sstevel@tonic-gate  * amount of space required to store the strings (ie, the sum of
5187c478bd9Sstevel@tonic-gate  * KSTAT_NAMED_STR_BUFLEN() for all KSTAT_DATA_STRING statistics) plus the
5197c478bd9Sstevel@tonic-gate  * space required to store the kstat_named_t's.
5207c478bd9Sstevel@tonic-gate  *
5217c478bd9Sstevel@tonic-gate  * The default update routine will update ks_data_size automatically for
5227c478bd9Sstevel@tonic-gate  * variable-length kstats containing long strings (using the default update
5237c478bd9Sstevel@tonic-gate  * routine only makes sense if the string is the only thing that is changing
5247c478bd9Sstevel@tonic-gate  * in size, and ks_ndata is constant).  Fixed-length kstats containing long
5257c478bd9Sstevel@tonic-gate  * strings must explicitly change ks_data_size (after creation but before
5267c478bd9Sstevel@tonic-gate  * initialization) to reflect the correct amount of space required for the
5277c478bd9Sstevel@tonic-gate  * long strings and the kstat_named_t's.
5287c478bd9Sstevel@tonic-gate  */
5297c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_STRING	9
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate /* These types are obsolete */
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_LONGLONG	KSTAT_DATA_INT64
5347c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_ULONGLONG	KSTAT_DATA_UINT64
5357c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_FLOAT	5
5367c478bd9Sstevel@tonic-gate #define	KSTAT_DATA_DOUBLE	6
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate #define	KSTAT_NAMED_PTR(kptr)	((kstat_named_t *)(kptr)->ks_data)
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate  * Retrieve the pointer of the string contained in the given named kstat.
5427c478bd9Sstevel@tonic-gate  */
543a1b5e537Sbmc #define	KSTAT_NAMED_STR_PTR(knptr) ((knptr)->value.str.addr.ptr)
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate /*
5467c478bd9Sstevel@tonic-gate  * Retrieve the length of the buffer required to store the string in the given
5477c478bd9Sstevel@tonic-gate  * named kstat.
5487c478bd9Sstevel@tonic-gate  */
549a1b5e537Sbmc #define	KSTAT_NAMED_STR_BUFLEN(knptr) ((knptr)->value.str.len)
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate  * Interrupt statistics.
5537c478bd9Sstevel@tonic-gate  *
5547c478bd9Sstevel@tonic-gate  * An interrupt is a hard interrupt (sourced from the hardware device
5557c478bd9Sstevel@tonic-gate  * itself), a soft interrupt (induced by the system via the use of
5567c478bd9Sstevel@tonic-gate  * some system interrupt source), a watchdog interrupt (induced by
5577c478bd9Sstevel@tonic-gate  * a periodic timer call), spurious (an interrupt entry point was
5587c478bd9Sstevel@tonic-gate  * entered but there was no interrupt condition to service),
5597c478bd9Sstevel@tonic-gate  * or multiple service (an interrupt condition was detected and
5607c478bd9Sstevel@tonic-gate  * serviced just prior to returning from any of the other types).
5617c478bd9Sstevel@tonic-gate  *
5627c478bd9Sstevel@tonic-gate  * Measurement of the spurious class of interrupts is useful for
5637c478bd9Sstevel@tonic-gate  * autovectored devices in order to pinpoint any interrupt latency
5647c478bd9Sstevel@tonic-gate  * problems in a particular system configuration.
5657c478bd9Sstevel@tonic-gate  *
5667c478bd9Sstevel@tonic-gate  * Devices that have more than one interrupt of the same
5677c478bd9Sstevel@tonic-gate  * type should use multiple structures.
5687c478bd9Sstevel@tonic-gate  */
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate #define	KSTAT_INTR_HARD			0
5717c478bd9Sstevel@tonic-gate #define	KSTAT_INTR_SOFT			1
5727c478bd9Sstevel@tonic-gate #define	KSTAT_INTR_WATCHDOG		2
5737c478bd9Sstevel@tonic-gate #define	KSTAT_INTR_SPURIOUS		3
5747c478bd9Sstevel@tonic-gate #define	KSTAT_INTR_MULTSVC		4
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate #define	KSTAT_NUM_INTRS			5
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate typedef struct kstat_intr {
5797c478bd9Sstevel@tonic-gate 	uint_t	intrs[KSTAT_NUM_INTRS];	/* interrupt counters */
5807c478bd9Sstevel@tonic-gate } kstat_intr_t;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate #define	KSTAT_INTR_PTR(kptr)	((kstat_intr_t *)(kptr)->ks_data)
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate /*
5857c478bd9Sstevel@tonic-gate  * I/O statistics.
5867c478bd9Sstevel@tonic-gate  */
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate typedef struct kstat_io {
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	/*
5917c478bd9Sstevel@tonic-gate 	 * Basic counters.
5927c478bd9Sstevel@tonic-gate 	 *
5937c478bd9Sstevel@tonic-gate 	 * The counters should be updated at the end of service
5947c478bd9Sstevel@tonic-gate 	 * (e.g., just prior to calling biodone()).
5957c478bd9Sstevel@tonic-gate 	 */
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	u_longlong_t	nread;		/* number of bytes read */
5987c478bd9Sstevel@tonic-gate 	u_longlong_t	nwritten;	/* number of bytes written */
5997c478bd9Sstevel@tonic-gate 	uint_t		reads;		/* number of read operations */
6007c478bd9Sstevel@tonic-gate 	uint_t		writes;		/* number of write operations */
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	/*
6037c478bd9Sstevel@tonic-gate 	 * Accumulated time and queue length statistics.
6047c478bd9Sstevel@tonic-gate 	 *
6057c478bd9Sstevel@tonic-gate 	 * Accumulated time statistics are kept as a running sum
6067c478bd9Sstevel@tonic-gate 	 * of "active" time.  Queue length statistics are kept as a
6077c478bd9Sstevel@tonic-gate 	 * running sum of the product of queue length and elapsed time
6087c478bd9Sstevel@tonic-gate 	 * at that length -- i.e., a Riemann sum for queue length
6097c478bd9Sstevel@tonic-gate 	 * integrated against time.  (You can also think of the active time
6107c478bd9Sstevel@tonic-gate 	 * as a Riemann sum, for the boolean function (queue_length > 0)
6117c478bd9Sstevel@tonic-gate 	 * integrated against time, or you can think of it as the
6127c478bd9Sstevel@tonic-gate 	 * Lebesgue measure of the set on which queue_length > 0.)
6137c478bd9Sstevel@tonic-gate 	 *
6147c478bd9Sstevel@tonic-gate 	 *		^
6157c478bd9Sstevel@tonic-gate 	 *		|			_________
6167c478bd9Sstevel@tonic-gate 	 *		8			| i4	|
6177c478bd9Sstevel@tonic-gate 	 *		|			|	|
6187c478bd9Sstevel@tonic-gate 	 *	Queue	6			|	|
6197c478bd9Sstevel@tonic-gate 	 *	Length	|	_________	|	|
6207c478bd9Sstevel@tonic-gate 	 *		4	| i2	|_______|	|
6217c478bd9Sstevel@tonic-gate 	 *		|	|	    i3		|
6227c478bd9Sstevel@tonic-gate 	 *		2_______|			|
6237c478bd9Sstevel@tonic-gate 	 *		|    i1				|
6247c478bd9Sstevel@tonic-gate 	 *		|_______________________________|
6257c478bd9Sstevel@tonic-gate 	 *		Time->	t1	t2	t3	t4
6267c478bd9Sstevel@tonic-gate 	 *
6277c478bd9Sstevel@tonic-gate 	 * At each change of state (entry or exit from the queue),
6287c478bd9Sstevel@tonic-gate 	 * we add the elapsed time (since the previous state change)
6297c478bd9Sstevel@tonic-gate 	 * to the active time if the queue length was non-zero during
6307c478bd9Sstevel@tonic-gate 	 * that interval; and we add the product of the elapsed time
6317c478bd9Sstevel@tonic-gate 	 * times the queue length to the running length*time sum.
6327c478bd9Sstevel@tonic-gate 	 *
6337c478bd9Sstevel@tonic-gate 	 * This method is generalizable to measuring residency
6347c478bd9Sstevel@tonic-gate 	 * in any defined system: instead of queue lengths, think
6357c478bd9Sstevel@tonic-gate 	 * of "outstanding RPC calls to server X".
6367c478bd9Sstevel@tonic-gate 	 *
6377c478bd9Sstevel@tonic-gate 	 * A large number of I/O subsystems have at least two basic
6387c478bd9Sstevel@tonic-gate 	 * "lists" of transactions they manage: one for transactions
6397c478bd9Sstevel@tonic-gate 	 * that have been accepted for processing but for which processing
6407c478bd9Sstevel@tonic-gate 	 * has yet to begin, and one for transactions which are actively
6417c478bd9Sstevel@tonic-gate 	 * being processed (but not done). For this reason, two cumulative
6427c478bd9Sstevel@tonic-gate 	 * time statistics are defined here: wait (pre-service) time,
6437c478bd9Sstevel@tonic-gate 	 * and run (service) time.
6447c478bd9Sstevel@tonic-gate 	 *
6457c478bd9Sstevel@tonic-gate 	 * All times are 64-bit nanoseconds (hrtime_t), as returned by
6467c478bd9Sstevel@tonic-gate 	 * gethrtime().
6477c478bd9Sstevel@tonic-gate 	 *
6487c478bd9Sstevel@tonic-gate 	 * The units of cumulative busy time are accumulated nanoseconds.
6497c478bd9Sstevel@tonic-gate 	 * The units of cumulative length*time products are elapsed time
6507c478bd9Sstevel@tonic-gate 	 * times queue length.
6517c478bd9Sstevel@tonic-gate 	 *
6527c478bd9Sstevel@tonic-gate 	 * Updates to the fields below are performed implicitly by calls to
6537c478bd9Sstevel@tonic-gate 	 * these five functions:
6547c478bd9Sstevel@tonic-gate 	 *
6557c478bd9Sstevel@tonic-gate 	 *	kstat_waitq_enter()
6567c478bd9Sstevel@tonic-gate 	 *	kstat_waitq_exit()
6577c478bd9Sstevel@tonic-gate 	 *	kstat_runq_enter()
6587c478bd9Sstevel@tonic-gate 	 *	kstat_runq_exit()
6597c478bd9Sstevel@tonic-gate 	 *
6607c478bd9Sstevel@tonic-gate 	 *	kstat_waitq_to_runq()		(see below)
6617c478bd9Sstevel@tonic-gate 	 *	kstat_runq_back_to_waitq()	(see below)
6627c478bd9Sstevel@tonic-gate 	 *
6637c478bd9Sstevel@tonic-gate 	 * Since kstat_waitq_exit() is typically followed immediately
6647c478bd9Sstevel@tonic-gate 	 * by kstat_runq_enter(), there is a single kstat_waitq_to_runq()
6657c478bd9Sstevel@tonic-gate 	 * function which performs both operations.  This is a performance
6667c478bd9Sstevel@tonic-gate 	 * win since only one timestamp is required.
6677c478bd9Sstevel@tonic-gate 	 *
6687c478bd9Sstevel@tonic-gate 	 * In some instances, it may be necessary to move a request from
6697c478bd9Sstevel@tonic-gate 	 * the run queue back to the wait queue, e.g. for write throttling.
6707c478bd9Sstevel@tonic-gate 	 * For these situations, call kstat_runq_back_to_waitq().
6717c478bd9Sstevel@tonic-gate 	 *
6727c478bd9Sstevel@tonic-gate 	 * These fields should never be updated by any other means.
6737c478bd9Sstevel@tonic-gate 	 */
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	hrtime_t wtime;		/* cumulative wait (pre-service) time */
6767c478bd9Sstevel@tonic-gate 	hrtime_t wlentime;	/* cumulative wait length*time product */
6777c478bd9Sstevel@tonic-gate 	hrtime_t wlastupdate;	/* last time wait queue changed */
6787c478bd9Sstevel@tonic-gate 	hrtime_t rtime;		/* cumulative run (service) time */
6797c478bd9Sstevel@tonic-gate 	hrtime_t rlentime;	/* cumulative run length*time product */
6807c478bd9Sstevel@tonic-gate 	hrtime_t rlastupdate;	/* last time run queue changed */
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	uint_t	wcnt;		/* count of elements in wait state */
6837c478bd9Sstevel@tonic-gate 	uint_t	rcnt;		/* count of elements in run state */
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate } kstat_io_t;
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate #define	KSTAT_IO_PTR(kptr)	((kstat_io_t *)(kptr)->ks_data)
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate /*
6907c478bd9Sstevel@tonic-gate  * Event timer statistics - cumulative elapsed time and number of events.
6917c478bd9Sstevel@tonic-gate  *
6927c478bd9Sstevel@tonic-gate  * Updates to these fields are performed implicitly by calls to
6937c478bd9Sstevel@tonic-gate  * kstat_timer_start() and kstat_timer_stop().
6947c478bd9Sstevel@tonic-gate  */
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate typedef struct kstat_timer {
6977c478bd9Sstevel@tonic-gate 	char		name[KSTAT_STRLEN];	/* event name */
6987c478bd9Sstevel@tonic-gate 	uchar_t		resv;			/* reserved */
6997c478bd9Sstevel@tonic-gate 	u_longlong_t	num_events;		/* number of events */
7007c478bd9Sstevel@tonic-gate 	hrtime_t	elapsed_time;		/* cumulative elapsed time */
7017c478bd9Sstevel@tonic-gate 	hrtime_t	min_time;		/* shortest event duration */
7027c478bd9Sstevel@tonic-gate 	hrtime_t	max_time;		/* longest event duration */
7037c478bd9Sstevel@tonic-gate 	hrtime_t	start_time;		/* previous event start time */
7047c478bd9Sstevel@tonic-gate 	hrtime_t	stop_time;		/* previous event stop time */
7057c478bd9Sstevel@tonic-gate } kstat_timer_t;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate #define	KSTAT_TIMER_PTR(kptr)	((kstat_timer_t *)(kptr)->ks_data)
7087c478bd9Sstevel@tonic-gate 
709b819cea2SGordon Ross #if	defined(_KERNEL) || defined(_FAKE_KERNEL)
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate extern kid_t	kstat_chain_id;		/* bumped at each state change */
7147c478bd9Sstevel@tonic-gate extern void	kstat_init(void);	/* initialize kstat framework */
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate /*
7177c478bd9Sstevel@tonic-gate  * Adding and deleting kstats.
7187c478bd9Sstevel@tonic-gate  *
7197c478bd9Sstevel@tonic-gate  * The typical sequence to add a kstat is:
7207c478bd9Sstevel@tonic-gate  *
7217c478bd9Sstevel@tonic-gate  *	ksp = kstat_create(module, instance, name, class, type, ndata, flags);
7227c478bd9Sstevel@tonic-gate  *	if (ksp) {
7237c478bd9Sstevel@tonic-gate  *		... provider initialization, if necessary
7247c478bd9Sstevel@tonic-gate  *		kstat_install(ksp);
7257c478bd9Sstevel@tonic-gate  *	}
7267c478bd9Sstevel@tonic-gate  *
7277c478bd9Sstevel@tonic-gate  * There are three logically distinct steps here:
7287c478bd9Sstevel@tonic-gate  *
7297c478bd9Sstevel@tonic-gate  * Step 1: System Initialization (kstat_create)
7307c478bd9Sstevel@tonic-gate  *
7317c478bd9Sstevel@tonic-gate  * kstat_create() performs system initialization.  kstat_create()
7327c478bd9Sstevel@tonic-gate  * allocates memory for the entire kstat (header plus data), initializes
7337c478bd9Sstevel@tonic-gate  * all header fields, initializes the data section to all zeroes, assigns
7347c478bd9Sstevel@tonic-gate  * a unique KID, and puts the kstat onto the system's kstat chain.
7357c478bd9Sstevel@tonic-gate  * The returned kstat is marked invalid (KSTAT_FLAG_INVALID is set),
7367c478bd9Sstevel@tonic-gate  * because the provider (caller) has not yet had a chance to initialize
7377c478bd9Sstevel@tonic-gate  * the data section.
7387c478bd9Sstevel@tonic-gate  *
7397c478bd9Sstevel@tonic-gate  * By default, kstats are exported to all zones on the system.  A kstat may be
7407c478bd9Sstevel@tonic-gate  * created via kstat_create_zone() to specify a zone to which the statistics
7417c478bd9Sstevel@tonic-gate  * should be exported.  kstat_zone_add() may be used to specify additional
7427c478bd9Sstevel@tonic-gate  * zones to which the statistics are to be exported.
7437c478bd9Sstevel@tonic-gate  *
7447c478bd9Sstevel@tonic-gate  * Step 2: Provider Initialization
7457c478bd9Sstevel@tonic-gate  *
7467c478bd9Sstevel@tonic-gate  * The provider performs any necessary initialization of the data section,
7477c478bd9Sstevel@tonic-gate  * e.g. setting the name fields in a KSTAT_TYPE_NAMED.  Virtual kstats set
7487c478bd9Sstevel@tonic-gate  * the ks_data field at this time.  The provider may also set the ks_update,
7497c478bd9Sstevel@tonic-gate  * ks_snapshot, ks_private, and ks_lock fields if necessary.
7507c478bd9Sstevel@tonic-gate  *
7517c478bd9Sstevel@tonic-gate  * Step 3: Installation (kstat_install)
7527c478bd9Sstevel@tonic-gate  *
7537c478bd9Sstevel@tonic-gate  * Once the kstat is completely initialized, kstat_install() clears the
7547c478bd9Sstevel@tonic-gate  * INVALID flag, thus making the kstat accessible to the outside world.
7557c478bd9Sstevel@tonic-gate  * kstat_install() also clears the DORMANT flag for persistent kstats.
7567c478bd9Sstevel@tonic-gate  *
7577c478bd9Sstevel@tonic-gate  * Removing a kstat from the system
7587c478bd9Sstevel@tonic-gate  *
7597c478bd9Sstevel@tonic-gate  * kstat_delete(ksp) removes ksp from the kstat chain and frees all
7607c478bd9Sstevel@tonic-gate  * associated system resources.  NOTE: When you call kstat_delete(),
7617c478bd9Sstevel@tonic-gate  * you must NOT be holding that kstat's ks_lock.  Otherwise, you may
7627c478bd9Sstevel@tonic-gate  * deadlock with a kstat reader.
7637c478bd9Sstevel@tonic-gate  *
7647c478bd9Sstevel@tonic-gate  * Persistent kstats
7657c478bd9Sstevel@tonic-gate  *
7667c478bd9Sstevel@tonic-gate  * From the provider's point of view, persistence is transparent.  The only
7677c478bd9Sstevel@tonic-gate  * difference between ephemeral (normal) kstats and persistent kstats
7687c478bd9Sstevel@tonic-gate  * is that you pass KSTAT_FLAG_PERSISTENT to kstat_create().  Magically,
7697c478bd9Sstevel@tonic-gate  * this has the effect of making your data visible even when you're
7707c478bd9Sstevel@tonic-gate  * not home.  Persistence is important to tools like iostat, which want
7717c478bd9Sstevel@tonic-gate  * to get a meaningful picture of disk activity.  Without persistence,
7727c478bd9Sstevel@tonic-gate  * raw disk i/o statistics could never accumulate: they would come and
7737c478bd9Sstevel@tonic-gate  * go with each open/close of the raw device.
7747c478bd9Sstevel@tonic-gate  *
7757c478bd9Sstevel@tonic-gate  * The magic of persistence works by slightly altering the behavior of
7767c478bd9Sstevel@tonic-gate  * kstat_create() and kstat_delete().  The first call to kstat_create()
7777c478bd9Sstevel@tonic-gate  * creates a new kstat, as usual.  However, kstat_delete() does not
7787c478bd9Sstevel@tonic-gate  * actually delete the kstat: it performs one final update of the data
7797c478bd9Sstevel@tonic-gate  * (i.e., calls the ks_update routine), marks the kstat as dormant, and
7807c478bd9Sstevel@tonic-gate  * sets the ks_lock, ks_update, ks_private, and ks_snapshot fields back
7817c478bd9Sstevel@tonic-gate  * to their default values (since they might otherwise point to garbage,
7827c478bd9Sstevel@tonic-gate  * e.g. if the provider is going away).  kstat clients can still access
7837c478bd9Sstevel@tonic-gate  * the dormant kstat just like a live kstat; they just continue to see
7847c478bd9Sstevel@tonic-gate  * the final data values as long as the kstat remains dormant.
7857c478bd9Sstevel@tonic-gate  * All subsequent kstat_create() calls simply find the already-existing,
7867c478bd9Sstevel@tonic-gate  * dormant kstat and return a pointer to it, without altering any fields.
7877c478bd9Sstevel@tonic-gate  * The provider then performs its usual initialization sequence, and
7887c478bd9Sstevel@tonic-gate  * calls kstat_install().  kstat_install() uses the old data values to
7897c478bd9Sstevel@tonic-gate  * initialize the native data (i.e., ks_update is called with KSTAT_WRITE),
7907c478bd9Sstevel@tonic-gate  * thus making it seem like you were never gone.
7917c478bd9Sstevel@tonic-gate  */
7927c478bd9Sstevel@tonic-gate 
793d624471bSelowe extern kstat_t *kstat_create(const char *, int, const char *, const char *,
794d624471bSelowe     uchar_t, uint_t, uchar_t);
795d624471bSelowe extern kstat_t *kstat_create_zone(const char *, int, const char *,
796d624471bSelowe     const char *, uchar_t, uint_t, uchar_t, zoneid_t);
7977c478bd9Sstevel@tonic-gate extern void kstat_install(kstat_t *);
7987c478bd9Sstevel@tonic-gate extern void kstat_delete(kstat_t *);
7997c478bd9Sstevel@tonic-gate extern void kstat_named_setstr(kstat_named_t *knp, const char *src);
800d624471bSelowe extern void kstat_set_string(char *, const char *);
801d624471bSelowe extern void kstat_delete_byname(const char *, int, const char *);
802d624471bSelowe extern void kstat_delete_byname_zone(const char *, int, const char *, zoneid_t);
803d624471bSelowe extern void kstat_named_init(kstat_named_t *, const char *, uchar_t);
804d624471bSelowe extern void kstat_timer_init(kstat_timer_t *, const char *);
8057c478bd9Sstevel@tonic-gate extern void kstat_waitq_enter(kstat_io_t *);
8067c478bd9Sstevel@tonic-gate extern void kstat_waitq_exit(kstat_io_t *);
8077c478bd9Sstevel@tonic-gate extern void kstat_runq_enter(kstat_io_t *);
8087c478bd9Sstevel@tonic-gate extern void kstat_runq_exit(kstat_io_t *);
8097c478bd9Sstevel@tonic-gate extern void kstat_waitq_to_runq(kstat_io_t *);
8107c478bd9Sstevel@tonic-gate extern void kstat_runq_back_to_waitq(kstat_io_t *);
8117c478bd9Sstevel@tonic-gate extern void kstat_timer_start(kstat_timer_t *);
8127c478bd9Sstevel@tonic-gate extern void kstat_timer_stop(kstat_timer_t *);
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate extern void kstat_zone_add(kstat_t *, zoneid_t);
8157c478bd9Sstevel@tonic-gate extern void kstat_zone_remove(kstat_t *, zoneid_t);
8167c478bd9Sstevel@tonic-gate extern int kstat_zone_find(kstat_t *, zoneid_t);
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate extern kstat_t *kstat_hold_bykid(kid_t kid, zoneid_t);
819d624471bSelowe extern kstat_t *kstat_hold_byname(const char *, int, const char *, zoneid_t);
8207c478bd9Sstevel@tonic-gate extern void kstat_rele(kstat_t *);
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate #endif	/* defined(_KERNEL) */
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate #endif
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate #endif	/* _SYS_KSTAT_H */
829