xref: /onnv-gate/usr/src/cmd/stat/common/statcommon.h (revision 12607:2bc0f474d551)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52723Scth  * Common Development and Distribution License (the "License").
62723Scth  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12607Sjohn.levon@sun.com  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  *
240Sstevel@tonic-gate  * Common routines for acquiring snapshots of kstats for
250Sstevel@tonic-gate  * iostat, mpstat, and vmstat.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #ifndef	_STATCOMMON_H
290Sstevel@tonic-gate #define	_STATCOMMON_H
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #ifdef __cplusplus
320Sstevel@tonic-gate extern "C" {
330Sstevel@tonic-gate #endif
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #include <stdio.h>
360Sstevel@tonic-gate #include <kstat.h>
370Sstevel@tonic-gate #include <sys/time.h>
380Sstevel@tonic-gate #include <sys/types.h>
390Sstevel@tonic-gate #include <sys/buf.h>
400Sstevel@tonic-gate #include <sys/dnlc.h>
410Sstevel@tonic-gate #include <sys/sysinfo.h>
420Sstevel@tonic-gate #include <sys/processor.h>
430Sstevel@tonic-gate #include <sys/pset.h>
445957Swroche #include <sys/avl.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /* No CPU present at this CPU position */
470Sstevel@tonic-gate #define	ID_NO_CPU -1
480Sstevel@tonic-gate /* CPU belongs to no pset (we number this as "pset 0")  */
490Sstevel@tonic-gate #define	ID_NO_PSET 0
500Sstevel@tonic-gate /* CPU is usable */
510Sstevel@tonic-gate #define	CPU_ONLINE(s) ((s) == P_ONLINE || (s) == P_NOINTR)
520Sstevel@tonic-gate /* will the CPU have kstats */
530Sstevel@tonic-gate #define	CPU_ACTIVE(c) (CPU_ONLINE((c)->cs_state) && (c)->cs_id != ID_NO_CPU)
540Sstevel@tonic-gate /* IO device has no identified ID */
550Sstevel@tonic-gate #define	IODEV_NO_ID -1
560Sstevel@tonic-gate /* no limit to iodevs to collect */
570Sstevel@tonic-gate #define	UNLIMITED_IODEVS ((size_t)-1)
580Sstevel@tonic-gate 
599123Sjohn.levon@sun.com #define	NODATE	0	/* Default:  No time stamp */
609123Sjohn.levon@sun.com #define	DDATE	1	/* Standard date format */
619123Sjohn.levon@sun.com #define	UDATE	2	/* Internal representation of Unix time */
629123Sjohn.levon@sun.com 
639123Sjohn.levon@sun.com 
640Sstevel@tonic-gate enum snapshot_types {
650Sstevel@tonic-gate 	/* All CPUs separately */
660Sstevel@tonic-gate 	SNAP_CPUS 		= 1 << 0,
670Sstevel@tonic-gate 	/* Aggregated processor sets */
680Sstevel@tonic-gate 	SNAP_PSETS		= 1 << 1,
690Sstevel@tonic-gate 	/* sys-wide stats including aggregated CPU stats */
700Sstevel@tonic-gate 	SNAP_SYSTEM		= 1 << 2,
710Sstevel@tonic-gate 	/* interrupt sources and counts */
720Sstevel@tonic-gate 	SNAP_INTERRUPTS 	= 1 << 3,
730Sstevel@tonic-gate 	/* disk etc. stats */
74*12607Sjohn.levon@sun.com 	SNAP_IODEVS		= 1 << 4,
750Sstevel@tonic-gate 	/* disk controller aggregates */
76*12607Sjohn.levon@sun.com 	SNAP_CONTROLLERS	= 1 << 5,
772907Scth 	/* mpxio L I (multipath) paths: -X: Lun,LunInitiator */
78*12607Sjohn.levon@sun.com 	SNAP_IOPATHS_LI		= 1 << 6,
792907Scth 	/* mpxio LTI (multipath) paths: -Y: Lun,LunTarget,LunTargetInitiator */
80*12607Sjohn.levon@sun.com 	SNAP_IOPATHS_LTI	= 1 << 7,
810Sstevel@tonic-gate 	/* disk error stats */
82*12607Sjohn.levon@sun.com 	SNAP_IODEV_ERRORS	= 1 << 8,
830Sstevel@tonic-gate 	/* pretty names for iodevs */
84*12607Sjohn.levon@sun.com 	SNAP_IODEV_PRETTY	= 1 << 9,
852723Scth 	/* devid for iodevs */
86*12607Sjohn.levon@sun.com 	SNAP_IODEV_DEVID	= 1 << 10
870Sstevel@tonic-gate };
880Sstevel@tonic-gate 
890Sstevel@tonic-gate struct cpu_snapshot {
900Sstevel@tonic-gate 	/* may be ID_NO_CPU if no CPU present */
910Sstevel@tonic-gate 	processorid_t cs_id;
920Sstevel@tonic-gate 	/* may be ID_NO_PSET if no pset */
930Sstevel@tonic-gate 	psetid_t cs_pset_id;
940Sstevel@tonic-gate 	/* as in p_online(2) */
950Sstevel@tonic-gate 	int cs_state;
960Sstevel@tonic-gate 	/* stats for this CPU */
970Sstevel@tonic-gate 	kstat_t cs_vm;
980Sstevel@tonic-gate 	kstat_t cs_sys;
990Sstevel@tonic-gate };
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate struct pset_snapshot {
1020Sstevel@tonic-gate 	/* ID may be zero to indicate the "none set" */
1030Sstevel@tonic-gate 	psetid_t ps_id;
1040Sstevel@tonic-gate 	/* number of CPUs in set */
1050Sstevel@tonic-gate 	size_t ps_nr_cpus;
1060Sstevel@tonic-gate 	/* the CPUs in this set */
1070Sstevel@tonic-gate 	struct cpu_snapshot **ps_cpus;
1080Sstevel@tonic-gate };
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate struct intr_snapshot {
1110Sstevel@tonic-gate 	/* name of interrupt source */
1120Sstevel@tonic-gate 	char is_name[KSTAT_STRLEN];
1130Sstevel@tonic-gate 	/* total number of interrupts from this source */
1140Sstevel@tonic-gate 	ulong_t is_total;
1150Sstevel@tonic-gate };
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate struct sys_snapshot {
1180Sstevel@tonic-gate 	sysinfo_t ss_sysinfo;
1190Sstevel@tonic-gate 	vminfo_t ss_vminfo;
1200Sstevel@tonic-gate 	struct nc_stats ss_nc;
1210Sstevel@tonic-gate 	/* vm/sys stats aggregated across all CPUs */
1220Sstevel@tonic-gate 	kstat_t ss_agg_vm;
1230Sstevel@tonic-gate 	kstat_t ss_agg_sys;
1240Sstevel@tonic-gate 	/* ticks since boot */
1250Sstevel@tonic-gate 	ulong_t ss_ticks;
1260Sstevel@tonic-gate 	long ss_deficit;
1270Sstevel@tonic-gate };
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate /* order is significant (see sort_before()) */
1300Sstevel@tonic-gate enum iodev_type {
1310Sstevel@tonic-gate 	IODEV_CONTROLLER	= 1 << 0,
1320Sstevel@tonic-gate 	IODEV_DISK		= 1 << 1,
1330Sstevel@tonic-gate 	IODEV_PARTITION		= 1 << 2,
1340Sstevel@tonic-gate 	IODEV_TAPE		= 1 << 3,
1350Sstevel@tonic-gate 	IODEV_NFS		= 1 << 4,
1362907Scth 	IODEV_IOPATH_LT		= 1 << 5,	/* synthetic LunTarget */
1372907Scth 	IODEV_IOPATH_LI		= 1 << 6,	/* synthetic LunInitiator */
1382907Scth 	IODEV_IOPATH_LTI	= 1 << 7,	/* LunTgtInitiator (pathinfo) */
1392907Scth 	IODEV_UNKNOWN		= 1 << 8
1400Sstevel@tonic-gate };
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate /* identify a disk, partition, etc. */
1430Sstevel@tonic-gate struct iodev_id {
1440Sstevel@tonic-gate 	int id;
1450Sstevel@tonic-gate 	/* target id (for disks) */
1460Sstevel@tonic-gate 	char tid[KSTAT_STRLEN];
1470Sstevel@tonic-gate };
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate  * Used for disks, partitions, tapes, nfs, controllers, iopaths
1510Sstevel@tonic-gate  * Each entry can be a branch of a tree; for example, the disks
1520Sstevel@tonic-gate  * of a controller constitute the children of the controller
1530Sstevel@tonic-gate  * iodev_snapshot. This relationship is not strictly maintained
1540Sstevel@tonic-gate  * if is_pretty can't be found.
1550Sstevel@tonic-gate  */
1560Sstevel@tonic-gate struct iodev_snapshot {
1570Sstevel@tonic-gate 	/* original kstat name */
1580Sstevel@tonic-gate 	char is_name[KSTAT_STRLEN];
1592907Scth 	/* type of kstat */
1600Sstevel@tonic-gate 	enum iodev_type is_type;
1610Sstevel@tonic-gate 	/* ID if meaningful */
1620Sstevel@tonic-gate 	struct iodev_id is_id;
1630Sstevel@tonic-gate 	/* parent ID if meaningful */
1640Sstevel@tonic-gate 	struct iodev_id is_parent_id;
1650Sstevel@tonic-gate 	/* user-friendly name if found */
1660Sstevel@tonic-gate 	char *is_pretty;
1670Sstevel@tonic-gate 	/* device ID if applicable */
1680Sstevel@tonic-gate 	char *is_devid;
1690Sstevel@tonic-gate 	/* mount-point if applicable */
1700Sstevel@tonic-gate 	char *is_dname;
1710Sstevel@tonic-gate 	/* number of direct children */
1720Sstevel@tonic-gate 	int is_nr_children;
1730Sstevel@tonic-gate 	/* children of this I/O device */
1740Sstevel@tonic-gate 	struct iodev_snapshot *is_children;
1750Sstevel@tonic-gate 	/* standard I/O stats */
1760Sstevel@tonic-gate 	kstat_io_t is_stats;
1770Sstevel@tonic-gate 	/* iodev error stats */
1780Sstevel@tonic-gate 	kstat_t is_errors;
1790Sstevel@tonic-gate 	/* creation time of the stats */
1800Sstevel@tonic-gate 	hrtime_t is_crtime;
1810Sstevel@tonic-gate 	/* time at which iodev snapshot was taken */
1820Sstevel@tonic-gate 	hrtime_t is_snaptime;
1830Sstevel@tonic-gate 	/* kstat module */
1840Sstevel@tonic-gate 	char is_module[KSTAT_STRLEN];
1850Sstevel@tonic-gate 	/* kstat instance */
1860Sstevel@tonic-gate 	int is_instance;
1870Sstevel@tonic-gate 	/* kstat (only used temporarily) */
1880Sstevel@tonic-gate 	kstat_t *is_ksp;
1890Sstevel@tonic-gate 	struct iodev_snapshot *is_prev;
1900Sstevel@tonic-gate 	struct iodev_snapshot *is_next;
1915957Swroche 	/* AVL structures to speedup insertion */
1925957Swroche 	avl_tree_t *avl_list;	/* list this element belongs to */
1935957Swroche 	avl_node_t avl_link;
1940Sstevel@tonic-gate };
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate /* which iodevs to show. */
1970Sstevel@tonic-gate struct iodev_filter {
1980Sstevel@tonic-gate 	/* nr. of iodevs to choose */
1990Sstevel@tonic-gate 	size_t if_max_iodevs;
2000Sstevel@tonic-gate 	/* bit mask of enum io_types to allow */
2010Sstevel@tonic-gate 	int if_allowed_types;
2020Sstevel@tonic-gate 	/* should we show floppy ? if_names can override this */
2030Sstevel@tonic-gate 	int if_skip_floppy;
2040Sstevel@tonic-gate 	/* nr. of named iodevs */
2050Sstevel@tonic-gate 	size_t if_nr_names;
2060Sstevel@tonic-gate 	char **if_names;
2070Sstevel@tonic-gate };
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate /* The primary structure of a system snapshot. */
2100Sstevel@tonic-gate struct snapshot {
2110Sstevel@tonic-gate 	/* what types were *requested* */
2120Sstevel@tonic-gate 	enum snapshot_types s_types;
2130Sstevel@tonic-gate 	size_t s_nr_cpus;
2140Sstevel@tonic-gate 	struct cpu_snapshot *s_cpus;
2150Sstevel@tonic-gate 	size_t s_nr_psets;
2160Sstevel@tonic-gate 	struct pset_snapshot *s_psets;
2170Sstevel@tonic-gate 	size_t s_nr_intrs;
2180Sstevel@tonic-gate 	struct intr_snapshot *s_intrs;
2190Sstevel@tonic-gate 	size_t s_nr_iodevs;
2200Sstevel@tonic-gate 	struct iodev_snapshot *s_iodevs;
2212907Scth 	size_t s_iodevs_is_name_maxlen;
2220Sstevel@tonic-gate 	struct sys_snapshot s_sys;
2230Sstevel@tonic-gate 	struct biostats s_biostats;
2240Sstevel@tonic-gate };
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate /* print a message and exit with failure */
2270Sstevel@tonic-gate void fail(int do_perror, char *message, ...);
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate /* strdup str, or exit with failure */
2300Sstevel@tonic-gate char *safe_strdup(char *str);
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate /* malloc successfully, or exit with failure */
2330Sstevel@tonic-gate void *safe_alloc(size_t size);
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate /*
2360Sstevel@tonic-gate  * Copy a kstat from src to dst. If the source kstat contains no data,
2370Sstevel@tonic-gate  * then set the destination kstat data to NULL and size to zero.
2380Sstevel@tonic-gate  * Returns 0 on success.
2390Sstevel@tonic-gate  */
2400Sstevel@tonic-gate int kstat_copy(const kstat_t *src, kstat_t *dst);
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate /*
2430Sstevel@tonic-gate  * Look up the named kstat, and give the ui64 difference i.e.
2440Sstevel@tonic-gate  * new - old, or if old is NULL, return new.
2450Sstevel@tonic-gate  */
2460Sstevel@tonic-gate uint64_t kstat_delta(kstat_t *old, kstat_t *new, char *name);
2470Sstevel@tonic-gate 
2482907Scth /* Return the number of ticks delta between two hrtime_t values. */
2492907Scth uint64_t hrtime_delta(hrtime_t old, hrtime_t new);
2502907Scth 
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate  * Add the integer-valued stats from "src" to the
2530Sstevel@tonic-gate  * existing ones in "dst". If "dst" does not contain
2540Sstevel@tonic-gate  * stats, then a kstat_copy() is performed.
2550Sstevel@tonic-gate  */
2560Sstevel@tonic-gate int kstat_add(const kstat_t *src, kstat_t *dst);
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate /* return the number of CPUs with kstats (i.e. present and online) */
2590Sstevel@tonic-gate int nr_active_cpus(struct snapshot *ss);
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate  * Return the difference in CPU ticks between the two sys
2630Sstevel@tonic-gate  * kstats.
2640Sstevel@tonic-gate  */
2650Sstevel@tonic-gate uint64_t cpu_ticks_delta(kstat_t *old, kstat_t *new);
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate /*
2680Sstevel@tonic-gate  * Open the kstat chain. Cannot fail.
2690Sstevel@tonic-gate  */
2700Sstevel@tonic-gate kstat_ctl_t *open_kstat(void);
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate /*
2730Sstevel@tonic-gate  * Return a struct snapshot based on the snapshot_types parameter
2740Sstevel@tonic-gate  * passed in. iodev_filter may be NULL in which case all iodevs
2750Sstevel@tonic-gate  * are selected if SNAP_IODEVS is passed.
2760Sstevel@tonic-gate  */
2770Sstevel@tonic-gate struct snapshot *acquire_snapshot(kstat_ctl_t *, int, struct iodev_filter *);
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate /* free a snapshot */
2800Sstevel@tonic-gate void free_snapshot(struct snapshot *ss);
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate typedef void (*snapshot_cb)(void *old, void *new, void *data);
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate /*
2850Sstevel@tonic-gate  * Call the call back for each pair of data items of the given type,
2860Sstevel@tonic-gate  * passing the data pointer passed in as well. If an item has been
2870Sstevel@tonic-gate  * added, the first pointer will be NULL; if removed, the second pointer
2880Sstevel@tonic-gate  * will be NULL.
2890Sstevel@tonic-gate  *
2900Sstevel@tonic-gate  * A non-zero return value indicates configuration has changed.
2910Sstevel@tonic-gate  */
2920Sstevel@tonic-gate int snapshot_walk(enum snapshot_types type, struct snapshot *old,
2930Sstevel@tonic-gate     struct snapshot *new, snapshot_cb cb, void *data);
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate  * Output a line detailing any configuration changes such as a CPU
2970Sstevel@tonic-gate  * brought online, etc, bracketed by << >>.
2980Sstevel@tonic-gate  */
2990Sstevel@tonic-gate void snapshot_report_changes(struct snapshot *old, struct snapshot *new);
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate /* Return non-zero if configuration has changed. */
3020Sstevel@tonic-gate int snapshot_has_changed(struct snapshot *old, struct snapshot *new);
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate /* free the given iodev */
3050Sstevel@tonic-gate void free_iodev(struct iodev_snapshot *iodev);
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate /* acquire the I/O devices */
3080Sstevel@tonic-gate int acquire_iodevs(struct snapshot *ss, kstat_ctl_t *kc,
3090Sstevel@tonic-gate     struct iodev_filter *df);
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate /* strcmp-style I/O device comparator */
3120Sstevel@tonic-gate int iodev_cmp(struct iodev_snapshot *io1, struct iodev_snapshot *io2);
3130Sstevel@tonic-gate 
3145461Stc35445 /* sleep until *wakeup + interval, keeping cadence where desired */
3155461Stc35445 void sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever,
3165461Stc35445     int *caught_cont);
3175461Stc35445 
3185461Stc35445 /* signal handler - so we can be aware of SIGCONT */
3195461Stc35445 void cont_handler(int sig_number);
3205461Stc35445 
3219123Sjohn.levon@sun.com /* Print a timestamp in either Unix or standard format. */
32210265SKrishnendu.Sadhukhan@Sun.COM void print_timestamp(uint_t);
3239123Sjohn.levon@sun.com 
3240Sstevel@tonic-gate #ifdef __cplusplus
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate #endif
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate #endif /* _STATCOMMON_H */
329