4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012 by Delphix. All rights reserved.
27 * Common routines for acquiring snapshots of kstats for
28 * iostat, mpstat, and vmstat.
41 #include <sys/types.h>
44 #include <sys/sysinfo.h>
45 #include <sys/processor.h>
49 /* No CPU present at this CPU position */
51 /* CPU belongs to no pset (we number this as "pset 0") */
54 #define CPU_ONLINE(s) ((s) == P_ONLINE || (s) == P_NOINTR)
55 /* will the CPU have kstats */
56 #define CPU_ACTIVE(c) (CPU_ONLINE((c)->cs_state) && (c)->cs_id != ID_NO_CPU)
57 /* IO device has no identified ID */
58 #define IODEV_NO_ID -1
59 /* no limit to iodevs to collect */
60 #define UNLIMITED_IODEVS ((size_t)-1)
62 #define NODATE 0 /* Default: No time stamp */
63 #define DDATE 1 /* Standard date format */
64 #define UDATE 2 /* Internal representation of Unix time */
68 /* All CPUs separately */
70 /* Aggregated processor sets */
72 /* sys-wide stats including aggregated CPU stats */
74 /* interrupt sources and counts */
75 SNAP_INTERRUPTS
= 1 << 3,
78 /* disk controller aggregates */
79 SNAP_CONTROLLERS
= 1 << 5,
80 /* mpxio L I (multipath) paths: -X: Lun,LunInitiator */
81 SNAP_IOPATHS_LI
= 1 << 6,
82 /* mpxio LTI (multipath) paths: -Y: Lun,LunTarget,LunTargetInitiator */
83 SNAP_IOPATHS_LTI
= 1 << 7,
84 /* disk error stats */
85 SNAP_IODEV_ERRORS
= 1 << 8,
86 /* pretty names for iodevs */
87 SNAP_IODEV_PRETTY
= 1 << 9,
88 /* devid for iodevs */
89 SNAP_IODEV_DEVID
= 1 << 10
93 /* may be ID_NO_CPU if no CPU present */
95 /* may be ID_NO_PSET if no pset */
97 /* as in p_online(2) */
99 /* stats for this CPU */
104 struct pset_snapshot
{
105 /* ID may be zero to indicate the "none set" */
107 /* number of CPUs in set */
109 /* the CPUs in this set */
110 struct cpu_snapshot
**ps_cpus
;
113 struct intr_snapshot
{
114 /* name of interrupt source */
115 char is_name
[KSTAT_STRLEN
];
116 /* total number of interrupts from this source */
120 struct sys_snapshot
{
121 sysinfo_t ss_sysinfo
;
123 struct nc_stats ss_nc
;
124 /* vm/sys stats aggregated across all CPUs */
127 /* ticks since boot */
132 /* order is significant (see sort_before()) */
134 IODEV_CONTROLLER
= 1 << 0,
136 IODEV_PARTITION
= 1 << 2,
139 IODEV_IOPATH_LT
= 1 << 5, /* synthetic LunTarget */
140 IODEV_IOPATH_LI
= 1 << 6, /* synthetic LunInitiator */
141 IODEV_IOPATH_LTI
= 1 << 7, /* LunTgtInitiator (pathinfo) */
142 IODEV_UNKNOWN
= 1 << 8
145 /* identify a disk, partition, etc. */
148 /* target id (for disks) */
149 char tid
[KSTAT_STRLEN
];
153 * Used for disks, partitions, tapes, nfs, controllers, iopaths
154 * Each entry can be a branch of a tree; for example, the disks
155 * of a controller constitute the children of the controller
156 * iodev_snapshot. This relationship is not strictly maintained
157 * if is_pretty can't be found.
159 struct iodev_snapshot
{
160 /* original kstat name */
161 char is_name
[KSTAT_STRLEN
];
163 enum iodev_type is_type
;
164 /* ID if meaningful */
165 struct iodev_id is_id
;
166 /* parent ID if meaningful */
167 struct iodev_id is_parent_id
;
168 /* user-friendly name if found */
170 /* device ID if applicable */
172 /* mount-point if applicable */
174 /* number of direct children */
176 /* children of this I/O device */
177 struct iodev_snapshot
*is_children
;
178 /* standard I/O stats */
180 /* iodev error stats */
182 /* creation time of the stats */
184 /* time at which iodev snapshot was taken */
185 hrtime_t is_snaptime
;
187 char is_module
[KSTAT_STRLEN
];
190 /* kstat (only used temporarily) */
192 struct iodev_snapshot
*is_prev
;
193 struct iodev_snapshot
*is_next
;
194 /* AVL structures to speedup insertion */
195 avl_tree_t
*avl_list
; /* list this element belongs to */
199 /* which iodevs to show. */
200 struct iodev_filter
{
201 /* nr. of iodevs to choose */
202 size_t if_max_iodevs
;
203 /* bit mask of enum io_types to allow */
204 int if_allowed_types
;
205 /* should we show floppy ? if_names can override this */
207 /* nr. of named iodevs */
212 /* The primary structure of a system snapshot. */
214 /* what types were *requested* */
215 enum snapshot_types s_types
;
217 struct cpu_snapshot
*s_cpus
;
219 struct pset_snapshot
*s_psets
;
221 struct intr_snapshot
*s_intrs
;
223 struct iodev_snapshot
*s_iodevs
;
224 size_t s_iodevs_is_name_maxlen
;
225 struct sys_snapshot s_sys
;
226 struct biostats s_biostats
;
227 size_t s_nr_active_cpus
;
230 /* print a message and exit with failure */
231 void fail(int do_perror
, char *message
, ...);
233 /* strdup str, or exit with failure */
234 char *safe_strdup(char *str
);
236 /* malloc successfully, or exit with failure */
237 void *safe_alloc(size_t size
);
240 * Copy a kstat from src to dst. If the source kstat contains no data,
241 * then set the destination kstat data to NULL and size to zero.
242 * Returns 0 on success.
244 int kstat_copy(const kstat_t
*src
, kstat_t
*dst
);
247 * Look up the named kstat, and give the ui64 difference i.e.
248 * new - old, or if old is NULL, return new.
250 uint64_t kstat_delta(kstat_t
*old
, kstat_t
*new, char *name
);
252 /* Return the number of ticks delta between two hrtime_t values. */
253 uint64_t hrtime_delta(hrtime_t old
, hrtime_t
new);
256 * Add the integer-valued stats from "src" to the
257 * existing ones in "dst". If "dst" does not contain
258 * stats, then a kstat_copy() is performed.
260 int kstat_add(const kstat_t
*src
, kstat_t
*dst
);
262 /* return the number of CPUs with kstats (i.e. present and online) */
263 int nr_active_cpus(struct snapshot
*ss
);
266 * Return the difference in CPU ticks between the two sys
269 uint64_t cpu_ticks_delta(kstat_t
*old
, kstat_t
*new);
272 * Open the kstat chain. Cannot fail.
274 kstat_ctl_t
*open_kstat(void);
277 * Return a struct snapshot based on the snapshot_types parameter
278 * passed in. iodev_filter may be NULL in which case all iodevs
279 * are selected if SNAP_IODEVS is passed.
281 struct snapshot
*acquire_snapshot(kstat_ctl_t
*, int, struct iodev_filter
*);
283 /* free a snapshot */
284 void free_snapshot(struct snapshot
*ss
);
286 typedef void (*snapshot_cb
)(void *old
, void *new, void *data
);
289 * Call the call back for each pair of data items of the given type,
290 * passing the data pointer passed in as well. If an item has been
291 * added, the first pointer will be NULL; if removed, the second pointer
294 * A non-zero return value indicates configuration has changed.
296 int snapshot_walk(enum snapshot_types type
, struct snapshot
*old
,
297 struct snapshot
*new, snapshot_cb cb
, void *data
);
300 * Output a line detailing any configuration changes such as a CPU
301 * brought online, etc, bracketed by << >>.
303 void snapshot_report_changes(struct snapshot
*old
, struct snapshot
*new);
305 /* Return non-zero if configuration has changed. */
306 int snapshot_has_changed(struct snapshot
*old
, struct snapshot
*new);
308 /* free the given iodev */
309 void free_iodev(struct iodev_snapshot
*iodev
);
311 /* acquire the I/O devices */
312 int acquire_iodevs(struct snapshot
*ss
, kstat_ctl_t
*kc
,
313 struct iodev_filter
*df
);
315 /* strcmp-style I/O device comparator */
316 int iodev_cmp(struct iodev_snapshot
*io1
, struct iodev_snapshot
*io2
);
318 /* sleep until *wakeup + interval, keeping cadence where desired */
319 void sleep_until(hrtime_t
*wakeup
, hrtime_t interval
, int forever
,
322 /* signal handler - so we can be aware of SIGCONT */
323 void cont_handler(int sig_number
);
325 /* Print a timestamp in either Unix or standard format. */
326 void print_timestamp(uint_t
);
332 #endif /* _STATCOMMON_H */