summaryrefslogtreecommitdiff
path: root/cmd/stat/common/statcommon.h
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/stat/common/statcommon.h')
-rw-r--r--cmd/stat/common/statcommon.h328
1 files changed, 328 insertions, 0 deletions
diff --git a/cmd/stat/common/statcommon.h b/cmd/stat/common/statcommon.h
new file mode 100644
index 000000000000..9ee077431ddb
--- /dev/null
+++ b/cmd/stat/common/statcommon.h
@@ -0,0 +1,328 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Common routines for acquiring snapshots of kstats for
+ * iostat, mpstat, and vmstat.
+ */
+
+#ifndef _STATCOMMON_H
+#define _STATCOMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <kstat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/buf.h>
+#include <sys/dnlc.h>
+#include <sys/sysinfo.h>
+#include <sys/processor.h>
+#include <sys/pset.h>
+#include <sys/avl.h>
+
+/* No CPU present at this CPU position */
+#define ID_NO_CPU -1
+/* CPU belongs to no pset (we number this as "pset 0") */
+#define ID_NO_PSET 0
+/* CPU is usable */
+#define CPU_ONLINE(s) ((s) == P_ONLINE || (s) == P_NOINTR)
+/* will the CPU have kstats */
+#define CPU_ACTIVE(c) (CPU_ONLINE((c)->cs_state) && (c)->cs_id != ID_NO_CPU)
+/* IO device has no identified ID */
+#define IODEV_NO_ID -1
+/* no limit to iodevs to collect */
+#define UNLIMITED_IODEVS ((size_t)-1)
+
+#define NODATE 0 /* Default: No time stamp */
+#define DDATE 1 /* Standard date format */
+#define UDATE 2 /* Internal representation of Unix time */
+
+
+enum snapshot_types {
+ /* All CPUs separately */
+ SNAP_CPUS = 1 << 0,
+ /* Aggregated processor sets */
+ SNAP_PSETS = 1 << 1,
+ /* sys-wide stats including aggregated CPU stats */
+ SNAP_SYSTEM = 1 << 2,
+ /* interrupt sources and counts */
+ SNAP_INTERRUPTS = 1 << 3,
+ /* disk etc. stats */
+ SNAP_IODEVS = 1 << 4,
+ /* disk controller aggregates */
+ SNAP_CONTROLLERS = 1 << 5,
+ /* mpxio L I (multipath) paths: -X: Lun,LunInitiator */
+ SNAP_IOPATHS_LI = 1 << 6,
+ /* mpxio LTI (multipath) paths: -Y: Lun,LunTarget,LunTargetInitiator */
+ SNAP_IOPATHS_LTI = 1 << 7,
+ /* disk error stats */
+ SNAP_IODEV_ERRORS = 1 << 8,
+ /* pretty names for iodevs */
+ SNAP_IODEV_PRETTY = 1 << 9,
+ /* devid for iodevs */
+ SNAP_IODEV_DEVID = 1 << 10
+};
+
+struct cpu_snapshot {
+ /* may be ID_NO_CPU if no CPU present */
+ processorid_t cs_id;
+ /* may be ID_NO_PSET if no pset */
+ psetid_t cs_pset_id;
+ /* as in p_online(2) */
+ int cs_state;
+ /* stats for this CPU */
+ kstat_t cs_vm;
+ kstat_t cs_sys;
+};
+
+struct pset_snapshot {
+ /* ID may be zero to indicate the "none set" */
+ psetid_t ps_id;
+ /* number of CPUs in set */
+ size_t ps_nr_cpus;
+ /* the CPUs in this set */
+ struct cpu_snapshot **ps_cpus;
+};
+
+struct intr_snapshot {
+ /* name of interrupt source */
+ char is_name[KSTAT_STRLEN];
+ /* total number of interrupts from this source */
+ ulong_t is_total;
+};
+
+struct sys_snapshot {
+ sysinfo_t ss_sysinfo;
+ vminfo_t ss_vminfo;
+ struct nc_stats ss_nc;
+ /* vm/sys stats aggregated across all CPUs */
+ kstat_t ss_agg_vm;
+ kstat_t ss_agg_sys;
+ /* ticks since boot */
+ ulong_t ss_ticks;
+ long ss_deficit;
+};
+
+/* order is significant (see sort_before()) */
+enum iodev_type {
+ IODEV_CONTROLLER = 1 << 0,
+ IODEV_DISK = 1 << 1,
+ IODEV_PARTITION = 1 << 2,
+ IODEV_TAPE = 1 << 3,
+ IODEV_NFS = 1 << 4,
+ IODEV_IOPATH_LT = 1 << 5, /* synthetic LunTarget */
+ IODEV_IOPATH_LI = 1 << 6, /* synthetic LunInitiator */
+ IODEV_IOPATH_LTI = 1 << 7, /* LunTgtInitiator (pathinfo) */
+ IODEV_UNKNOWN = 1 << 8
+};
+
+/* identify a disk, partition, etc. */
+struct iodev_id {
+ int id;
+ /* target id (for disks) */
+ char tid[KSTAT_STRLEN];
+};
+
+/*
+ * Used for disks, partitions, tapes, nfs, controllers, iopaths
+ * Each entry can be a branch of a tree; for example, the disks
+ * of a controller constitute the children of the controller
+ * iodev_snapshot. This relationship is not strictly maintained
+ * if is_pretty can't be found.
+ */
+struct iodev_snapshot {
+ /* original kstat name */
+ char is_name[KSTAT_STRLEN];
+ /* type of kstat */
+ enum iodev_type is_type;
+ /* ID if meaningful */
+ struct iodev_id is_id;
+ /* parent ID if meaningful */
+ struct iodev_id is_parent_id;
+ /* user-friendly name if found */
+ char *is_pretty;
+ /* device ID if applicable */
+ char *is_devid;
+ /* mount-point if applicable */
+ char *is_dname;
+ /* number of direct children */
+ int is_nr_children;
+ /* children of this I/O device */
+ struct iodev_snapshot *is_children;
+ /* standard I/O stats */
+ kstat_io_t is_stats;
+ /* iodev error stats */
+ kstat_t is_errors;
+ /* creation time of the stats */
+ hrtime_t is_crtime;
+ /* time at which iodev snapshot was taken */
+ hrtime_t is_snaptime;
+ /* kstat module */
+ char is_module[KSTAT_STRLEN];
+ /* kstat instance */
+ int is_instance;
+ /* kstat (only used temporarily) */
+ kstat_t *is_ksp;
+ struct iodev_snapshot *is_prev;
+ struct iodev_snapshot *is_next;
+ /* AVL structures to speedup insertion */
+ avl_tree_t *avl_list; /* list this element belongs to */
+ avl_node_t avl_link;
+};
+
+/* which iodevs to show. */
+struct iodev_filter {
+ /* nr. of iodevs to choose */
+ size_t if_max_iodevs;
+ /* bit mask of enum io_types to allow */
+ int if_allowed_types;
+ /* should we show floppy ? if_names can override this */
+ int if_skip_floppy;
+ /* nr. of named iodevs */
+ size_t if_nr_names;
+ char **if_names;
+};
+
+/* The primary structure of a system snapshot. */
+struct snapshot {
+ /* what types were *requested* */
+ enum snapshot_types s_types;
+ size_t s_nr_cpus;
+ struct cpu_snapshot *s_cpus;
+ size_t s_nr_psets;
+ struct pset_snapshot *s_psets;
+ size_t s_nr_intrs;
+ struct intr_snapshot *s_intrs;
+ size_t s_nr_iodevs;
+ struct iodev_snapshot *s_iodevs;
+ size_t s_iodevs_is_name_maxlen;
+ struct sys_snapshot s_sys;
+ struct biostats s_biostats;
+};
+
+/* print a message and exit with failure */
+void fail(int do_perror, char *message, ...);
+
+/* strdup str, or exit with failure */
+char *safe_strdup(char *str);
+
+/* malloc successfully, or exit with failure */
+void *safe_alloc(size_t size);
+
+/*
+ * Copy a kstat from src to dst. If the source kstat contains no data,
+ * then set the destination kstat data to NULL and size to zero.
+ * Returns 0 on success.
+ */
+int kstat_copy(const kstat_t *src, kstat_t *dst);
+
+/*
+ * Look up the named kstat, and give the ui64 difference i.e.
+ * new - old, or if old is NULL, return new.
+ */
+uint64_t kstat_delta(kstat_t *old, kstat_t *new, char *name);
+
+/* Return the number of ticks delta between two hrtime_t values. */
+uint64_t hrtime_delta(hrtime_t old, hrtime_t new);
+
+/*
+ * Add the integer-valued stats from "src" to the
+ * existing ones in "dst". If "dst" does not contain
+ * stats, then a kstat_copy() is performed.
+ */
+int kstat_add(const kstat_t *src, kstat_t *dst);
+
+/* return the number of CPUs with kstats (i.e. present and online) */
+int nr_active_cpus(struct snapshot *ss);
+
+/*
+ * Return the difference in CPU ticks between the two sys
+ * kstats.
+ */
+uint64_t cpu_ticks_delta(kstat_t *old, kstat_t *new);
+
+/*
+ * Open the kstat chain. Cannot fail.
+ */
+kstat_ctl_t *open_kstat(void);
+
+/*
+ * Return a struct snapshot based on the snapshot_types parameter
+ * passed in. iodev_filter may be NULL in which case all iodevs
+ * are selected if SNAP_IODEVS is passed.
+ */
+struct snapshot *acquire_snapshot(kstat_ctl_t *, int, struct iodev_filter *);
+
+/* free a snapshot */
+void free_snapshot(struct snapshot *ss);
+
+typedef void (*snapshot_cb)(void *old, void *new, void *data);
+
+/*
+ * Call the call back for each pair of data items of the given type,
+ * passing the data pointer passed in as well. If an item has been
+ * added, the first pointer will be NULL; if removed, the second pointer
+ * will be NULL.
+ *
+ * A non-zero return value indicates configuration has changed.
+ */
+int snapshot_walk(enum snapshot_types type, struct snapshot *old,
+ struct snapshot *new, snapshot_cb cb, void *data);
+
+/*
+ * Output a line detailing any configuration changes such as a CPU
+ * brought online, etc, bracketed by << >>.
+ */
+void snapshot_report_changes(struct snapshot *old, struct snapshot *new);
+
+/* Return non-zero if configuration has changed. */
+int snapshot_has_changed(struct snapshot *old, struct snapshot *new);
+
+/* free the given iodev */
+void free_iodev(struct iodev_snapshot *iodev);
+
+/* acquire the I/O devices */
+int acquire_iodevs(struct snapshot *ss, kstat_ctl_t *kc,
+ struct iodev_filter *df);
+
+/* strcmp-style I/O device comparator */
+int iodev_cmp(struct iodev_snapshot *io1, struct iodev_snapshot *io2);
+
+/* sleep until *wakeup + interval, keeping cadence where desired */
+void sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever,
+ int *caught_cont);
+
+/* signal handler - so we can be aware of SIGCONT */
+void cont_handler(int sig_number);
+
+/* Print a timestamp in either Unix or standard format. */
+void print_timestamp(uint_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STATCOMMON_H */