--- old/usr/src/cmd/stat/Makefile	2014-02-03 15:34:52.602014282 +0000
+++ new/usr/src/cmd/stat/Makefile	2014-02-03 15:34:52.614171212 +0000
@@ -27,7 +27,7 @@
 
 include ../Makefile.cmd
 
-SUBDIRS=	iostat mpstat vmstat fsstat kstat
+SUBDIRS=	arcstat iostat mpstat vmstat fsstat kstat
 
 all :=		TARGET = all
 install :=	TARGET = install
--- /dev/null	2014-02-03 15:34:53.000000000 +0000
+++ new/usr/src/cmd/stat/arcstat/Makefile	2014-02-03 15:34:52.996495713 +0000
@@ -0,0 +1,65 @@
+#
+# 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 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+PROG = arcstat
+OBJS = arcstat.o
+SRCS =$(OBJS:%.o=%.c) $(COMMON_SRCS)
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/stat/Makefile.stat
+
+LDLIBS += -lavl -lcmdutils -ldevinfo -lgen -lkstat
+CFLAGS += $(CCVERBOSE) -I${STATCOMMONDIR}
+CERRWARN += -_gcc=-Wno-uninitialized
+CERRWARN += -_gcc=-Wno-switch
+
+CPPFLAGS_sparc += -I$(SRC)/uts/sfmmu
+CPPFLAGS_sparc += -I$(SRC)/uts/sun4u/sunfire
+CPPFLAGS += $(CPPFLAGS_$(MACH))
+
+FILEMODE= 0555
+
+lint := LINTFLAGS = -muxs -I$(STATCOMMONDIR)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTPROG)
+
+$(PROG): $(OBJS) $(COMMON_OBJS)
+	$(LINK.c) -o $(PROG) $(OBJS) $(COMMON_OBJS) $(LDLIBS)
+	$(POST_PROCESS)
+
+%.o : $(STATCOMMONDIR)/%.c
+	$(COMPILE.c) -o $@ $<
+	$(POST_PROCESS_O)
+
+clean:
+	-$(RM) $(OBJS) $(COMMON_OBJS)
+
+lint: lint_SRCS
+
+include $(SRC)/cmd/Makefile.targ
--- /dev/null	2014-02-03 15:34:53.000000000 +0000
+++ new/usr/src/cmd/stat/arcstat/arcstat.c	2014-02-03 15:34:53.192304351 +0000
@@ -0,0 +1,796 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * Display ZFS ARC statistics.
+ *
+ * Based on work by Neelakanth Nadgir and Mike Harsch.
+ */
+#include <sys/list.h>
+#include <assert.h>
+#include <errno.h>
+#include <kstat.h>
+#include <libintl.h>
+#include <limits.h>
+#include <locale.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include "statcommon.h"
+
+char *cmdname = "arcstat";	/* Name of this command */
+int caught_cont = 0;		/* Have caught a SIGCONT */
+
+/* Saved command line options */
+static boolean_t g_fflg = B_FALSE;	/* custom header fields */
+static boolean_t g_oflg = B_FALSE;	/* write output file */
+static boolean_t g_rflg = B_FALSE;	/* raw output */
+static boolean_t g_vflg = B_FALSE;	/* verbose help */
+static boolean_t g_xflg = B_FALSE;	/* extended header */
+
+/* Time in seconds between snapshots */
+int		interval = 1;
+
+static list_t	fields_list;
+static char	*separator = "  ";
+static char	*output_file = NULL;
+static char	*hdr;
+
+typedef struct _arcstat_delta {
+	int64_t	ad_hits;
+	int64_t	ad_miss;
+	int64_t	ad_read;
+	int64_t	ad_hit_percent;
+	int64_t	ad_miss_percent;
+	int64_t	ad_dhit;
+	int64_t	ad_dmis;
+	int64_t	ad_dread;
+	int64_t	ad_dh_percent;
+	int64_t	ad_dm_percent;
+	int64_t	ad_phit;
+	int64_t	ad_pmis;
+	int64_t	ad_pread;
+	int64_t	ad_ph_percent;
+	int64_t	ad_pm_percent;
+	int64_t	ad_mhit;
+	int64_t	ad_mmis;
+	int64_t	ad_mread;
+	int64_t	ad_mh_percent;
+	int64_t	ad_mm_percent;
+	int64_t	ad_arcsz;
+	int64_t	ad_c;
+	int64_t	ad_mfu;
+	int64_t	ad_mru;
+	int64_t	ad_mfug;
+	int64_t	ad_mrug;
+	int64_t	ad_eskip;
+	int64_t	ad_rmiss;
+	int64_t	ad_mtxmis;
+} arcstat_delta_t;
+
+typedef struct arcstat_snapshot {
+        kstat_t as_arcstats;
+        uint64_t as_hits;
+        uint64_t as_misses;
+        uint64_t as_demand_data_hits;
+        uint64_t as_demand_data_misses;
+        uint64_t as_demand_metadata_hits;
+        uint64_t as_demand_metadata_misses;
+        uint64_t as_prefetch_data_hits;
+        uint64_t as_prefetch_data_misses;
+        uint64_t as_prefetch_metadata_hits;
+        uint64_t as_prefetch_metadata_misses;
+        uint64_t as_size;
+        uint64_t as_c;
+        uint64_t as_mfu_hits;
+        uint64_t as_mru_hits;
+        uint64_t as_mru_ghost_hits;
+        uint64_t as_mfu_ghost_hits;
+        uint64_t as_evict_skip;
+        uint64_t as_recycle_miss;
+        uint64_t as_mutex_miss;
+        uint64_t as_l2_hits;
+        uint64_t as_l2_misses;
+        uint64_t as_l2_size;
+        uint64_t as_l2_read_bytes;
+} arcstat_snapshot_t;
+
+typedef struct arcstat_hdr_field {
+	list_node_t	ahf_next;
+	char		*ahf_name;
+	struct arcstat_field *ahf_desc;
+} arcstat_hdr_field_t;
+
+typedef enum field_type {
+	as_time,
+	as_hits,
+	as_miss,
+	as_read,
+	as_hit_percent,
+	as_miss_percent,
+	as_dhit,
+	as_dmis,
+	as_dread,
+	as_dh_percent,
+	as_dm_percent,
+	as_phit,
+	as_pmis,
+	as_pread,
+	as_ph_percent,
+	as_pm_percent,
+	as_mhit,
+	as_mmis,
+	as_mread,
+	as_mh_percent,
+	as_mm_percent,
+	as_arcsz,
+	as_c,
+} field_type_t;
+
+/* XXX */
+struct arcstat_field {
+	char	*af_name;
+	char	*af_description;
+	int	af_length;
+	int	af_interval;
+	field_type_t	af_type;
+} arcstat_fields[] = {
+	{ "time", "Time", 8, -1, as_time },
+	{ "hits", "ARC reads per second", 4, 1000, as_hits },
+	{ "miss", "ARC misses per second", 4, 1000, as_miss },
+	{ "read", "Total ARC accesses per second", 4, 1000, as_read },
+	{ "hit%", "ARC Hit percentage", 4, 100, as_hit_percent },
+	{ "miss%", "ARC miss percentage", 5, 100, as_miss_percent },
+	{ "dhit", "Demand Data hits per second", 4, 1000, as_dhit },
+	{ "dmis", "Demand Data misses per second", 4, 1000, as_dmis },
+	{ "dread", "Demand data accesses per second", 5, 1000, as_dread },
+	{ "dh%", "Demand Data hit percentage", 3, 100, as_dh_percent  },
+	{ "dm%", "Demand Data miss percentage", 3, 100, as_dm_percent },
+	{ "phit", "Prefetch hits per second", 4, 1000, as_phit },
+	{ "pmis", "Prefetch misses per second", 4, 1000, as_pmis },
+	{ "ph%", "Prefetch hits percentage", 3, 100, as_ph_percent },
+	{ "pm%", "Prefetch miss percentage", 3, 100, as_pm_percent },
+	{ "mhit", "Metadata hits per second", 4, 1000, as_mhit },
+	{ "mmis", "Metadata misses per second", 4, 1000, as_mmis },
+	{ "mread", "Metadata accesses per second", 4, 1000, as_mread },
+	{ "mh%", "Metadata hit percentage", 3, 100, as_mh_percent },
+	{ "mm%", "Metadata miss percentage", 3, 100, as_mm_percent },
+	{ "arcsz", "ARC Size", 5, 1024, as_arcsz },
+	{ "c", "ARC Target Size", 4, 1024, as_c },
+	{ "mfu", "MFU List hits per second", 4, 1000 },
+	{ "mru", "MRU List hits per second", 4, 1000 },
+	{ "mfug", "MFU Ghost List hits per second", 4, 1000 },
+	{ "mrug", "MRU Ghost List hits per second", 4, 1000 },
+	{ "eskip", "evict_skip per second", 5, 1000 },
+	{ "mtxmis", "mutex_miss per second", 6, 1000 },
+	{ "rmis", "recycle_miss per second", 4, 1000 },
+	{ "pread", "Prefetch accesses per second", 5, 1000 },
+	{ "l2hits", "L2ARC hits per second", 6, 1000 },
+	{ "l2miss", "L2ARC misses per second", 6, 1000 },
+	{ "l2read", "Total L2ARC accesses per second", 6, 1000 },
+	{ "l2hit%", "L2ARC access hit percentage", 6, 100 },
+	{ "l2miss%", "L2ARC access miss percentage", 7, 100 },
+	{ "l2size", "Size of the L2ARC", 6, 1024 },
+	{ "l2bytes", "bytes read per second from the L2ARC", 7, 1024 },
+	{ NULL, NULL, -1, -1 },
+};
+
+/*
+ * Print usage.
+ */
+static void
+usage(void)
+{
+	(void) fprintf(stderr, gettext(
+	    "Usage: arcstat [-hvxr] [-f fields] [-o file] [-s string] "
+	    "[interval [count]]\n\n"));
+
+	if (g_vflg) {
+		int	i = 0;
+
+		(void) fprintf(stderr, gettext(
+		    "Field definitions are as follows:\n"));
+
+		for (;arcstat_fields[i].af_name != NULL; i++) {
+			(void) fprintf(stderr, "%11s : ",
+			    arcstat_fields[i].af_name);
+			(void) fprintf(stderr, "%s\n", gettext(
+			    arcstat_fields[i].af_description));
+		}
+	}
+}
+
+/*
+ * Print header.
+ */
+static void
+printhdr(int sig)
+{
+	arcstat_hdr_field_t	*hdr_field;
+
+	/*
+	 * Reenable the signal.
+	 */
+	if (sig)
+		(void) signal(SIGCONT, printhdr);
+	if (sig == SIGCONT)
+		caught_cont = 1;
+
+	/*
+	 * Print fields in fields list for this header.
+	 */
+	hdr_field = list_head(&fields_list);
+	while (hdr_field != NULL) {
+		if (g_rflg) {
+			printf("%s%s", hdr_field->ahf_name, separator);
+		} else {
+			printf("%*s%s", hdr_field->ahf_desc->af_length,
+			    hdr_field->ahf_name, separator);
+		}
+
+		hdr_field = list_next(&fields_list, hdr_field);
+	}
+
+	(void) putchar('\n');
+}
+
+/*
+ * Pretty print values.
+ */
+static void
+printvals(arcstat_delta_t *delta)
+{
+	arcstat_hdr_field_t	*hdr_field;
+
+#define	ARCSTAT_PRINT_VALUE(field, delta, value)	\
+	(void) printf("%*llu%s", field->ahf_desc->af_length, delta->ad_##value, separator);
+
+	/*
+	 * Print values for fields.
+	 */
+	hdr_field = list_head(&fields_list);
+	while (hdr_field != NULL) {
+		switch (hdr_field->ahf_desc->af_type) {
+		case as_time: {
+			time_t	t = time(NULL);
+			char	dstr[64];
+			char	*fmt = "%H:%M:%S";
+			int	len;
+
+			len = strftime(dstr, sizeof (dstr), fmt, localtime(&t));
+			if (len > 0)
+				(void) printf("%s%s", dstr, separator);
+			break;
+		};
+		case as_miss:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, miss);
+			break;
+		case as_read:
+			(void) printf("%*llu%s", hdr_field->ahf_desc->af_length, delta->ad_miss, separator);
+			break;
+		case as_hit_percent:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, hit_percent);
+			break;
+		case as_miss_percent:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, miss_percent);
+			break;
+		case as_dhit:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, dhit);
+			break;
+		case as_dmis:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, dmis);
+			break;
+		case as_dread:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, dread);
+			break;
+		case as_dh_percent:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, dh_percent);
+			break;
+		case as_dm_percent:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, dm_percent);
+			break;
+		case as_phit:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, phit);
+			break;
+		case as_pmis:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, pmis);
+			break;
+		case as_pread:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, pread);
+			break;
+		case as_ph_percent:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, ph_percent);
+			break;
+		case as_pm_percent:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, pm_percent);
+			break;
+		case as_mhit:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, mhit);
+			break;
+		case as_mmis:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, mmis);
+			break;
+		case as_mread:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, mread);
+			break;
+		case as_mh_percent:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, mh_percent);
+			break;
+		case as_mm_percent:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, mm_percent);
+			break;
+		case as_arcsz:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, arcsz);
+			break;
+		case as_c:
+			ARCSTAT_PRINT_VALUE(hdr_field, delta, c);
+			break;
+		default:
+			break;
+		}
+
+		// number_to_scaled_string
+
+		hdr_field = list_next(&fields_list, hdr_field);
+	}
+
+	(void) putchar('\n');
+}
+
+arcstat_snapshot_t *
+arcstat_acquire_snapshot(kstat_ctl_t *kc)
+{
+	arcstat_snapshot_t	*snapshot;
+        kstat_named_t		*knp;
+        kstat_t			*ksp;
+
+        if ((ksp = kstat_lookup(kc, "zfs", 0, "arcstats")) == NULL)
+                return (NULL);
+
+        if (kstat_read(kc, ksp, NULL) == -1)
+                return (NULL);
+
+	snapshot = safe_alloc(sizeof (arcstat_snapshot_t));
+
+/* XXX snapshot */
+#define ARC_KSTAT_DATA_LOOKUP(name)                                \
+        knp = (kstat_named_t *)kstat_data_lookup(ksp, #name);      \
+        if (knp == NULL)                                        \
+                return (NULL);                                 \
+        snapshot->as_##name = knp->value.ui64;
+
+        ARC_KSTAT_DATA_LOOKUP(hits);
+        ARC_KSTAT_DATA_LOOKUP(misses);
+        ARC_KSTAT_DATA_LOOKUP(demand_data_hits);
+        ARC_KSTAT_DATA_LOOKUP(demand_data_misses);
+        ARC_KSTAT_DATA_LOOKUP(demand_metadata_hits);
+        ARC_KSTAT_DATA_LOOKUP(demand_metadata_misses);
+        ARC_KSTAT_DATA_LOOKUP(prefetch_data_hits);
+        ARC_KSTAT_DATA_LOOKUP(prefetch_data_misses);
+        ARC_KSTAT_DATA_LOOKUP(prefetch_metadata_hits);
+        ARC_KSTAT_DATA_LOOKUP(prefetch_metadata_misses);
+        ARC_KSTAT_DATA_LOOKUP(size);
+        ARC_KSTAT_DATA_LOOKUP(c);
+        ARC_KSTAT_DATA_LOOKUP(mfu_hits);
+        ARC_KSTAT_DATA_LOOKUP(mru_hits);
+        ARC_KSTAT_DATA_LOOKUP(mru_ghost_hits);
+        ARC_KSTAT_DATA_LOOKUP(mfu_ghost_hits);
+        ARC_KSTAT_DATA_LOOKUP(evict_skip);
+        ARC_KSTAT_DATA_LOOKUP(recycle_miss);
+        ARC_KSTAT_DATA_LOOKUP(mutex_miss);
+        ARC_KSTAT_DATA_LOOKUP(l2_hits);
+        ARC_KSTAT_DATA_LOOKUP(l2_misses);
+        ARC_KSTAT_DATA_LOOKUP(l2_size);
+        ARC_KSTAT_DATA_LOOKUP(l2_read_bytes);
+
+        return (snapshot);
+}
+
+static void
+arcstat_free_snapshot(arcstat_snapshot_t *old)
+{
+}
+
+static void
+arcstat_chain_update(kstat_ctl_t *kc)
+{
+	int	ret;
+
+	ret = kstat_chain_update(kc);
+	if (ret != 0) {
+		(void) printf("<State Changed>\n");
+	}
+}
+
+static void
+free_field_list(list_t list)
+{
+	arcstat_hdr_field_t	*hdr_field;
+
+	hdr_field = list_head(&list);
+	while (hdr_field != NULL) {
+
+		hdr_field = list_next(&list, hdr_field);
+	}
+}
+
+static arcstat_delta_t *
+arcstat_calculate_delta(arcstat_snapshot_t *old, arcstat_snapshot_t *new)
+{
+	arcstat_delta_t	*delta;
+
+	assert(old != NULL && new != NULL);
+
+	delta = safe_alloc(sizeof (arcstat_delta_t));
+
+	(void) memset(delta, 0, sizeof (arcstat_delta_t));
+
+#define	ARC_SNAPSHOT_DIFF(O, N, S)			\
+	(N->as_##S - O->as_##S)
+
+	delta->ad_hits = ARC_SNAPSHOT_DIFF(old, new, hits) / interval;
+	delta->ad_miss = ARC_SNAPSHOT_DIFF(old, new, misses) / interval;
+
+	delta->ad_read = delta->ad_hits + delta->ad_miss;
+	if (delta->ad_read > 0) {
+		delta->ad_hit_percent = 100 * (delta->ad_hits / delta->ad_read);
+		delta->ad_miss_percent = 100 - delta->ad_hit_percent;
+	}
+
+	delta->ad_dhit = (ARC_SNAPSHOT_DIFF(old, new, demand_data_hits) +
+	    ARC_SNAPSHOT_DIFF(old, new, demand_metadata_hits)) / interval;
+	delta->ad_dmis = (ARC_SNAPSHOT_DIFF(old, new, demand_data_misses) +
+	    ARC_SNAPSHOT_DIFF(old, new, demand_metadata_misses)) / interval;
+
+	delta->ad_dread = delta->ad_dhit + delta->ad_dmis;
+	if (delta->ad_dread > 0) {
+		delta->ad_dh_percent = 100 * (delta->ad_dhit / delta->ad_dread);
+		delta->ad_dm_percent = 100 - delta->ad_dh_percent;
+	}
+
+	delta->ad_phit = (ARC_SNAPSHOT_DIFF(old, new, prefetch_data_hits) +
+	    ARC_SNAPSHOT_DIFF(old, new, prefetch_metadata_hits)) / interval;
+	delta->ad_pmis = (ARC_SNAPSHOT_DIFF(old, new, prefetch_data_misses) +
+	    ARC_SNAPSHOT_DIFF(old, new, prefetch_metadata_misses)) / interval;
+
+	delta->ad_pread = delta->ad_phit + delta->ad_pmis;
+	if (delta->ad_pread > 0) {
+		delta->ad_ph_percent = 100 * (delta->ad_phit / delta->ad_pread);
+		delta->ad_pm_percent = 100 - delta->ad_ph_percent;
+	}
+
+	delta->ad_mhit = (ARC_SNAPSHOT_DIFF(old, new, prefetch_metadata_hits) +
+	    ARC_SNAPSHOT_DIFF(old, new, demand_metadata_hits)) / interval;
+	delta->ad_mmis = (ARC_SNAPSHOT_DIFF(old, new,
+	    prefetch_metadata_misses) + ARC_SNAPSHOT_DIFF(old, new,
+	    demand_metadata_misses)) / interval;
+
+	delta->ad_mread = delta->ad_mhit + delta->ad_mmis;
+	if (delta->ad_mread > 0) {
+		delta->ad_mh_percent = 100 * (delta->ad_mhit / delta->ad_mread);
+		delta->ad_mm_percent = 100 - delta->ad_mh_percent;
+	}
+
+	delta->ad_arcsz = new->as_size;
+	delta->ad_c = new->as_c;
+	delta->ad_mfu = ARC_SNAPSHOT_DIFF(old, new, mfu_hits) / interval;
+	delta->ad_mru = ARC_SNAPSHOT_DIFF(old, new, mru_hits) / interval;
+	delta->ad_mfug = ARC_SNAPSHOT_DIFF(old, new, mfu_ghost_hits) /
+	    interval;
+	delta->ad_mrug = ARC_SNAPSHOT_DIFF(old, new, mru_ghost_hits) /
+	    interval;
+	delta->ad_eskip = ARC_SNAPSHOT_DIFF(old, new, evict_skip) / interval;
+	delta->ad_rmiss = ARC_SNAPSHOT_DIFF(old, new, recycle_miss) / interval;
+	delta->ad_mtxmis = ARC_SNAPSHOT_DIFF(old, new, mutex_miss) / interval;
+
+	/* XXX L2 cache */
+
+	return (delta);
+}
+
+int
+main(int argc, char **argv)
+{
+	int		c;
+	int		i = 0;
+	int		iter = 1;
+	char		*endptr;
+	int		infinite_cycles = 0;
+	kstat_ctl_t	*kc;
+	hrtime_t	start_n;
+	hrtime_t	period_n;
+	list_t		invalid_list;
+	list_t		incompt_list;
+	boolean_t	l2exist = B_FALSE;
+	arcstat_hdr_field_t	*hdr_field;
+	arcstat_snapshot_t	*old = NULL;
+	arcstat_snapshot_t	*new = NULL;
+
+
+	(void) setlocale(LC_ALL, "");
+#if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
+#define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it wasn't */
+#endif
+	(void) textdomain(TEXT_DOMAIN);
+
+	/*
+	 * Parse command line arguments.
+	 */
+	while ((c = getopt(argc, argv, "h?f:o:rs:vx")) != EOF) {
+		switch (c) {
+		case 'h':
+		case '?':
+			usage();
+			exit(0);
+			break;
+		case 'f':
+			g_fflg = B_TRUE;
+			hdr = safe_strdup(optarg);
+			break;
+		case 'o':
+			g_oflg = B_TRUE;
+			output_file = (char *)optarg;
+		case 'r':
+			g_rflg = B_TRUE;
+			break;
+		case 's':
+			separator = (char *)optarg;
+			break;
+		case 'v':
+			g_vflg = B_TRUE;
+			usage();
+			exit(0);
+			break;
+		case 'x':
+			g_xflg = B_TRUE;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Select the standard, extended or user supplied header fields.
+	 */
+	if (!g_fflg) {
+		if (g_xflg) {
+			hdr = safe_strdup("time,mfu,mru,mfug,mrug,eskip,mtxmis,rmis,dread,pread,read");
+		} else {
+			hdr = safe_strdup("time,read,miss,miss%,dmis,dm%,pmis,pm%,mmis,mm%,arcsz,c");
+		}
+	}
+
+	/*
+	 * Interval and count.
+	 */
+	if (argc > optind) {
+		interval = (int)strtol(argv[optind], &endptr, 10);
+		if (*endptr != NULL)
+			usage();
+		period_n = (hrtime_t)interval * NANOSEC;
+		if (argc > optind + 1) {
+			iter = (unsigned int)strtoul
+			    (argv[optind + 1], &endptr, 10);
+			if (*endptr != NULL || iter < 0)
+				usage();
+			if (iter == 0)
+				return (0);	/* XXX */
+		} else {
+			infinite_cycles = 1;
+		}
+	}
+
+	/*
+	 * Need to know if there is a L2 cache.
+	 */
+	kc = open_kstat();
+
+	/* XXX L2 cache */
+
+	/* Valid field names */
+	list_create(&fields_list, sizeof (arcstat_hdr_field_t),
+	    offsetof(arcstat_hdr_field_t, ahf_next));
+
+	/* Invalid field names */
+	list_create(&invalid_list, sizeof (arcstat_hdr_field_t),
+	    offsetof(arcstat_hdr_field_t, ahf_next));
+
+	/* Invalid field names if no L2 ARC */
+	list_create(&incompt_list, sizeof (arcstat_hdr_field_t),
+	    offsetof(arcstat_hdr_field_t, ahf_next));
+
+	while ((endptr = (char *)strsep(&hdr, ",")) != NULL) {
+		boolean_t	found_field = B_FALSE;
+		int		i = 0;
+
+		for (; arcstat_fields[i].af_name != NULL; i++) {
+			if (strcmp(arcstat_fields[i].af_name, endptr) == 0) {
+				found_field = B_TRUE;
+				break;
+			}
+		}
+
+		/*
+		 * Allocate a new header field and link it to the fields table.
+		 */
+		hdr_field = safe_alloc(sizeof (arcstat_hdr_field_t));
+		hdr_field->ahf_name = safe_strdup(endptr);
+		hdr_field->ahf_desc = &arcstat_fields[i];
+
+		list_link_init(&hdr_field->ahf_next);
+
+		/*
+		 * Add valid fields to fields_list or to the list of invalid fields.
+		 */
+		if (found_field) {
+			list_insert_tail(&fields_list, hdr_field);
+		} else {
+			list_insert_tail(&invalid_list, hdr_field);
+		}
+	}
+
+	/*
+	 * User supplied an invalid field per cmdline.
+	 */
+	if (!list_is_empty(&invalid_list)) {
+		(void) fprintf(stderr, "%s -- ", gettext(
+		    "Invalid column definition!"));
+
+		hdr_field = list_head(&invalid_list);
+		while (hdr_field != NULL) {
+			(void) fprintf(stderr, "%s ", hdr_field->ahf_name);
+
+			hdr_field = list_next(&invalid_list, hdr_field);
+		}
+
+		(void) fprintf(stderr, "\n\n");
+
+		//free_field_list(invalid_list);
+
+		usage();
+		exit(2);
+	}
+
+	/*
+	 * User supplied an L2 cache field, but we have no L2 cache.
+	 */
+	if (!list_is_empty(&incompt_list)) {
+		(void) fprintf(stderr, "%s -- ", gettext(
+		    "Incompatible field specified!"));
+
+		hdr_field = list_head(&incompt_list);
+		while (hdr_field != NULL) {
+			(void) fprintf(stderr, "%s ", hdr_field->ahf_name);
+
+			hdr_field = list_next(&incompt_list, hdr_field);
+		}
+
+		(void) fprintf(stderr, "\n\n");
+
+		usage();
+		exit(2);
+	}
+
+	/* We should have at least one valid field */
+	assert(!list_is_empty(&fields_list));
+
+	/*
+	 * If we need write to a file, try to open it.
+	 */
+	if (g_oflg) {
+
+	}
+
+	// (void) sigset(SIGCONT, printhdr);
+	/* Set up handler for SIGCONT */
+	if (signal(SIGCONT, cont_handler) == SIG_ERR)
+		fail(1, "signal failed");
+
+	start_n = gethrtime();
+
+	new = arcstat_acquire_snapshot(kc);
+	while (infinite_cycles || iter > 0) {
+		arcstat_delta_t	*delta;
+
+		arcstat_free_snapshot(old);
+		old = new;
+		new = arcstat_acquire_snapshot(kc);
+
+		arcstat_chain_update(kc);
+
+		/* XXX */
+		if (i % 20 == 0)
+			printhdr(0);
+		i++;
+
+		delta = arcstat_calculate_delta(old, new);
+		printvals(delta);
+
+		if (!infinite_cycles && --iter < 1)
+			break;
+
+		sleep_until(&start_n, period_n, infinite_cycles, &caught_cont);
+	}
+
+	(void) kstat_close(kc);
+
+	arcstat_free_snapshot(old);
+	arcstat_free_snapshot(new);
+
+	free(hdr);
+
+	return (0);
+}
+
+#define	NUMBER_WIDTH	64
+typedef char numbuf_t[NUMBER_WIDTH];
+
+/* Copied from du.c */
+static char *
+number_to_scaled_string(
+	numbuf_t buf,			/* put the result here */
+	unsigned long long number,	/* convert this number */
+	unsigned long long unit_from,	/* number of byes per input unit */
+	unsigned long long scale)	/* 1024 (-h) or 1000 (-H) */
+{
+	unsigned long long save = 0;
+	char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */
+	char *uom = M;	/* unit of measurement, initially 'K' (=M[0]) */
+
+	if ((long long)number == (long long) -1) {
+		(void) strcpy(buf, "-1");
+		return (buf);
+	}
+
+	/*
+	 * Convert number from unit_from to given scale (1024 or 1000)
+	 * This means multiply number with unit_from and divide by scale.
+	 * if number is large enough, we first divide and then multiply
+	 * to avoid an overflow (large enough here means 100 (rather arbitrary
+	 * value) times scale in order to reduce rounding errors)
+	 * otherwise, we first multiply and then divide to avoid an underflow.
+	 */
+	if (number >= 100L * scale) {
+		number = number / scale;
+		number = number * unit_from;
+	} else {
+		number = number * unit_from;
+		number = number / scale;
+	}
+
+	/*
+	 * Now we have number as a count of scale units.
+	 * Stop scaling when we reached exa bytes, then something is
+	 * probably wrong with our number.
+	 */
+	while ((number >= scale) && (*uom != 'E')) {
+		uom++;	/* Next unit of measurement */
+		save = number;
+		number = (number + (scale / 2)) / scale;
+	}
+
+	/* Check if we should output a decimal place after the point */
+	if (save && ((save / scale) < 10)) {
+		/* sprintf() will round for us */
+		float fnum = (float)save / scale;
+		(void) sprintf(buf, "%.1f%c", fnum, *uom);
+	} else {
+		(void) sprintf(buf, "%llu%c", number, *uom);
+	}
+	return (buf);
+}
--- old/usr/src/cmd/stat/common/acquire.c	2014-02-03 15:34:53.389528635 +0000
+++ new/usr/src/cmd/stat/common/acquire.c	2014-02-03 15:34:53.401479386 +0000
@@ -50,7 +50,7 @@
 
 static kstat_t *
 kstat_lookup_read(kstat_ctl_t *kc, char *module,
-		int instance, char *name)
+    int instance, char *name)
 {
 	kstat_t *ksp = kstat_lookup(kc, module, instance, name);
 	if (ksp == NULL)
--- old/usr/src/cmd/stat/common/common.c	2014-02-03 15:34:53.817022585 +0000
+++ new/usr/src/cmd/stat/common/common.c	2014-02-03 15:34:53.828958705 +0000
@@ -102,7 +102,7 @@
 		pause_tv.tv_sec = pause_left / NANOSEC;
 		pause_tv.tv_nsec = pause_left % NANOSEC;
 		status = nanosleep(&pause_tv, (struct timespec *)NULL);
-		if (status < 0)
+		if (status < 0) {
 			if (errno == EINTR) {
 				now = gethrtime();
 				pause_left = *wakeup - now;
@@ -112,6 +112,7 @@
 			} else {
 				fail(1, "nanosleep failed");
 			}
+		}
 	} while (status != 0);
 }
 
--- old/usr/src/cmd/stat/fsstat/Makefile	2014-02-03 15:34:54.216661069 +0000
+++ new/usr/src/cmd/stat/fsstat/Makefile	2014-02-03 15:34:54.228276861 +0000
@@ -35,7 +35,6 @@
 
 LDLIBS += -lkstat
 CFLAGS += $(CCVERBOSE) -I${STATCOMMONDIR}
-CERRWARN += -_gcc=-Wno-parentheses
 FILEMODE= 0555
 
 lint := LINTFLAGS = -muxs -I$(STATCOMMONDIR)
--- old/usr/src/cmd/stat/iostat/Makefile	2014-02-03 15:34:54.608344153 +0000
+++ new/usr/src/cmd/stat/iostat/Makefile	2014-02-03 15:34:54.620048308 +0000
@@ -34,7 +34,6 @@
 CFLAGS += $(CCVERBOSE) -I${STATCOMMONDIR}
 CERRWARN += -_gcc=-Wno-uninitialized
 CERRWARN += -_gcc=-Wno-switch
-CERRWARN += -_gcc=-Wno-parentheses
 FILEMODE= 0555
 
 lint := LINTFLAGS = -muxs -I$(STATCOMMONDIR)
--- old/usr/src/cmd/stat/kstat/Makefile	2014-02-03 15:34:55.011051261 +0000
+++ new/usr/src/cmd/stat/kstat/Makefile	2014-02-03 15:34:55.023085643 +0000
@@ -34,7 +34,6 @@
 CFLAGS += $(CCVERBOSE) -I${STATCOMMONDIR}
 CERRWARN += -_gcc=-Wno-uninitialized
 CERRWARN += -_gcc=-Wno-switch
-CERRWARN += -_gcc=-Wno-parentheses
 
 CPPFLAGS_sparc += -I$(SRC)/uts/sfmmu
 CPPFLAGS_sparc += -I$(SRC)/uts/sun4u/sunfire
--- old/usr/src/cmd/stat/mpstat/Makefile	2014-02-03 15:34:55.406653924 +0000
+++ new/usr/src/cmd/stat/mpstat/Makefile	2014-02-03 15:34:55.418123591 +0000
@@ -34,7 +34,6 @@
 CFLAGS += $(CCVERBOSE) -I${STATCOMMONDIR}
 CERRWARN += -_gcc=-Wno-uninitialized
 CERRWARN += -_gcc=-Wno-switch
-CERRWARN += -_gcc=-Wno-parentheses
 FILEMODE= 0555
 
 lint := LINTFLAGS = -muxs -I$(STATCOMMONDIR)
--- old/usr/src/cmd/stat/vmstat/Makefile	2014-02-03 15:34:55.808183530 +0000
+++ new/usr/src/cmd/stat/vmstat/Makefile	2014-02-03 15:34:55.819952895 +0000
@@ -34,7 +34,6 @@
 CFLAGS += $(CCVERBOSE) -I${STATCOMMONDIR}
 CERRWARN += -_gcc=-Wno-switch
 CERRWARN += -_gcc=-Wno-uninitialized
-CERRWARN += -_gcc=-Wno-parentheses
 FILEMODE= 0555
 
 lint := LINTFLAGS = -muxs -I$(STATCOMMONDIR)
--- /dev/null	2014-02-03 15:34:56.000000000 +0000
+++ new/usr/src/man/man1m/arcstat.1m	2014-02-03 15:34:56.208170236 +0000
@@ -0,0 +1,13 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source.  A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2014 David Hoeppner.  All rights reserved.
+.\"
--- /dev/null	2014-02-03 15:34:56.000000000 +0000
+++ new/usr/src/pkg/manifests/system-monitoring-arcstat.mf	2014-02-03 15:34:56.397409573 +0000
@@ -0,0 +1,29 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 David Hoeppner.  All rights reserved.
+#
+
+set name=pkg.fmri value=pkg:/system/monitoring/arcstat@$(PKGVERS)
+set name=pkg.description \
+    value=""
+set name=pkg.summary \
+    value=""
+set name=info.classification \
+    value="org.opensolaris.category.2008:System/Core"
+set name=variant.arch value=$(ARCH)
+dir path=usr group=sys
+dir path=usr/bin
+dir path=usr/share/man/man1
+file path=usr/bin/arcstat mode=0555
+file path=usr/share/man/man1m/arcstat.1m
+license lic_CDDL license=lic_CDDL
