changeset 14992:0bfb555837b4

Merge branch 'master' into core Conflicts: usr/src/man/man2/Makefile usr/src/man/man2/chmod.2 usr/src/man/man2/link.2 usr/src/man/man2/mkdir.2 usr/src/man/man2/mknod.2 usr/src/man/man2/readlink.2 usr/src/man/man2/symlink.2 usr/src/man/man2/utimes.2 usr/src/man/man3c/Makefile usr/src/man/man3c/mkfifo.3c usr/src/man/man3c/pthread_mutex_consistent.3c usr/src/man/man3c/pthread_mutexattr_getrobust.3c usr/src/man/man3lib/libc.3lib usr/src/man/man9f/Intro.9f usr/src/pkg/manifests/system-kernel.man2.inc
author Garrett D'Amore <garrett@damore.org>
date Sun, 04 Jan 2015 07:19:22 -0800
parents 2aced5917cc3 (current diff) fe89d6147073 (diff)
children 3c9a075f736c
files usr/src/cmd/Makefile usr/src/cmd/mailx/Makefile usr/src/cmd/ypcmd/ypinit.sh usr/src/cmd/zoneadm/zoneadm.c usr/src/head/netdb.h usr/src/man/man1/Makefile usr/src/man/man2/Makefile usr/src/man/man2/chmod.2 usr/src/man/man2/link.2 usr/src/man/man2/mkdir.2 usr/src/man/man2/mknod.2 usr/src/man/man2/readlink.2 usr/src/man/man2/symlink.2 usr/src/man/man2/utimes.2 usr/src/man/man3c/Makefile usr/src/man/man3c/mkfifo.3c usr/src/man/man3c/pthread_mutex_consistent.3c usr/src/man/man3c/pthread_mutexattr_getrobust.3c usr/src/man/man3lib/libc.3lib usr/src/man/man9f/Intro.9f usr/src/man/man9f/Makefile usr/src/man/man9f/canputnext.9f usr/src/pkg/manifests/SUNWcs.man1.inc usr/src/pkg/manifests/system-kernel.man2.inc usr/src/pkg/manifests/system-kernel.man9f.inc usr/src/pkg/manifests/system-library.man3c.inc
diffstat 101 files changed, 5035 insertions(+), 2070 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/Makefile	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/Makefile	Sun Jan 04 07:19:22 2015 -0800
@@ -808,6 +808,7 @@
 ksh:	shcomp isaexec
 mdb:	terminfo
 print:	lp
+fmt:	mailx
 
 $(FIRST_SUBDIRS) $(BWOSDIRS) $(SUBDIRS) $(AUDITSUBDIRS): FRC
 	@if [ -f $@/Makefile  ]; then \
--- a/usr/src/cmd/dd/dd.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/dd/dd.c	Sun Jan 04 07:19:22 2015 -0800
@@ -147,6 +147,7 @@
 static off_t	oseekn;	/* number of output records to seek past */
 static unsigned long long	count;	/* number of input records to copy */
 			/* (0 = all) */
+static boolean_t ecount;	/* explicit count given */
 static int	trantype; /* BSD or SVr4 compatible EBCDIC */
 
 static char		*string;	/* command arg pointer */
@@ -571,6 +572,7 @@
 		if (match("count="))
 		{
 			count = number(BIG);
+			ecount = B_TRUE;
 			continue;
 		}
 		if (match("files="))
@@ -1009,8 +1011,7 @@
 			nstats = 0;
 		}
 
-		if ((count == 0) || (nifr+nipr < count))
-		{
+		if ((count == 0 && ecount == B_FALSE) || (nifr+nipr < count)) {
 		/* If proceed on error is enabled, zero the input buffer */
 
 			if (cflag&NERR)
--- a/usr/src/cmd/fmt/Makefile	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/fmt/Makefile	Sun Jan 04 07:19:22 2015 -0800
@@ -33,6 +33,7 @@
 
 include ../Makefile.cmd
 
+LDLIBS += -lcmdutils
 CERRWARN += -_gcc=-Wno-switch
 CERRWARN += -_gcc=-Wno-parentheses
 
--- a/usr/src/cmd/fmt/fmt.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/fmt/fmt.c	Sun Jan 04 07:19:22 2015 -0800
@@ -86,7 +86,7 @@
 
 void (*(split))(wchar_t []);
 extern int scrwidth(wchar_t);
-extern int ishead(char []);
+extern boolean_t is_headline(const char *);
 
 
 static void fill_hdrbuf(wchar_t []);
@@ -240,13 +240,13 @@
 			}
 			/*
 			 * Need to convert string from wchar_t to char,
-			 * since this is what ishead() expects.  Since we
+			 * since this is what is_headline() expects.  Since we
 			 * only want to make sure cp points to a "From" line
 			 * of the email, we don't have to alloc
 			 * BUFSIZ * MB_LEN_MAX to cbuf.
 			 */
 			wcstombs(cbuf, cp, (BUFSIZ - 1));
-			if (ishead(cbuf)) {
+			if (is_headline(cbuf) == B_TRUE) {
 				hdr_state = in_hdr;
 				fill_hdrbuf(canonb);
 			} else {
--- a/usr/src/cmd/ipf/lib/common/load_hash.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/lib/common/load_hash.c	Sun Jan 04 07:19:22 2015 -0800
@@ -7,15 +7,16 @@
  *
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include "ipf.h"
 #include "netinet/ip_lookup.h"
 #include "netinet/ip_htable.h"
+#include "ipfzone.h"
 
 static int hashfd = -1;
 
@@ -35,6 +36,10 @@
 		hashfd = open(IPLOOKUP_NAME, O_RDWR);
 	if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
 		return -1;
+	if (setzone(hashfd) != 0) {
+		close(hashfd);
+		return -1;
+	}
 
 	for (n = 0, a = list; a != NULL; a = a->ipe_next)
 		n++;
--- a/usr/src/cmd/ipf/lib/common/load_hashnode.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/lib/common/load_hashnode.c	Sun Jan 04 07:19:22 2015 -0800
@@ -7,15 +7,16 @@
  *
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include "ipf.h"
 #include "netinet/ip_lookup.h"
 #include "netinet/ip_htable.h"
+#include "ipfzone.h"
 
 static int hashfd = -1;
 
@@ -34,6 +35,10 @@
 		hashfd = open(IPLOOKUP_NAME, O_RDWR);
 	if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
 		return -1;
+	if (setzone(hashfd) != 0) {
+		close(hashfd);
+		return -1;
+	}
 
 	op.iplo_type = IPLT_HASH;
 	op.iplo_unit = unit;
--- a/usr/src/cmd/ipf/lib/common/load_pool.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/lib/common/load_pool.c	Sun Jan 04 07:19:22 2015 -0800
@@ -7,15 +7,16 @@
  *
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include "ipf.h"
 #include "netinet/ip_lookup.h"
 #include "netinet/ip_pool.h"
+#include "ipfzone.h"
 
 static int poolfd = -1;
 
@@ -32,6 +33,10 @@
 		poolfd = open(IPLOOKUP_NAME, O_RDWR);
 	if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
 		return -1;
+	if (setzone(poolfd) != 0) {
+		close(poolfd);
+		return -1;
+	}
 
 	op.iplo_unit = plp->ipo_unit;
 	op.iplo_type = IPLT_POOL;
--- a/usr/src/cmd/ipf/lib/common/load_poolnode.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/lib/common/load_poolnode.c	Sun Jan 04 07:19:22 2015 -0800
@@ -4,6 +4,8 @@
  * See the IPFILTER.LICENCE file for details on licencing.
  *
  * $Id: load_poolnode.c,v 1.3.2.1 2004/03/06 14:33:29 darrenr Exp $
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #include <fcntl.h>
@@ -11,6 +13,7 @@
 #include "ipf.h"
 #include "netinet/ip_lookup.h"
 #include "netinet/ip_pool.h"
+#include "ipfzone.h"
 
 static int poolfd = -1;
 
@@ -29,6 +32,10 @@
 		poolfd = open(IPLOOKUP_NAME, O_RDWR);
 	if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
 		return -1;
+	if (setzone(poolfd) != 0) {
+		close(poolfd);
+		return -1;
+	}
 
 	op.iplo_unit = role;
 	op.iplo_type = IPLT_POOL;
--- a/usr/src/cmd/ipf/tools/Makefile.tools	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/tools/Makefile.tools	Sun Jan 04 07:19:22 2015 -0800
@@ -24,17 +24,19 @@
 #
 # Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 #
+# Copyright (c) 2012, Joyent Inc. All rights reserved.
+#
 
 PROG=		ipf ipfs ipmon ipnat ippool ipfstat
 IPFPROG=	ipftest
 
-IPF_OBJS=	ipf.o ipfcomp.o ipf_y.o ipf_l.o
-IPFS_OBJS=	ipfs.o
-IPFSTAT_OBJS=	ipfstat.o
-IPMON_OBJS=	ipmon.o ipmon_y.o ipmon_l.o
-IPNAT_OBJS=	ipnat.o ipnat_y.o ipnat_l.o
-IPPOOL_OBJS=	ippool.o ippool_y.o ippool_l.o
-IPFTEST_OBJS=	ipftest.o  \
+IPF_OBJS=	ipf.o ipfcomp.o ipfzone.o ipf_y.o ipf_l.o
+IPFS_OBJS=	ipfs.o ipfzone.o
+IPFSTAT_OBJS=	ipfstat.o ipfzone.o
+IPMON_OBJS=	ipmon.o ipfzone.o ipmon_y.o ipmon_l.o
+IPNAT_OBJS=	ipnat.o ipfzone.o ipnat_y.o ipnat_l.o
+IPPOOL_OBJS=	ippool.o ipfzone.o ippool_y.o ippool_l.o
+IPFTEST_OBJS=	ipftest.o ipfzone.o \
 		ip_fil.o ip_state.o ip_compat.o \
 		ip_frag.o ip_nat.o ip_nat6.o fil.o \
 		ip_htable.o ip_lookup.o \
--- a/usr/src/cmd/ipf/tools/ipf.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/tools/ipf.c	Sun Jan 04 07:19:22 2015 -0800
@@ -5,6 +5,8 @@
  *
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #ifdef	__FreeBSD__
@@ -20,6 +22,7 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include "netinet/ipl.h"
+#include "ipfzone.h"
 
 #if !defined(lint)
 static const char sccsid[] = "@(#)ipf.c	1.23 6/5/96 (C) 1993-2000 Darren Reed";
@@ -62,9 +65,9 @@
 
 static void usage()
 {
-	fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n",
+	fprintf(stderr, "usage: ipf [-6AdDEGInoPrRsvVyzZ] %s %s %s",
 		"[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]",
-		"[-f filename] [-T <tuneopts>]");
+		"[-f filename] [-T <tuneopts>] [zonename]\n");
 	exit(1);
 }
 
@@ -74,11 +77,21 @@
 char *argv[];
 {
 	int c;
+	const char *optstr = "6Ac:dDEf:F:GIl:noPrRsT:vVyzZ";
 
 	if (argc < 2)
 		usage();
 
-	while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) {
+	/*
+	 * We need to set the zone name before calling the functions
+	 * in the switch statement below. Note that ipf.c differs from the other
+	 * tools in the ipfilter suite: the zone name is specified as the
+	 * last argument, while the other tools use the -z option. ipf
+	 * already has a -z option, so the last argument is used instead.
+	 */
+	getzonearg(argc, argv, optstr);
+
+	while ((c = getopt(argc, argv, optstr)) != -1) {
 		switch (c)
 		{
 		case '?' :
@@ -111,6 +124,9 @@
 		case 'F' :
 			flushfilter(optarg);
 			break;
+		case 'G' :
+			/* Already handled by getzonearg() above */
+			break;
 		case 'I' :
 			opts ^= OPT_INACTIVE;
 			break;
@@ -187,6 +203,12 @@
 		if ((fd = open(ipfdev, O_RDWR)) == -1)
 			if ((fd = open(ipfdev, O_RDONLY)) == -1)
 				perror("open device");
+
+	if (setzone(fd) != 0) {
+		close(fd);
+		return -2;
+	}
+
 	return fd;
 }
 
@@ -307,6 +329,11 @@
 		if (opts & OPT_VERBOSE)
 			printf("set state log flag\n");
 		xfd = open(IPSTATE_NAME, O_RDWR);
+		if (xfd >= 0 && setzone(xfd) != 0) {
+			close(xfd);
+			xfd = -1;
+		}
+
 		if (xfd >= 0) {
 			logopt = 0;
 			if (ioctl(xfd, SIOCGETLG, &logopt))
@@ -324,6 +351,11 @@
 		if (opts & OPT_VERBOSE)
 			printf("set nat log flag\n");
 		xfd = open(IPNAT_NAME, O_RDWR);
+		if (xfd >= 0 && setzone(xfd) != 0) {
+			close(xfd);
+			xfd = -1;
+		}
+
 		if (xfd >= 0) {
 			logopt = 0;
 			if (ioctl(xfd, SIOCGETLG, &logopt))
@@ -516,6 +548,11 @@
 		return 1;
 	}
 
+	if (setzone(vfd) != 0) {
+		close(vfd);
+		return 1;
+	}
+
 	if (ioctl(vfd, SIOCGETFS, &ipfo)) {
 		perror("ioctl(SIOCGETFS)");
 		close(vfd);
--- a/usr/src/cmd/ipf/tools/ipfs.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/tools/ipfs.c	Sun Jan 04 07:19:22 2015 -0800
@@ -5,6 +5,8 @@
  *
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #ifdef	__FreeBSD__
@@ -44,6 +46,7 @@
 #include <resolv.h>
 #include "ipf.h"
 #include "netinet/ipl.h"
+#include "ipfzone.h"
 
 #if !defined(lint)
 static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp";
@@ -86,14 +89,17 @@
 
 void usage()
 {
-	fprintf(stderr, "usage: %s [-nv] -l\n", progname);
-	fprintf(stderr, "usage: %s [-nv] -u\n", progname);
-	fprintf(stderr, "usage: %s [-nv] [-d <dir>] -R\n", progname);
-	fprintf(stderr, "usage: %s [-nv] [-d <dir>] -W\n", progname);
-	fprintf(stderr, "usage: %s [-nv] [-N|-S] [-f <file>] -r\n", progname);
-	fprintf(stderr, "usage: %s [-nv] [-N|-S] [-f <file>] -w\n", progname);
-	fprintf(stderr, "usage: %s [-nv] [-N|-S] -f <file> -i <if1>,<if2>\n",
-		progname);
+	const char *zoneopt = "[-G|-z zonename] ";
+	fprintf(stderr, "usage: %s %s[-nv] -l\n", progname, zoneopt);
+	fprintf(stderr, "usage: %s %s[-nv] -u\n", progname, zoneopt);
+	fprintf(stderr, "usage: %s %s[-nv] [-d <dir>] -R\n", progname, zoneopt);
+	fprintf(stderr, "usage: %s %s[-nv] [-d <dir>] -W\n", progname, zoneopt);
+	fprintf(stderr, "usage: %s %s[-nv] [-N|-S] [-f <file>] -r\n", progname,
+		zoneopt);
+	fprintf(stderr, "usage: %s %s[-nv] [-N|-S] [-f <file>] -w\n", progname,
+		zoneopt);
+	fprintf(stderr, "usage: %s %s[-nv] [-N|-S] -f <file> -i <if1>,<if2>\n",
+		progname, zoneopt);
 	exit(1);
 }
 
@@ -218,7 +224,7 @@
 	char *dirname = NULL, *filename = NULL, *ifs = NULL;
 
 	progname = argv[0];
-	while ((c = getopt(argc, argv, "d:f:lNnSRruvWw")) != -1)
+	while ((c = getopt(argc, argv, "d:f:G:lNnSRruvWwz:")) != -1)
 		switch (c)
 		{
 		case 'd' :
@@ -233,6 +239,9 @@
 			else
 				usage();
 			break;
+		case 'G' :
+			setzonename_global(optarg);
+			break;
 		case 'i' :
 			ifs = optarg;
 			set = 1;
@@ -287,6 +296,9 @@
 			rw = 3;
 			set = 1;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		case '?' :
 		default :
 			usage();
@@ -355,6 +367,12 @@
 	if ((fd = open(ipfdev, O_RDWR)) == -1)
 		if ((fd = open(ipfdev, O_RDONLY)) == -1)
 			perror("open device");
+
+	if (setzone(fd) != 0) {
+		close(fd);
+		fd = -1;
+	}
+
 	return fd;
 }
 
--- a/usr/src/cmd/ipf/tools/ipfstat.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/tools/ipfstat.c	Sun Jan 04 07:19:22 2015 -0800
@@ -5,6 +5,8 @@
  *
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #ifdef __FreeBSD__
@@ -71,6 +73,7 @@
 #if defined(__NetBSD__) || (__OpenBSD__)
 # include <paths.h>
 #endif
+#include "ipfzone.h"
 
 #if !defined(lint)
 static const char sccsid[] = "@(#)fils.c	1.21 4/20/96 (C) 1993-2000 Darren Reed";
@@ -177,6 +180,7 @@
 #else
 	fprintf(stderr, "       %s -t [-C] ", name);
 #endif
+	fprintf(stderr, "[-G|-z zonename] ");
 	fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n");
 	exit(1);
 }
@@ -207,9 +211,9 @@
 	u_32_t frf;
 
 #ifdef	USE_INET6
-	options = "6aACdfghIilnostvD:M:N:P:RS:T:";
+	options = "6aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
 #else
-	options = "aACdfghIilnostvD:M:N:P:RS:T:";
+	options = "aACdfgG:hIilnostvD:M:N:P:RS:T:z:";
 #endif
 
 	saddr.in4.s_addr = INADDR_ANY; 	/* default any v4 source addr */
@@ -223,13 +227,16 @@
 	opterr = 0;
 
 	/*
-	 * Parse these two arguments now lest there be any buffer overflows
+	 * Parse these four arguments now lest there be any buffer overflows
 	 * in the parsing of the rest.
 	 */
 	myoptind = optind;
 	while ((c = getopt(argc, argv, options)) != -1) {
 		switch (c)
 		{
+		case 'G' :
+			setzonename_global(optarg);
+			break;
 		case 'M' :
 			memf = optarg;
 			live_kernel = 0;
@@ -238,6 +245,9 @@
 			kern = optarg;
 			live_kernel = 0;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		}
 	}
 	optind = myoptind;
@@ -247,11 +257,22 @@
 			perror("open(IPSTATE_NAME)");
 			exit(-1);
 		}
+
+		if (setzone(state_fd) != 0) {
+			close(state_fd);
+			exit(-1);
+		}
+
 		if ((ipf_fd = open(device, O_RDONLY)) == -1) {
 			fprintf(stderr, "open(%s)", device);
 			perror("");
 			exit(-1);
 		}
+
+		if (setzone(ipf_fd) != 0) {
+			close(ipf_fd);
+			exit(-1);
+		}
 	}
 
 	if (kern != NULL || memf != NULL) {
@@ -298,6 +319,9 @@
 		case 'g' :
 			opts |= OPT_GROUPS;
 			break;
+		case 'G' :
+			/* Already handled by getzoneopt() above */
+			break;
 		case 'h' :
 			opts |= OPT_HITS;
 			break;
@@ -360,6 +384,9 @@
 			opts |= OPT_VERBOSE;
 			opts |= OPT_UNDEF;
 			break;
+		case 'z' :
+			/* Already handled by getzoneopt() above */
+			break;
 		default :
 			usage(argv[0]);
 			break;
@@ -482,6 +509,11 @@
 			exit(-1);
 		}
 
+		if (setzone(ipf_fd) != 0) {
+			close(ipf_fd);
+			exit(-1);
+		}
+
 		bzero((caddr_t)&ipfo, sizeof(ipfo));
 		ipfo.ipfo_rev = IPFILTER_VERSION;
 		ipfo.ipfo_size = sizeof(fr_authstat_t);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/ipf/tools/ipfzone.c	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2014 Joyent, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * See the IPFILTER.LICENCE file for details on licensing.
+ */
+
+
+#include <errno.h>
+#include <net/if.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <zone.h>
+
+#include "netinet/ip_fil.h"
+#include "ipfzone.h"
+
+static ipfzoneobj_t	ipzo;
+static boolean_t	do_setzone = 0;
+static int		num_setzones = 0;
+
+extern int	errno;
+extern int	opterr;
+extern int	optind;
+extern char	*optarg;
+
+/*
+ * Get the zonename if it's the last argument and set the zonename
+ * in ipfzo to it. This is used by ipf(1m) only - all of the other tools
+ * specify the zone with the -z option, and therefore use getzoneopt() below.
+ */
+void
+getzonearg(int argc, char *argv[], const char *optstr)
+{
+	int c;
+
+	/*
+	 * Don't warn about unknown options - let subsequent calls to
+	 * getopt() handle this.
+	 */
+	opterr = 0;
+
+	/*
+	 * getopt is also used here to set optind so that we can
+	 * determine if the last argument belongs to a flag or is
+	 * actually a zonename.
+	 */
+	while ((c = getopt(argc, argv, optstr)) != -1) {
+		if (c == 'G')
+			ipzo.ipfz_gz = 1;
+	}
+
+	if (optind < argc)
+		setzonename(argv[optind]);
+
+	/*
+	 * Reset optind and opterr so the next getopt call will go through all
+	 * of argv again and warn about unknown options.
+	 */
+	optind = 1;
+	opterr = 1;
+}
+
+/*
+ * Get a -z option from argv and set the zonename in ipfzo accordingly
+ */
+void
+getzoneopt(int argc, char *argv[], const char *optstr)
+{
+	int c;
+
+	/*
+	 * Don't warn about unknown options - let subsequent calls to
+	 * getopt() handle this.
+	 */
+	opterr = 0;
+
+	while ((c = getopt(argc, argv, optstr)) != -1) {
+		if (c == 'G')
+			setzonename_global(optarg);
+
+		if (c == 'z')
+			setzonename(optarg);
+	}
+
+	/*
+	 * Reset optind and opterr so the next getopt call will go through all
+	 * of argv again and warn about unknown options.
+	 */
+	optind = 1;
+	opterr = 1;
+}
+
+/*
+ * Set the zonename in ipfzo to the given string: this is the zone all further
+ * ioctls will act on.
+ */
+void
+setzonename(const char *zonename)
+{
+	memcpy(ipzo.ipfz_zonename, zonename, sizeof (ipzo.ipfz_zonename));
+	do_setzone = B_TRUE;
+	num_setzones++;
+}
+
+/*
+ * Set the zonename in ipfo, and the gz flag. This indicates that we want all
+ * further ioctls to act on the GZ-controlled stack for that zone.
+ */
+void
+setzonename_global(const char *zonename)
+{
+	setzonename(zonename);
+	ipzo.ipfz_gz = 1;
+}
+
+/*
+ * Set the zone that all further ioctls will operate on. See the "GZ-controlled
+ * and per-zone stacks" note at the top of ip_fil_solaris.c for further
+ * explanation.
+ */
+int
+setzone(int fd)
+{
+	if (!do_setzone)
+		return (0);
+
+	if (num_setzones > 1) {
+		(void) fprintf(stderr,
+		    "Only one of -G and -z may be set\n");
+		return (-1);
+	}
+
+	if (ipzo.ipfz_gz == 1 &&
+	    getzoneidbyname(ipzo.ipfz_zonename) == GLOBAL_ZONEID) {
+		(void) fprintf(stderr,
+		    "-G cannot be used with the global zone\n");
+		return (-1);
+	}
+
+	if (ioctl(fd, SIOCIPFZONESET, &ipzo) == -1) {
+		switch (errno) {
+		case ENODEV:
+			(void) fprintf(stderr,
+			    "Could not find running zone: %s\n",
+			    ipzo.ipfz_zonename);
+			break;
+		case EACCES:
+			(void) fprintf(stderr,
+			    "Permission denied setting zone: %s\n",
+			    ipzo.ipfz_zonename);
+			break;
+		default:
+			perror("Error setting zone");
+		}
+		return (-1);
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/ipf/tools/ipfzone.h	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * See the IPFILTER.LICENCE file for details on licensing.
+ */
+
+#ifndef	__IPFZONE_H__
+#define	__IPFZONE_H__
+
+void getzonearg(int, char *[], const char *);
+void getzoneopt(int, char *[], const char *);
+int setzone(int);
+void setzonename(const char *);
+void setzonename_global(const char *);
+
+#endif /* __IPFZONE_H__ */
--- a/usr/src/cmd/ipf/tools/ipmon.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/tools/ipmon.c	Sun Jan 04 07:19:22 2015 -0800
@@ -5,6 +5,8 @@
  *
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 
@@ -78,6 +80,7 @@
 #include "netinet/ip_state.h"
 #include "netinet/ip_proxy.h"
 #include "ipmon.h"
+#include "ipfzone.h"
 
 #if !defined(lint)
 static const char sccsid[] = "@(#)ipmon.c	1.21 6/5/96 (C)1993-2000 Darren Reed";
@@ -1340,10 +1343,10 @@
 static void usage(prog)
 char *prog;
 {
-	fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s\n",
-		prog, "[-N device]", "[ [-o [NSI]] [-O [NSI]]",
-		"[-P pidfile]", "[-S device]", "[-f device]",
-		"filename");
+	fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s %s\n",
+		prog, "[-G|-z zonename]", "[-N device]",
+		"[ [-o [NSI]] [-O [NSI]]", "[-P pidfile]", "[-S device]",
+		"[-f device]", "filename");
 	exit(1);
 }
 
@@ -1380,6 +1383,11 @@
 		exit(1);
 	}
 
+	if (setzone(fd) != 0) {
+		close(fd);
+		exit(1);
+	}
+
 	if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
 		printf("%d bytes flushed from log buffer\n",
 			flushed);
@@ -1444,6 +1452,7 @@
 	char	buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s;
 	extern	int	optind;
 	extern	char	*optarg;
+	const	char	*optstr = "?abB:C:Df:G:FhnN:o:O:pP:sS:tvxXz:";
 
 	fd[0] = fd[1] = fd[2] = -1;
 	fdt[0] = fdt[1] = fdt[2] = -1;
@@ -1451,7 +1460,13 @@
 	iplfile[1] = IPNAT_NAME;
 	iplfile[2] = IPSTATE_NAME;
 
-	while ((c = getopt(argc, argv, "?abB:C:Df:FhnN:o:O:pP:sS:tvxX")) != -1)
+	/*
+	 * We need to set the zone name before calling openlog in
+	 * the switch statement below
+	 */
+	getzoneopt(argc, argv, optstr);
+
+	while ((c = getopt(argc, argv, optstr)) != -1)
 		switch (c)
 		{
 		case 'a' :
@@ -1483,6 +1498,9 @@
 			flushlogs(iplfile[1], log);
 			flushlogs(iplfile[2], log);
 			break;
+		case 'G' :
+			/* Already handled by getzoneopt() above */
+			break;
 		case 'n' :
 			opts |= OPT_RESOLVE;
 			break;
@@ -1535,6 +1553,9 @@
 		case 'X' :
 			opts |= OPT_HEXHDR;
 			break;
+		case 'z' :
+			/* Already handled by getzoneopt() above */
+			break;
 		default :
 		case 'h' :
 		case '?' :
@@ -1571,6 +1592,12 @@
 				exit(1);
 				/* NOTREACHED */
 			}
+
+			if (setzone(fd[i]) != 0) {
+				close(fd[i]);
+				exit(1);
+			}
+
 			if (!(regular[i] = !S_ISCHR(sb.st_mode)))
 				devices++;
 		}
--- a/usr/src/cmd/ipf/tools/ipnat.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/tools/ipnat.c	Sun Jan 04 07:19:22 2015 -0800
@@ -7,6 +7,8 @@
  *
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #include <stdio.h>
@@ -55,6 +57,7 @@
 #include "ipf.h"
 #include "netinet/ipl.h"
 #include "kmem.h"
+#include "ipfzone.h"
 
 #ifdef	__hpux
 # define	nlist	nlist64
@@ -95,7 +98,8 @@
 void usage(name)
 char *name;
 {
-	fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]\n", name);
+	fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]", name);
+	fprintf(stderr, " [-G|-z zonename]\n");
 	exit(1);
 }
 
@@ -117,7 +121,7 @@
 	kernel = NULL;
 	mode = O_RDWR;
 
-	while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1)
+	while ((c = getopt(argc, argv, "CdFf:G:hlM:N:nrRsvz:")) != -1)
 		switch (c)
 		{
 		case 'C' :
@@ -132,6 +136,9 @@
 		case 'F' :
 			opts |= OPT_FLUSH;
 			break;
+		case 'G' :
+			setzonename_global(optarg);
+			break;
 		case 'h' :
 			opts |=OPT_HITS;
 			break;
@@ -162,6 +169,9 @@
 		case 'v' :
 			opts |= OPT_VERBOSE;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		default :
 			usage(argv[0]);
 		}
@@ -195,6 +205,11 @@
 			exit(1);
 		}
 
+		if (setzone(fd) != 0) {
+			close(fd);
+			exit(1);
+		}
+
 		bzero((char *)&obj, sizeof(obj));
 		obj.ipfo_rev = IPFILTER_VERSION;
 		obj.ipfo_size = sizeof(*nsp);
--- a/usr/src/cmd/ipf/tools/ippool.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ipf/tools/ippool.c	Sun Jan 04 07:19:22 2015 -0800
@@ -5,10 +5,10 @@
  *
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/param.h>
@@ -41,6 +41,7 @@
 #include "netinet/ip_pool.h"
 #include "netinet/ip_htable.h"
 #include "kmem.h"
+#include "ipfzone.h"
 
 extern	int	ippool_yyparse __P((void));
 extern	int	ippool_yydebug;
@@ -71,15 +72,21 @@
 void usage(prog)
 char *prog;
 {
+	const char *zoneopt = "[-G|-z zonename] ";
 	fprintf(stderr, "Usage:\t%s\n", prog);
-	fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
-	fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
-	fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n");
-	fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n");
-	fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n");
-	fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
-	fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
-	fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
+	fprintf(stderr, "\t\t\t-a [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
+	    zoneopt);
+	fprintf(stderr, "\t\t\t-A [-dnv] %s[-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n",
+	    zoneopt);
+	fprintf(stderr, "\t\t\t-f <file> %s[-dnuv]\n", zoneopt);
+	fprintf(stderr, "\t\t\t-F [-dv] %s[-o <role>] [-t <type>]\n", zoneopt);
+	fprintf(stderr, "\t\t\t-l [-dv] %s[-m <name>] [-t <type>]\n", zoneopt);
+	fprintf(stderr, "\t\t\t-r [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
+	    zoneopt);
+	fprintf(stderr, "\t\t\t-R [-dnv] %s[-m <name>] [-o <role>] [-t <type>]\n",
+	    zoneopt);
+	fprintf(stderr, "\t\t\t-s [-dtv] %s[-M <core>] [-N <namelist>]\n",
+	    zoneopt);
 	exit(1);
 }
 
@@ -140,13 +147,16 @@
 	role = IPL_LOGIPF;
 	bzero((char *)&node, sizeof(node));
 
-	while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1)
+	while ((c = getopt(argc, argv, "di:G:m:no:Rvz:")) != -1)
 		switch (c)
 		{
 		case 'd' :
 			opts |= OPT_DEBUG;
 			ippool_yydebug++;
 			break;
+		case 'G' :
+			setzonename_global(optarg);
+			break;
 		case 'i' :
 			s = strchr(optarg, '/');
 			if (s == NULL)
@@ -182,6 +192,9 @@
 		case 'v' :
 			opts |= OPT_VERBOSE;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		}
 
 	if (opts & OPT_DEBUG)
@@ -219,13 +232,16 @@
 	bzero((char *)&iph, sizeof(iph));
 	bzero((char *)&pool, sizeof(pool));
 
-	while ((c = getopt(argc, argv, "dm:no:RS:t:v")) != -1)
+	while ((c = getopt(argc, argv, "dG:m:no:RS:t:vz:")) != -1)
 		switch (c)
 		{
 		case 'd' :
 			opts |= OPT_DEBUG;
 			ippool_yydebug++;
 			break;
+		case 'G' :
+			setzonename_global(optarg);
+			break;
 		case 'm' :
 			poolname = optarg;
 			break;
@@ -255,6 +271,9 @@
 		case 'v' :
 			opts |= OPT_VERBOSE;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		}
 
 	if (opts & OPT_DEBUG)
@@ -308,13 +327,16 @@
 
 	infile = optarg;
 
-	while ((c = getopt(argc, argv, "dnRuv")) != -1)
+	while ((c = getopt(argc, argv, "dG:nRuvz:")) != -1)
 		switch (c)
 		{
 		case 'd' :
 			opts |= OPT_DEBUG;
 			ippool_yydebug++;
 			break;
+		case 'G' :
+			setzonename_global(optarg);
+			break;
 		case 'n' :
 			opts |= OPT_DONOTHING;
 			break;
@@ -327,6 +349,9 @@
 		case 'v' :
 			opts |= OPT_VERBOSE;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		}
 
 	if (opts & OPT_DEBUG)
@@ -338,6 +363,11 @@
 			perror("open(IPLOOKUP_NAME)");
 			exit(1);
 		}
+
+		if (setzone(fd) != 0) {
+			close(fd);
+			exit(1);
+		}
 	}
 
 	if (ippool_parsefile(fd, infile, ioctl) != 0)
@@ -365,12 +395,15 @@
 	poolname = NULL;
 	role = IPL_LOGALL;
 
-	while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
+	while ((c = getopt(argc, argv, "dG:m:M:N:o:Rt:vz:")) != -1)
 		switch (c)
 		{
 		case 'd' :
 			opts |= OPT_DEBUG;
 			break;
+		case 'G' :
+			setzonename_global(optarg);
+			break;
 		case 'm' :
 			poolname = optarg;
 			break;
@@ -402,6 +435,9 @@
 		case 'v' :
 			opts |= OPT_VERBOSE;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		}
 
 	if (opts & OPT_DEBUG)
@@ -413,6 +449,11 @@
 			perror("open(IPLOOKUP_NAME)");
 			exit(1);
 		}
+
+		if (setzone(fd) != 0) {
+			close(fd);
+			exit(1);
+		}
 	}
 
 	bzero((char *)&op, sizeof(op));
@@ -615,12 +656,15 @@
 
 	bzero((char *)&op, sizeof(op));
 
-	while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
+	while ((c = getopt(argc, argv, "dG:M:N:o:t:vz:")) != -1)
 		switch (c)
 		{
 		case 'd' :
 			opts |= OPT_DEBUG;
 			break;
+		case 'G' :
+			setzonename_global(optarg);
+			break;
 		case 'M' :
 			live_kernel = 0;
 			core = optarg;
@@ -647,6 +691,9 @@
 		case 'v' :
 			opts |= OPT_VERBOSE;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		}
 
 	if (opts & OPT_DEBUG)
@@ -658,6 +705,11 @@
 			perror("open(IPLOOKUP_NAME)");
 			exit(1);
 		}
+
+		if (setzone(fd) != 0) {
+			close(fd);
+			exit(1);
+		}
 	}
 
 	if (type == IPLT_ALL || type == IPLT_POOL) {
@@ -705,7 +757,7 @@
 	type = IPLT_ALL;
 	role = IPL_LOGALL;
 
-	while ((c = getopt(argc, argv, "do:t:v")) != -1)
+	while ((c = getopt(argc, argv, "do:t:vz:")) != -1)
 		switch (c)
 		{
 		case 'd' :
@@ -728,6 +780,9 @@
 		case 'v' :
 			opts |= OPT_VERBOSE;
 			break;
+		case 'z' :
+			setzonename(optarg);
+			break;
 		}
 
 	if (opts & OPT_DEBUG)
@@ -739,6 +794,11 @@
 			perror("open(IPLOOKUP_NAME)");
 			exit(1);
 		}
+
+		if (setzone(fd) != 0) {
+			close(fd);
+			exit(1);
+		}
 	}
 
 	bzero((char *)&flush, sizeof(flush));
--- a/usr/src/cmd/mailx/Makefile	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/Makefile	Sun Jan 04 07:19:22 2015 -0800
@@ -22,6 +22,8 @@
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
+# Copyright 2014 Joyent, Inc.
+#
 # cmd/mailx/Makefile
 
 PROG= mailx
@@ -62,7 +64,7 @@
 CERRWARN +=	-_gcc=-Wno-unused-variable
 CERRWARN +=	-_gcc=-Wno-clobbered
 LINTFLAGS= 	-hb
-LDLIBS +=	-lmail
+LDLIBS +=	-lmail -lcmdutils
 LDFLAGS +=	$(MAPFILE.NGB:%=-M%)
 
 CLOBBERFILES += $(MAILXHELP)
--- a/usr/src/cmd/mailx/cmd1.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/cmd1.c	Sun Jan 04 07:19:22 2015 -0800
@@ -19,6 +19,11 @@
  *
  * CDDL HEADER END
  */
+
+/*
+ * Copyright 2014 Joyent, Inc.
+ */
+
 /*
  * Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -37,8 +42,7 @@
  * contributors.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
+#include <err.h>
 #include "rcv.h"
 #include <locale.h>
 
@@ -213,10 +217,14 @@
 	char *fromline;
 	char pbuf[LINESIZE];
 	char name[LINESIZE];
-	struct headline hl;
+	headline_t *hl;
 	register char *cp;
 	int showto;
 
+	if (headline_alloc(&hl) != 0) {
+		err(1, "could not allocate memory");
+	}
+
 	mp = &message[mesg-1];
 	ibuf = setinput(mp);
 	readline(ibuf, headline);
@@ -248,9 +256,14 @@
 			dispc = 'H';
 	if (mp->m_flag & MBOX)
 		dispc = 'M';
-	parse(headline, &hl, pbuf);
-	if (hl.l_date == NOSTR)
-		hl.l_date = "<Unknown date>";
+	if (parse_headline(headline, hl) == -1) {
+		headline_reset(hl);
+	}
+	if (custr_len(hl->hl_date) == 0) {
+		if (custr_append(hl->hl_date, "<Unknown date>") != 0) {
+			err(1, "could not print header");
+		}
+	}
 
 	/*
 	 * Netnews interface?
@@ -299,11 +312,14 @@
 	}
 	if (mp->m_text) {
 		printf("%16.16s %4ld/%-5ld %-.25s\n",
-			hl.l_date, mp->m_lines, mp->m_size, subjline);
+		    custr_cstr(hl->hl_date), mp->m_lines, mp->m_size,
+		    subjline);
 	} else {
-		printf("%16.16s binary/%-5ld %-.25s\n", hl.l_date, mp->m_size,
-		    subjline);
+		printf("%16.16s binary/%-5ld %-.25s\n", custr_cstr(hl->hl_date),
+		    mp->m_size, subjline);
 	}
+
+	headline_free(hl);
 }
 
 /*
--- a/usr/src/cmd/mailx/fio.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/fio.c	Sun Jan 04 07:19:22 2015 -0800
@@ -21,6 +21,10 @@
  */
 
 /*
+ * Copyright 2014 Joyent, Inc.
+ */
+
+/*
  * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -28,8 +32,6 @@
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-#pragma	ident	"%Z%%M%	%I%	%E% SMI"
-
 #include "rcv.h"
 #include <locale.h>
 #include <wordexp.h>
@@ -174,7 +176,7 @@
 		}
 
 		/* Look for a From line that starts a new message */
-		if (blankline && linebuf[0] == 'F' && ishead(linebuf)) {
+		if (blankline && linebuf[0] == 'F' && is_headline(linebuf)) {
 			if (msgCount > 0 && !newmail) {
 				message[msgCount-1].m_size = s;
 				message[msgCount-1].m_lines = l;
@@ -755,7 +757,7 @@
 		if (debug) fprintf(stderr, "%s\n", name);
 		return (name);
 	}
-	if (wordexp(name, &wrdexp_buf, 0) != 0) {
+	if (wordexp(name, &wrdexp_buf, WRDE_NOCMD) != 0) {
 		fprintf(stderr, gettext("Syntax error in \"%s\"\n"), name);
 		fflush(stderr);
 		return (NOSTR);
--- a/usr/src/cmd/mailx/hdr/def.h	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/hdr/def.h	Sun Jan 04 07:19:22 2015 -0800
@@ -20,6 +20,10 @@
  */
 
 /*
+ * Copyright 2014 Joyent, Inc.
+ */
+
+/*
  * Copyright (c) 1985, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
@@ -60,6 +64,7 @@
 #include <stdlib.h>
 #include <ulimit.h>
 #include <wait.h>
+#include <libcmdutils.h>
 #endif
 #ifdef VMUNIX
 #include <sys/wait.h>
@@ -204,11 +209,11 @@
  * line
  */
 
-struct headline {
-	char	*l_from;	/* The name of the sender */
-	char	*l_tty;		/* His tty string (if any) */
-	char	*l_date;	/* The entire date string */
-};
+typedef struct headline {
+	custr_t	*hl_from;	/* The name of the sender */
+	custr_t	*hl_tty;	/* His tty string (if any) */
+	custr_t	*hl_date;	/* The entire date string */
+} headline_t;
 
 #define	GTO	1		/* Grab To: line */
 #define	GSUBJECT 2		/* Likewise, Subject: line */
@@ -486,6 +491,9 @@
 extern char	*hcontents(char hfield[]);
 extern int	headerp(register char *line);
 extern int	headers(int *msgvec);
+extern int	headline_alloc(headline_t **);
+extern void	headline_free(headline_t *);
+extern void	headline_reset(headline_t *);
 extern int	help(void);
 extern char	*helppath(char *file);
 extern char	*hfield(char field[], struct message *mp,
@@ -497,7 +505,7 @@
 extern int	inc(void);
 extern void	inithost(void);
 extern int	isdir(char name[]);
-extern int	ishead(char linebuf[]);
+extern boolean_t is_headline(const char *);
 extern int	ishfield(char linebuf[], char field[]);
 extern int	ishost(char *sys, char *rest);
 extern int	isign(char *field, int saving);
@@ -533,7 +541,7 @@
 extern int	outof(struct name *names, FILE *fo);
 extern struct name	*outpre(struct name *to);
 extern void	panic(char *str);
-extern void	parse(char line[], struct headline *hl, char pbuf[]);
+extern int	parse_headline(const char *, headline_t *);
 extern int	pcmdlist(void);
 extern int	pdot(void);
 extern int	preserve(int *msgvec);
--- a/usr/src/cmd/mailx/head.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/head.c	Sun Jan 04 07:19:22 2015 -0800
@@ -19,6 +19,11 @@
  *
  * CDDL HEADER END
  */
+
+/*
+ * Copyright 2014 Joyent, Inc.
+ */
+
 /*
  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -38,7 +43,7 @@
  * contributors.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#include <err.h>
 
 #include "rcv.h"
 
@@ -49,115 +54,188 @@
  * Routines for processing and detecting headlines.
  */
 
-static char	*copyin(char src[], char **space);
-static char	*nextword(char wp[], char wbuf[]);
+static int nextword(const char *, custr_t *, const char **);
 
 /*
  * See if the passed line buffer is a mail header.
  * Return true if yes.
  */
-
-int 
-ishead(char linebuf[])
+boolean_t
+is_headline(const char *linebuf)
 {
-	register char *cp;
-	struct headline hl;
-	char parbuf[BUFSIZ];
+	headline_t *hl;
+	boolean_t ret;
 
-	cp = linebuf;
-	if (strncmp("From ", cp, 5) != 0)
-		return(0);
-	parse(cp, &hl, parbuf);
-	if (hl.l_from == NOSTR) {
-		return(0);
+	if (strncmp("From ", linebuf, 5) != 0) {
+		return (B_FALSE);
 	}
-	return(1);
+
+	if (headline_alloc(&hl) != 0 || parse_headline(linebuf, hl) != 0) {
+		err(1, "could not parse headline");
+	}
+
+	ret = custr_len(hl->hl_from) > 0 ? B_TRUE : B_FALSE;
+
+	headline_free(hl);
+	return (ret);
 }
 
 /*
- * Split a headline into its useful components.
- * Copy the line into dynamic string space, then set
- * pointers into the copied line in the passed headline
- * structure.  Actually, it scans.
+ * Manage headline_t objects:
  */
-void 
-parse(char line[], struct headline *hl, char pbuf[])
+void
+headline_free(headline_t *hl)
 {
-	register char *cp, *dp;
-	char *sp;
-	char word[LINESIZE];
+	custr_free(hl->hl_from);
+	custr_free(hl->hl_tty);
+	custr_free(hl->hl_date);
+	free(hl);
+}
+
+int
+headline_alloc(headline_t **hl)
+{
+	int en;
+	headline_t *t;
 
-	hl->l_from = NOSTR;
-	hl->l_date = NOSTR;
-	cp = line;
-	sp = pbuf;
+	if ((t = calloc(1, sizeof (*t))) == NULL) {
+		return (-1);
+	}
+
+	if (custr_alloc(&t->hl_from) != 0 || custr_alloc(&t->hl_tty) != 0 ||
+	    custr_alloc(&t->hl_date) != 0) {
+		en = errno;
 
-	/*
-	 * Skip the first "word" of the line, which should be "From"
-	 * anyway.
-	 */
+		headline_free(t);
 
-	cp = nextword(cp, word);
-	dp = nextword(cp, word);
-	if (!equal(word, ""))
-		hl->l_from = copyin(word, &sp);
-	if (dp != NOSTR)
-		hl->l_date = copyin(dp, &sp);
+		errno = en;
+		return (-1);
+	}
+
+	*hl = t;
+	return (0);
 }
 
 /*
- * Copy the string on the left into the string on the right
- * and bump the right (reference) string pointer by the length.
- * Thus, dynamically allocate space in the right string, copying
- * the left string into it.
+ * Clear all of the strings in a headline_t:
  */
+void
+headline_reset(headline_t *hl)
+{
+	custr_reset(hl->hl_from);
+	custr_reset(hl->hl_tty);
+	custr_reset(hl->hl_date);
+}
 
-static char *
-copyin(char src[], char **space)
+int
+parse_headline(const char *line, headline_t *hl)
 {
-	register char *cp, *top;
-	register int s;
+	const char *c = line;
+
+	headline_reset(hl);
+
+	/*
+	 * Load the first word from the line and ensure that it is "From".
+	 */
+	if (nextword(c, hl->hl_from, &c) != 0) {
+		return (-1);
+	}
+	if (strcmp(custr_cstr(hl->hl_from), "From") != 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+	custr_reset(hl->hl_from);
 
-	s = strlen(src);
-	cp = *space;
-	top = cp;
-	strcpy(cp, src);
-	cp += s + 1;
-	*space = cp;
-	return(top);
+	/*
+	 * The next word will be the From address.
+	 */
+	if (nextword(c, hl->hl_from, &c) != 0) {
+		return (-1);
+	}
+
+	/*
+	 * If there is a next word, the rest of the string is the Date.
+	 */
+	if (c != NULL) {
+		if (custr_append(hl->hl_date, c) != 0) {
+			return (-1);
+		}
+	}
+
+	errno = 0;
+	return (0);
 }
 
 /*
- * Collect a liberal (space, tab delimited) word into the word buffer
- * passed.  Also, return a pointer to the next word following that,
- * or NOSTR if none follow.
+ * Collect a space- or tab-delimited word into the word buffer, if one is
+ * passed.  The double quote character (") can be used to include whitespace
+ * within a word.  Set "nextword" to the location of the first character of the
+ * _next_ word, or NULL if there were no more words.  Returns 0 on success or
+ * -1 otherwise.
  */
+static int
+nextword(const char *input, custr_t *word, const char **nextword)
+{
+	boolean_t in_quotes = B_FALSE;
+	const char *c = input != NULL ? input : "";
+
+	/*
+	 * Collect the first word into the word buffer, if one is provided.
+	 */
+	for (;;) {
+		if (*c == '\0') {
+			/*
+			 * We have reached the end of the string.
+			 */
+			*nextword = NULL;
+			return (0);
+		}
 
-static char *
-nextword(char wp[], char wbuf[])
-{
-	register char *cp, *cp2;
+		if (*c == '"') {
+			/*
+			 * Either beginning or ending a quoted string.
+			 */
+			in_quotes = in_quotes ? B_FALSE : B_TRUE;
+		}
 
-	if ((cp = wp) == NOSTR) {
-		copy("", wbuf);
-		return(NOSTR);
+		if (!in_quotes && (*c == ' ' || *c == '\t')) {
+			/*
+			 * We have reached a whitespace region.
+			 */
+			break;
+		}
+
+		/*
+		 * Copy this character into the word buffer.
+		 */
+		if (word != NULL) {
+			if (custr_appendc(word, *c) != 0) {
+				return (-1);
+			}
+		}
+		c++;
 	}
-	cp2 = wbuf;
-	while (!any(*cp, " \t") && *cp != '\0')
-		if (*cp == '"') {
-			*cp2++ = *cp++;
-			while (*cp != '\0' && *cp != '"')
-				*cp2++ = *cp++;
-			if (*cp == '"')
-				*cp2++ = *cp++;
-		} else
-			*cp2++ = *cp++;
-	*cp2 = '\0';
-	while (any(*cp, " \t"))
-		cp++;
-	if (*cp == '\0')
-		return(NOSTR);
-	return(cp);
+
+	/*
+	 * Find the beginning of the next word, if there is one.
+	 */
+	for (;;) {
+		if (*c == '\0') {
+			/*
+			 * We have reached the end of the string.
+			 */
+			*nextword = NULL;
+			return (0);
+
+		} else if (*c != ' ' && *c != '\t') {
+			/*
+			 * We have located the next word.
+			 */
+			*nextword = c;
+			return (0);
+		}
+		c++;
+	}
 }
 
 /*
--- a/usr/src/cmd/mailx/main.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/main.c	Sun Jan 04 07:19:22 2015 -0800
@@ -37,8 +37,6 @@
  * contributors.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include "rcv.h"
 #ifndef preSVr4
 #include <locale.h>
@@ -104,7 +102,6 @@
 	progname = argv[0];
 	if (progname[strlen(progname) - 1] != 'x') {
 		assign("bsdcompat", "");
-		assign("escapeok", "");		/* XXX */
 	}
 	myegid = getegid();
 	myrgid = getgid();
--- a/usr/src/cmd/mailx/misc/mailx.rc	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/misc/mailx.rc	Sun Jan 04 07:19:22 2015 -0800
@@ -21,8 +21,6 @@
 # Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 # The following 3 settings produce the familiar Solaris behavior.
 set appenddeadletter
 unset pipeignore
@@ -44,8 +42,6 @@
 	set LISTER="ls -LF"
 	# default is to allow editing of message windows
 	set editmessagewindow
-	# have to allow ~ escapes even though not using tty
-	set escapeok
 endif
 
 # most mail headers are uninteresting to most people.  here we ignore all
--- a/usr/src/cmd/mailx/names.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/names.c	Sun Jan 04 07:19:22 2015 -0800
@@ -191,7 +191,7 @@
 /*
  * For each recipient in the passed name list with a /
  * in the name, append the message to the end of the named file
- * and remove him from the recipient list.
+ * and remove them from the recipient list.
  *
  * Recipients whose name begins with | are piped through the given
  * program and removed.
@@ -212,6 +212,9 @@
 	char line[BUFSIZ];
 #endif
 
+	if (value("expandaddr") == NOSTR)
+		return (nout);
+
 	for (np = names; np != NIL; np = np->n_flink) {
 		if (!isfileaddr(np->n_name) && np->n_name[0] != '|')
 			continue;
@@ -599,14 +602,15 @@
 		panic("No names to unpack");
 
 	/*
-	 * Compute the number of extra arguments we will need.
-	 * We need at least 2 extra -- one for "mail" and one for
-	 * the terminating 0 pointer.
-	 * Additional spots may be needed to pass along -r and -f to
-	 * the host mailer.
+	 * Compute the number of extra arguments we will need.  We need at least
+	 * 3 extra -- one for "mail", one for a terminating -- to stop sendmail
+	 * option processing, and one for the terminating 0 pointer.
+	 *
+	 * Additional spots may be needed to pass along -r and -f to the host
+	 * mailer.
 	 */
 
-	extra = 2;
+	extra = 3;
 
 	if (rflag != NOSTR)
 		extra += 2;
@@ -636,6 +640,7 @@
 		snprintf(hbuf, sizeof (hbuf), "%d", hflag);
 		*ap++ = savestr(hbuf);
 	}
+	*ap++ = "--";
 	while (n != NIL) {
 		if (n->n_type & GDEL) {
 			n = n->n_flink;
--- a/usr/src/cmd/mailx/receipt.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mailx/receipt.c	Sun Jan 04 07:19:22 2015 -0800
@@ -19,6 +19,11 @@
  *
  * CDDL HEADER END
  */
+
+/*
+ * Copyright 2014 Joyent, Inc.
+ */
+
 /*
  * Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -38,7 +43,7 @@
  * contributors.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+#include <err.h>
 
 #include "rcv.h"
 
@@ -47,12 +52,12 @@
 void 
 receipt(struct message *mp)
 {
-	struct headline	hl;
 	char	head[LINESIZE];
 	char	buf[BUFSIZ];
 	FILE	*pp, *fp;
 	char	*mail, *s;
 
+
 	if ((mail = value("sendmail")) == 0)
 #ifdef SENDMAIL
 		mail = SENDMAIL;
@@ -63,16 +68,27 @@
 	 || icsubstr(hfield(">to", mp, addto), "/receipt")) {
 		snprintf(buf, sizeof (buf), "%s %s", mail, skin(nameof(mp)));
 		if (pp = npopen(buf, "w")) {
+			headline_t *hl;
+
+			if (headline_alloc(&hl) != 0) {
+				err(1, "could not allocate memory");
+			}
+
 			fp = setinput(mp);
 			readline(fp, head);
-			parse(head, &hl, buf);
-			if (hl.l_date != NOSTR)
-				fprintf(pp, "Original-Date: %s\n", hl.l_date);
+			if (parse_headline(head, hl) != 0) {
+				headline_reset(hl);
+			}
+			if (custr_len(hl->hl_date) > 0) {
+				fprintf(pp, "Original-Date: %s\n",
+				    custr_cstr(hl->hl_date));
+			}
 			if (s = hfield("message-id", mp, addone))
 				fprintf(pp, "Original-Message-ID: %s\n", s);
 			s = hfield("subject", mp, addone);
 			fprintf(pp, "Subject: RR: %s\n", s ? s : "(none)");
 			npclose(pp);
+			headline_free(hl);
 		}
 	}
 }
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c	Sun Jan 04 07:19:22 2015 -0800
@@ -960,7 +960,16 @@
 	static const char *bytestats[] = {
 		"p", "c", "c_min", "c_max", "size", "duplicate_buffers_size",
 		"arc_meta_used", "arc_meta_limit", "arc_meta_max",
-		"arc_meta_min", "hdr_size", "data_size", "other_size",
+		"arc_meta_min", "hdr_size", "data_size", "metadata_size",
+		"other_size", "anon_size", "anon_evictable_data",
+		"anon_evictable_metadata", "mru_size", "mru_evictable_data",
+		"mru_evictable_metadata", "mru_ghost_size",
+		"mru_ghost_evictable_data", "mru_ghost_evictable_metadata",
+		"mfu_size", "mfu_evictable_data", "mfu_evictable_metadata",
+		"mfu_ghost_size", "mfu_ghost_evictable_data",
+		"mfu_ghost_evictable_metadata", "evict_l2_cached",
+		"evict_l2_eligible", "evict_l2_ineligible", "l2_read_bytes",
+		"l2_write_bytes", "l2_size", "l2_asize", "l2_hdr_size",
 		NULL
 	};
 
--- a/usr/src/cmd/ndmpadm/ndmpadm_main.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ndmpadm/ndmpadm_main.c	Sun Jan 04 07:19:22 2015 -0800
@@ -616,14 +616,14 @@
 		if (strncmp(auth_type, ndmp_auth_table[i].auth_type,
 		    strlen(ndmp_auth_table[i].auth_type)) == 0) {
 			auth_type_flag = 1;
-			if ((ndmp_set_prop((char *)ndmp_auth_table[i].username,
+			if ((ndmp_set_prop(ndmp_auth_table[i].username,
 			    username)) == -1) {
 				(void) fprintf(stdout,
 				    gettext("Could not set username - %s\n"),
 				    ndmp_strerror(ndmp_errno));
 				continue;
 			}
-			if ((ndmp_set_prop((char *)ndmp_auth_table[i].password,
+			if ((ndmp_set_prop(ndmp_auth_table[i].password,
 			    enc_password)) == -1) {
 				(void) fprintf(stdout,
 				    gettext("Could not set password - %s\n"),
@@ -677,14 +677,14 @@
 		if (strncmp(auth_type, ndmp_auth_table[i].auth_type,
 		    strlen(ndmp_auth_table[i].auth_type)) == 0) {
 			auth_type_flag = 1;
-			if ((ndmp_set_prop((char *)ndmp_auth_table[i].username,
+			if ((ndmp_set_prop(ndmp_auth_table[i].username,
 			    "")) == -1) {
 				(void) fprintf(stdout,
 				    gettext("Could not clear username - %s\n"),
 				    ndmp_strerror(ndmp_errno));
 				continue;
 			}
-			if ((ndmp_set_prop((char *)ndmp_auth_table[i].password,
+			if ((ndmp_set_prop(ndmp_auth_table[i].password,
 			    "")) == -1) {
 				(void) fprintf(stdout,
 				    gettext("Could not clear password - %s\n"),
--- a/usr/src/cmd/sgs/libld/common/unwind.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/sgs/libld/common/unwind.c	Sun Jan 04 07:19:22 2015 -0800
@@ -634,7 +634,7 @@
 						 * field.
 						 */
 					    (void) dwarf_ehe_extract(
-						&data[off + ndx],
+						&data[off],
 						&ndx, ciePflag,
 						ofl->ofl_dehdr->e_ident, B_FALSE,
 						shdr->sh_addr, off + ndx, 0);
--- a/usr/src/cmd/utmpd/Makefile	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/utmpd/Makefile	Sun Jan 04 07:19:22 2015 -0800
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-#
+# Copyright 2014 Shruti V Sampat <shrutisampat@gmail.com>
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
@@ -34,8 +34,6 @@
 
 FILEMODE = 555
 
-CERRWARN += -_gcc=-Wno-extra
-
 .KEEP_STATE:
 
 all: $(PROG)
--- a/usr/src/cmd/utmpd/utmpd.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/utmpd/utmpd.c	Sun Jan 04 07:19:22 2015 -0800
@@ -19,6 +19,10 @@
  * CDDL HEADER END
  */
 /*
+ * Copyright 2014 Shruti V Sampat <shrutisampat@gmail.com>
+ */
+
+/*
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
@@ -177,8 +181,7 @@
  */
 
 int
-main(argc, argv)
-	char **argv;
+main(int argc, char *argv[])
 {
 	char *defp;
 	struct rlimit rlim;
@@ -189,7 +192,7 @@
 
 	if (getuid() != 0)  {
 		(void) fprintf(stderr,
-			"You must be root to run this program\n");
+		    "You must be root to run this program\n");
 		fatal("You must be root to run this program");
 	}
 
@@ -199,9 +202,9 @@
 			Debug = 1;
 		} else {
 			(void) fprintf(stderr,
-				"%s: Wrong number of arguments\n", prog_name);
+			    "%s: Wrong number of arguments\n", prog_name);
 			(void) fprintf(stderr,
-				"Usage: %s [-debug]\n", prog_name);
+			    "Usage: %s [-debug]\n", prog_name);
 			exit(2);
 		}
 	}
@@ -349,7 +352,7 @@
 	register struct pollfd *pfd;
 	register int i;
 	pid_t pid;
-	int ret_val;
+	int ret_val = 0;
 	int timeout;
 	static time_t last_timeout  = 0;
 	static int bad_error  = 0;	/* Count of POLL errors */
--- a/usr/src/cmd/ypcmd/ypinit.sh	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ypcmd/ypinit.sh	Sun Jan 04 07:19:22 2015 -0800
@@ -19,6 +19,7 @@
 #
 # CDDL HEADER END
 #
+# Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
 #
 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
@@ -29,8 +30,6 @@
 # Portions of this source code were derived from Berkeley 4.3 BSD
 # under license from the Regents of the University of California.
 
-#ident	"%Z%%M%	%I%	%E% SMI"
-
 # set -xv
 YPXFR=/usr/lib/netsvc/yp/ypxfr
 MAKEPATH=/usr/ccs/bin
@@ -50,6 +49,7 @@
 master=""
 got_host_list=F
 first_time=T
+non_interactive=F
 exit_on_error=F
 errors_in_setup=F
 
@@ -84,12 +84,13 @@
 # To do cleanup
 trap '/usr/bin/rm -f $hf' 0 1 2 3 15
 
+# Check out total number of arguments
 case $# in
 1)	case $1 in
 	-c)	clientp=T;;
 	-m)	masterp=T;;
 	*)	echo 'usage:'
-		echo '	ypinit -c'
+		echo '	ypinit -c [server_name...]'
 		echo '	ypinit -m'
 		echo '	ypinit -s master_server'
 		echo ""
@@ -111,9 +112,13 @@
 			echo "server not found in $hosts_file or $hosts6_file"
 			exit 1
 		fi;;
-		
+
+	# the case with more than one argument with the '-c' option
+	# is a subject to enter non-interactive mode
+	-c)	clientp=T; non_interactive=T;
+		;;
 	*)	echo 'usage:'
-		echo '	ypinit -c'
+		echo '	ypinit -c [server_name...]'
 		echo '	ypinit -m'
 		echo '	ypinit -s master_server'
 		echo ""
@@ -125,10 +130,14 @@
 master_server must be an existing reachable yp server."
 		exit 1;;
 	esac;;
-3)	case $1 in
-	-c)	clientp=T;;
+*)	case $1 in
+
+	# the case with more than one argument with the '-c' option
+	# is a subject to enter non-interactive mode
+	-c)	clientp=T; non_interactive=T;
+		;;
 	*)	echo 'usage:'
-		echo '	ypinit -c'
+		echo '	ypinit -c [server_name...]'
 		echo '	ypinit -m'
 		echo '	ypinit -s master_server'
 		echo ""
@@ -140,19 +149,6 @@
 master_server must be an existing reachable yp server."
 		exit 1;;
 	esac;;
-
-*)	echo 'usage:'
-	echo '	ypinit -c'
-	echo '	ypinit -m'
-	echo '	ypinit -s master_server'
-	echo ""
-	echo "\
-where -c is used to set up a yp client, -m is used to build a master "
-	echo "\
-yp server data base, and -s is used for a slave data base."
-	echo "\
-master_server must be an existing reachable yp server."
-	exit 1;;
 esac
 
 if [ $? -ne 0 ]
@@ -222,97 +218,114 @@
 
 if [ $slavep = F ]
 then
-	while [ $got_host_list = F ]; do
-		touch $hf    # make sure file exists
-		echo ""
-		echo "\
+	if [ $non_interactive = F ]
+	then
+		while [ $got_host_list = F ]; do
+			touch $hf    # make sure file exists
+			echo ""
+			echo "\
 In order for NIS to operate sucessfully, we have to construct a list of the "
-		echo "\
+			echo "\
 NIS servers.  Please continue to add the names for YP servers in order of"
-		echo "\
+			echo "\
 preference, one per line.  When you are done with the list, type a <control D>"
-		echo "\
+			echo "\
 or a return on a line by itself."
-		if [ $masterp = T ]
-		then
-			echo $host > $hf
-			echo "\tnext host to add:  $host"
-		elif [ -f $binding_file ]
-		then
-			if [ $first_time = T ]
+			if [ $masterp = T ]
+			then
+				echo $host > $hf
+				echo "\tnext host to add:  $host"
+			elif [ -f $binding_file ]
 			then
-				for h in `cat $binding_file`
-				do
-					echo $h >> $hf
-					echo "\tnext host to add:  $h"
-				done
+				if [ $first_time = T ]
+				then
+					for h in `cat $binding_file`
+					do
+						echo $h >> $hf
+						echo "\tnext host to add:  $h"
+					done
+				fi
 			fi
-		fi
+
+			echo  "\tnext host to add:  \c"
 
-		echo  "\tnext host to add:  \c"
+			while read h ; test -n "$h"
+			do
+				#
+				# Host should be in the v4 or v6 hosts file or
+				# reasonably resemble an IP address.  We'll do a
+				# sanity check that a v4 addr is one word consisting
+				# of only numbers and the "." character,
+				# which should guard against fully qualified
+				# hostnames and most malformed entries.  IPv6
+				# addresses can be numbers, hex letters, and have
+				# at least one ":" character and possibly one or
+				# more "." characters for embedded v4 addresses
+				#
+				if ( grep $h $hosts_file $hosts6_file > /dev/null ) || \
+				    ( test $clientp = T && `is_valid_ipaddr $h` )
+				then
+					echo $h >> $hf
+					echo  "\tnext host to add:  \c"
+				else
+					echo "host $h not found in $hosts_file or" \
+					    "$hosts6_file.\nNot added to the list."
+					echo ""
+					echo  "Do you wish to abort [y/n: y]  \c"
+					read cont_ok
+
+					case $cont_ok in
+					n*)	echo "\tnext host to add:  \c";;
+					N*)	echo "\tnext host to add:  \c";;
+					*)	exit 1;;
+					esac
+				fi
+			done
 
-		while read h ; test -n "$h"
-		do
-			#
-			# Host should be in the v4 or v6 hosts file or
-			# reasonably resemble an IP address.  We'll do a
-			# sanity check that a v4 addr is one word consisting
-			# of only numbers and the "." character,
-			# which should guard against fully qualified
-			# hostnames and most malformed entries.  IPv6
-			# addresses can be numbers, hex letters, and have
-			# at least one ":" character and possibly one or
-			# more "." characters for embedded v4 addresses
-			#
-			if ( grep $h $hosts_file $hosts6_file > /dev/null ) || \
-			    ( test $clientp = T && `is_valid_ipaddr $h` )
+			echo ""
+			if [ -s $hf ]
 			then
-				echo $h >> $hf
-				echo  "\tnext host to add:  \c"
+				echo "The current list of yp servers looks like this:"
+				echo ""
+				cat $hf
+				echo ""
+				echo "Is this correct?  [y/n: y]  \c"
 			else
-				echo "host $h not found in $hosts_file or" \
+				echo "You have not added any server information."
+				echo ""
+				echo "Do you still wish to exit? [y/n: y]  \c"
+			fi
+
+			read hlist_ok
+
+			case $hlist_ok in
+			n*)	got_host_list=F
+				first_time=F
+				rm $hf
+				echo "Let's try the whole thing again...";;
+			N*)	got_host_list=F
+				first_time=F
+				rm $hf
+				echo "Let's try the whole thing again...";;
+			*)	got_host_list=T;;
+			esac
+		done
+	else
+		shift
+		> $hf
+		while [[ $# > 0 ]]; do
+			if ( grep $1 $hosts_file $hosts6_file > /dev/null ) || \
+			    ( `is_valid_ipaddr $1` )
+			then
+				echo $1 >> $hf
+			else
+				echo "host $1 not found in $hosts_file or" \
 				    "$hosts6_file.\nNot added to the list."
 				echo ""
-				echo  "Do you wish to abort [y/n: y]  \c"
-				read cont_ok
-
-				case $cont_ok in
-				n*)	echo "\tnext host to add:  \c";;	
-				N*)	echo "\tnext host to add:  \c";;	
-				*)	exit 1;;
-				esac
 			fi
-
+			shift
 		done
-
-		echo ""
-		if [ -s $hf ]
-		then
-			echo "The current list of yp servers looks like this:"
-			echo ""
-			cat $hf
-			echo ""
-			echo "Is this correct?  [y/n: y]  \c"
-		else
-			echo "You have not added any server information."
-			echo ""
-			echo "Do you still wish to exit? [y/n: y]  \c"
-		fi
-
-		read hlist_ok
-
-		case $hlist_ok in
-		n*)	got_host_list=F
-			first_time=F
-			rm $hf
-			echo "Let's try the whole thing again...";;
-		N*)	got_host_list=F
-			first_time=F
-			rm $hf
-			echo "Let's try the whole thing again...";;
-		*)	got_host_list=T;;
-		esac
-	done
+	fi
 
 	if [ -s $hf ]
 	then
--- a/usr/src/cmd/zoneadm/zoneadm.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/zoneadm/zoneadm.c	Sun Jan 04 07:19:22 2015 -0800
@@ -1023,6 +1023,18 @@
 		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
 		    rpath);
 		err = B_TRUE;
+
+		/* Try to change owner */
+		if (cmd_num != CMD_VERIFY) {
+			(void) fprintf(stderr, gettext("%s: changing owner "
+			    "to root.\n"), rpath);
+			if (chown(rpath, 0, -1) != 0) {
+				zperror(rpath, B_FALSE);
+				return (Z_ERR);
+			} else {
+				err = B_FALSE;
+			}
+		}
 	}
 	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath);
 	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath);
@@ -1034,6 +1046,17 @@
 	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath);
 	err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath);
 
+	/* If the group perms are wrong, fix them */
+	if (err && (cmd_num != CMD_VERIFY)) {
+		(void) fprintf(stderr, gettext("%s: changing permissions "
+		    "to 0700.\n"), rpath);
+		if (chmod(rpath, S_IRWXU) != 0) {
+			zperror(path, B_FALSE);
+		} else {
+			err = B_FALSE;
+		}
+	}
+
 	(void) snprintf(ppath, sizeof (ppath), "%s/..", path);
 	if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) {
 		zperror(ppath, B_FALSE);
--- a/usr/src/cmd/ztest/ztest.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/cmd/ztest/ztest.c	Sun Jan 04 07:19:22 2015 -0800
@@ -3905,7 +3905,7 @@
 		 * assign an arcbuf to a dbuf.
 		 */
 		for (j = 0; j < s; j++) {
-			if (i != 5) {
+			if (i != 5 || chunksize < (SPA_MINBLOCKSIZE * 2)) {
 				bigbuf_arcbufs[j] =
 				    dmu_request_arcbuf(bonus_db, chunksize);
 			} else {
@@ -3929,7 +3929,8 @@
 			umem_free(packbuf, packsize);
 			umem_free(bigbuf, bigsize);
 			for (j = 0; j < s; j++) {
-				if (i != 5) {
+				if (i != 5 ||
+				    chunksize < (SPA_MINBLOCKSIZE * 2)) {
 					dmu_return_arcbuf(bigbuf_arcbufs[j]);
 				} else {
 					dmu_return_arcbuf(
@@ -3973,7 +3974,7 @@
 		}
 		for (off = bigoff, j = 0; j < s; j++, off += chunksize) {
 			dmu_buf_t *dbt;
-			if (i != 5) {
+			if (i != 5 || chunksize < (SPA_MINBLOCKSIZE * 2)) {
 				bcopy((caddr_t)bigbuf + (off - bigoff),
 				    bigbuf_arcbufs[j]->b_data, chunksize);
 			} else {
@@ -3990,7 +3991,7 @@
 				VERIFY(dmu_buf_hold(os, bigobj, off,
 				    FTAG, &dbt, DMU_READ_NO_PREFETCH) == 0);
 			}
-			if (i != 5) {
+			if (i != 5 || chunksize < (SPA_MINBLOCKSIZE * 2)) {
 				dmu_assign_arcbuf(bonus_db, off,
 				    bigbuf_arcbufs[j], tx);
 			} else {
--- a/usr/src/head/netdb.h	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/head/netdb.h	Sun Jan 04 07:19:22 2015 -0800
@@ -131,7 +131,10 @@
 	struct addrinfo *ai_next;	/* next structure in linked list */
 };
 
-
+/*
+ * The flag 0x8000 is currently reserved for private use between libnsl and
+ * libsocket. See lib/libsocket/inet/getaddrinfo.c for more information.
+ */
 /* addrinfo flags */
 #define	AI_PASSIVE	0x0008	/* intended for bind() + listen() */
 #define	AI_CANONNAME	0x0010	/* return canonical version of host */
--- a/usr/src/lib/libcmdutils/Makefile.com	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libcmdutils/Makefile.com	Sun Jan 04 07:19:22 2015 -0800
@@ -25,7 +25,8 @@
 
 LIBRARY=	libcmdutils.a
 VERS=		.1
-CMD_OBJS=	avltree.o sysattrs.o writefile.o process_xattrs.o uid.o gid.o
+CMD_OBJS=	avltree.o sysattrs.o writefile.o process_xattrs.o uid.o gid.o \
+		custr.o
 COM_OBJS=	list.o
 OBJECTS=	$(CMD_OBJS) $(COM_OBJS)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libcmdutils/common/custr.c	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+/*
+ * String utility functions with dynamic memory management.
+ */
+
+/*
+ * Copyright 2014, Joyent, Inc.
+ */
+
+#include <stdlib.h>
+#include <err.h>
+#include <string.h>
+
+#include "libcmdutils.h"
+
+struct custr {
+	size_t cus_strlen;
+	size_t cus_datalen;
+	char *cus_data;
+};
+
+#define	STRING_CHUNK_SIZE	64
+
+void
+custr_reset(custr_t *cus)
+{
+	if (cus->cus_data == NULL)
+		return;
+
+	cus->cus_strlen = 0;
+	cus->cus_data[0] = '\0';
+}
+
+size_t
+custr_len(custr_t *cus)
+{
+	return (cus->cus_strlen);
+}
+
+const char *
+custr_cstr(custr_t *cus)
+{
+	return (cus->cus_data);
+}
+
+int
+custr_appendc(custr_t *cus, char newc)
+{
+	char news[2];
+
+	news[0] = newc;
+	news[1] = '\0';
+
+	return (custr_append(cus, news));
+}
+
+int
+custr_append(custr_t *cus, const char *news)
+{
+	size_t len = strlen(news);
+	size_t chunksz = STRING_CHUNK_SIZE;
+
+	while (chunksz < len) {
+		chunksz *= 2;
+	}
+
+	if (len + cus->cus_strlen + 1 >= cus->cus_datalen) {
+		char *new_data;
+		size_t new_datalen = cus->cus_datalen + chunksz;
+
+		/*
+		 * Allocate replacement memory:
+		 */
+		if ((new_data = malloc(new_datalen)) == NULL) {
+			return (-1);
+		}
+
+		/*
+		 * Copy existing data into replacement memory and free
+		 * the old memory.
+		 */
+		if (cus->cus_data != NULL) {
+			(void) memcpy(new_data, cus->cus_data,
+			    cus->cus_strlen + 1);
+			free(cus->cus_data);
+		}
+
+		/*
+		 * Swap in the replacement buffer:
+		 */
+		cus->cus_data = new_data;
+		cus->cus_datalen = new_datalen;
+	}
+	/*
+	 * Append new string to existing string:
+	 */
+	(void) memcpy(cus->cus_data + cus->cus_strlen, news, len + 1);
+	cus->cus_strlen += len;
+
+	return (0);
+}
+
+int
+custr_alloc(custr_t **cus)
+{
+	custr_t *t;
+
+	if ((t = calloc(1, sizeof (*t))) == NULL) {
+		*cus = NULL;
+		return (-1);
+	}
+
+	*cus = t;
+	return (0);
+}
+
+void
+custr_free(custr_t *cus)
+{
+	if (cus == NULL)
+		return;
+
+	free(cus->cus_data);
+	free(cus);
+}
--- a/usr/src/lib/libcmdutils/common/mapfile-vers	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libcmdutils/common/mapfile-vers	Sun Jan 04 07:19:22 2015 -0800
@@ -42,6 +42,13 @@
 SYMBOL_VERSION SUNWprivate_1.1 {
     global:
 	add_tnode;
+	custr_alloc;
+	custr_append;
+	custr_appendc;
+	custr_cstr;
+	custr_free;
+	custr_len;
+	custr_reset;
 	destroy_tree;
 	findnextgid;
 	findnextuid;
--- a/usr/src/lib/libcmdutils/libcmdutils.h	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libcmdutils/libcmdutils.h	Sun Jan 04 07:19:22 2015 -0800
@@ -25,6 +25,9 @@
 /*
  * Copyright (c) 2013 RackTop Systems.
  */
+/*
+ * Copyright 2014 Joyent, Inc.
+ */
 
 /*
  * Declarations for the functions in libcmdutils.
@@ -140,6 +143,46 @@
  */
 extern int findnextgid(gid_t, gid_t, gid_t *);
 
+
+
+		/* dynamic string utilities */
+
+typedef struct custr custr_t;
+
+/*
+ * Allocate and free a "custr_t" dynamic string object.  Returns 0 on success
+ * and -1 otherwise.
+ */
+extern int custr_alloc(custr_t **);
+extern void custr_free(custr_t *);
+
+/*
+ * Append a single character, or a NUL-terminated string of characters, to a
+ * dynamic string.  Returns 0 on success and -1 otherwise.  The dynamic string
+ * will be unmodified if the function returns -1.
+ */
+extern int custr_appendc(custr_t *, char);
+extern int custr_append(custr_t *, const char *);
+
+/*
+ * Determine the length in bytes, not including the NUL terminator, of the
+ * dynamic string.
+ */
+extern size_t custr_len(custr_t *);
+
+/*
+ * Clear the contents of a dynamic string.  Does not free the underlying
+ * memory.
+ */
+extern void custr_reset(custr_t *);
+
+/*
+ * Retrieve a const pointer to a NUL-terminated string version of the contents
+ * of the dynamic string.  Storage for this string should not be freed, and
+ * the pointer will be invalidated by any mutations to the dynamic string.
+ */
+extern const char *custr_cstr(custr_t *str);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/lib/libipadm/common/libipadm.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libipadm/common/libipadm.c	Sun Jan 04 07:19:22 2015 -0800
@@ -18,8 +18,10 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <stdio.h>
@@ -806,14 +808,14 @@
 		status = ipadm_errno2status(err);
 		goto done;
 	}
-	nvlsize = rvalp->ir_nvlsize;
-	nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t);
 
 	/*
-	 * nvlbuf contains a list of nvlists, each of which represents
-	 * configuration information for the given interface(s)
+	 * Daemon reply pointed to by rvalp contains ipmgmt_get_rval_t structure
+	 * followed by a list of packed nvlists, each of which represents
+	 * configuration information for the given interface(s).
 	 */
-	err = nvlist_unpack(nvlbuf, nvlsize, allifs, NV_ENCODE_NATIVE);
+	err = nvlist_unpack((char *)rvalp + sizeof (ipmgmt_get_rval_t),
+	    rvalp->ir_nvlsize, allifs, NV_ENCODE_NATIVE);
 	if (err != 0)
 		status = ipadm_errno2status(err);
 done:
--- a/usr/src/lib/libndmp/common/libndmp.h	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libndmp/common/libndmp.h	Sun Jan 04 07:19:22 2015 -0800
@@ -37,6 +37,7 @@
  */
 /* Copyright (c) 2007, The Storage Networking Industry Association. */
 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
+/* Copyright 2014 Nexenta Systems, Inc.  All rights reserved. */
 #ifndef	_LIBNDMP_H
 #define	_LIBNDMP_H
 
@@ -347,11 +348,11 @@
 extern int ndmp_set_dbglevel(int);
 extern const char *ndmp_strerror(int);
 extern int ndmp_door_status(void);
-extern int ndmp_get_prop(char *, char **);
-extern int ndmp_set_prop(char *, char *);
+extern int ndmp_get_prop(const char *, char **);
+extern int ndmp_set_prop(const char *, const char *);
 extern int ndmp_service_refresh(void);
-extern char *ndmp_base64_encode(char *);
-extern char *ndmp_base64_decode(char *);
+extern char *ndmp_base64_encode(const char *);
+extern char *ndmp_base64_decode(const char *);
 extern ndmp_door_ctx_t *ndmp_door_decode_start(char *, int);
 extern int ndmp_door_decode_finish(ndmp_door_ctx_t *);
 extern ndmp_door_ctx_t *ndmp_door_encode_start(char *, int);
--- a/usr/src/lib/libndmp/common/libndmp_base64.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libndmp/common/libndmp_base64.c	Sun Jan 04 07:19:22 2015 -0800
@@ -36,6 +36,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+/* Copyright 2014 Nexenta Systems, Inc.  All rights reserved. */
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -47,9 +48,6 @@
 #define	NDMP_ENC_LEN	1024
 #define	NDMP_DEC_LEN	256
 
-char *ndmp_base64_encode(char *);
-char *ndmp_base64_decode(char *);
-
 static boolean_t ndmp_is_base64(unsigned char);
 
 static char *b64_data =
@@ -61,9 +59,9 @@
 	return (isalnum(c) || (c == '+') || (c == '/'));
 }
 
-/* caller should use the encloded string and then free the string. */
+/* caller should use the encoded string and then free the string. */
 char *
-ndmp_base64_encode(char *str_to_encode)
+ndmp_base64_encode(const char *str_to_encode)
 {
 	int ret_cnt = 0;
 	int i = 0, j = 0;
@@ -115,7 +113,7 @@
 }
 
 char *
-ndmp_base64_decode(char *encoded_str)
+ndmp_base64_decode(const char *encoded_str)
 {
 	int len = strlen(encoded_str);
 	int i = 0, j = 0;
@@ -136,8 +134,10 @@
 		en_ind++;
 		if (i == 4) {
 			for (i = 0; i < 4; i++) {
-				if ((p = strchr(b64_data, arr_4[i])) == NULL)
+				if ((p = strchr(b64_data, arr_4[i])) == NULL) {
+					free(ret);
 					return (NULL);
+				}
 
 				arr_4[i] = (int)(p - b64_data);
 			}
@@ -161,8 +161,10 @@
 			arr_4[j] = 0;
 
 		for (j = 0; j < 4; j++) {
-			if ((p = strchr(b64_data, arr_4[j])) == NULL)
+			if ((p = strchr(b64_data, arr_4[j])) == NULL) {
+				free(ret);
 				return (NULL);
+			}
 
 			arr_4[j] = (int)(p - b64_data);
 		}
--- a/usr/src/lib/libndmp/common/libndmp_prop.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libndmp/common/libndmp_prop.c	Sun Jan 04 07:19:22 2015 -0800
@@ -75,15 +75,17 @@
 } ndmp_scfhandle_t;
 
 static int ndmp_config_saveenv(ndmp_scfhandle_t *);
-static ndmp_scfhandle_t *ndmp_smf_scf_init(char *);
+static ndmp_scfhandle_t *ndmp_smf_scf_init(const char *);
 static void ndmp_smf_scf_fini(ndmp_scfhandle_t *);
 static int ndmp_smf_start_transaction(ndmp_scfhandle_t *);
 static int ndmp_smf_end_transaction(ndmp_scfhandle_t *);
-static int ndmp_smf_set_property(ndmp_scfhandle_t *, char *, char *);
-static int ndmp_smf_get_property(ndmp_scfhandle_t *, char *, char *, size_t);
-static int ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *, char *);
-static int ndmp_smf_delete_property(ndmp_scfhandle_t *, char *);
-static int ndmp_smf_get_pg_name(ndmp_scfhandle_t *, char *, char **);
+static int ndmp_smf_set_property(ndmp_scfhandle_t *, const char *,
+		const char *);
+static int ndmp_smf_get_property(ndmp_scfhandle_t *, const char *, char *,
+		size_t);
+static int ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *, const char *);
+static int ndmp_smf_delete_property(ndmp_scfhandle_t *, const char *);
+static int ndmp_smf_get_pg_name(ndmp_scfhandle_t *, const char *, char **);
 
 /*
  * This routine send a refresh signal to ndmpd service which cause ndmpd
@@ -105,7 +107,7 @@
  * defined otherwise it would be NULL.
  */
 int
-ndmp_get_prop(char *prop, char **value)
+ndmp_get_prop(const char *prop, char **value)
 {
 	ndmp_scfhandle_t *handle = NULL;
 	char *lval = (char *)malloc(NDMP_PROP_LEN);
@@ -141,7 +143,7 @@
 }
 
 int
-ndmp_set_prop(char *env, char *env_val)
+ndmp_set_prop(const char *env, const char *env_val)
 {
 	ndmp_scfhandle_t *handle = NULL;
 	char *pgname;
@@ -176,7 +178,7 @@
 }
 
 static int
-ndmp_smf_get_pg_name(ndmp_scfhandle_t *h, char *pname, char **pgname)
+ndmp_smf_get_pg_name(ndmp_scfhandle_t *h, const char *pname, char **pgname)
 {
 	scf_value_t *value;
 	scf_property_t *prop;
@@ -250,7 +252,7 @@
  * ndmp_scfhandle_t pointer if success.
  */
 static ndmp_scfhandle_t *
-ndmp_smf_scf_init(char *svc_name)
+ndmp_smf_scf_init(const char *svc_name)
 {
 	ndmp_scfhandle_t *handle;
 
@@ -301,7 +303,7 @@
  * Create a new property group at service level.
  */
 static int
-ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *handle, char *pgroup)
+ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *handle, const char *pgroup)
 {
 	int err;
 
@@ -397,7 +399,7 @@
  * Deletes property in current pg
  */
 static int
-ndmp_smf_delete_property(ndmp_scfhandle_t *handle, char *propname)
+ndmp_smf_delete_property(ndmp_scfhandle_t *handle, const char *propname)
 {
 	scf_transaction_entry_t *entry = NULL;
 
@@ -430,7 +432,7 @@
  */
 static int
 ndmp_smf_set_property(ndmp_scfhandle_t *handle,
-    char *propname, char *valstr)
+    const char *propname, const char *valstr)
 {
 	int ret = 0;
 	scf_value_t *value = NULL;
@@ -516,7 +518,7 @@
  * memory allocated.
  */
 static int
-ndmp_smf_get_property(ndmp_scfhandle_t *handle, char *propname,
+ndmp_smf_get_property(ndmp_scfhandle_t *handle, const char *propname,
     char *valstr, size_t sz)
 {
 	int ret = 0;
--- a/usr/src/lib/libnsl/nss/getipnodeby.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libnsl/nss/getipnodeby.c	Sun Jan 04 07:19:22 2015 -0800
@@ -73,6 +73,8 @@
  * IPNODE_LOOKUPIPNODES	getipnodebyname() needs to lookup the name in ipnodes.
  * IPNODE_LOOKUPHOSTS	getipnodebyname() needs to lookup the name in hosts.
  * IPNODE_ISLITERAL	The name supplied is a literal address string.
+ * IPNODE_UNMAP		The user doesn't want v4 mapped addresses if no IPv6
+ * 			interfaces are plumbed on the system.
  */
 #define	IPNODE_WANTIPV6		0x00000001u
 #define	IPNODE_WANTIPV4		0x00000002u
@@ -80,9 +82,16 @@
 #define	IPNODE_LOOKUPIPNODES	0x00000008u
 #define	IPNODE_LOOKUPHOSTS	0x00000010u
 #define	IPNODE_LITERAL		0x00000020u
+#define	IPNODE_UNMAP		0x00000040u
 #define	IPNODE_IPV4		(IPNODE_WANTIPV4 | IPNODE_IPV4IFNOIPV6)
 
 /*
+ * The private flag between libsocket and libnsl. See
+ * lib/libsocket/inet/getaddrinfo.c for more information.
+ */
+#define	AI_ADDRINFO	0x8000
+
+/*
  * The default set of bits corresponding to a getipnodebyname() flags
  * argument of AI_DEFAULT.
  */
@@ -162,6 +171,10 @@
 			} else if (flags & AI_ALL) {
 				ipnode_bits &= ~IPNODE_IPV4IFNOIPV6;
 			}
+			if ((flags & AI_ADDRCONFIG) && !ipv6configured &&
+			    (flags & AI_ADDRINFO)) {
+				ipnode_bits |= IPNODE_UNMAP;
+			}
 		} else {
 			ipnode_bits &= ~IPNODE_IPV4;
 		}
@@ -343,7 +356,18 @@
 			else if (!(ipnode_bits & IPNODE_WANTIPV6))
 				hp = __filter_addresses(AF_INET6, buf6->result);
 
-			if (hp == NULL)
+			/*
+			 * We've been asked to unmap v4 addresses. This
+			 * situation implies IPNODE_WANTIPV4 and
+			 * !IPNODE_WANTIPV6.
+			 */
+			if (hp != NULL && (ipnode_bits & IPNODE_UNMAP)) {
+				/*
+				 * Just set hp to a new value, cleanup: will
+				 * free the old one
+				 */
+				hp = __mappedtov4(hp, error_num);
+			} else if (hp == NULL)
 				*error_num = NO_ADDRESS;
 		}
 
--- a/usr/src/lib/libsocket/inet/getaddrinfo.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libsocket/inet/getaddrinfo.c	Sun Jan 04 07:19:22 2015 -0800
@@ -69,6 +69,17 @@
 #define	AI_MASK		(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST \
 	| AI_ADDRCONFIG | AI_NUMERICSERV | AI_V4MAPPED | AI_ALL)
 #define	ANY		0
+
+/*
+ * This is a private, undocumented, flag that getaddrinfo() uses for
+ * getipnodebyname(). In the case of AI_ADDRCONFIG && AI_V4MAPPED, if there are
+ * no IPv6 addresses, getaddrinfo() should return non-IPv4 mapped addresses. On
+ * the flip side, getipnodebyname() is defined by RFC 2553 to explicitly do so.
+ * Therefore this private flag indicates to getaddrinfo that we shouldn't do
+ * this.
+ */
+#define	AI_ADDRINFO	0x8000
+
 /* function prototypes for used by getaddrinfo() routine */
 static int get_addr(int family, const char *hostname, struct addrinfo *aip,
 	struct addrinfo *cur, ushort_t port, int version);
@@ -602,7 +613,7 @@
 	/* if hostname argument is literal, name service doesn't get called */
 	if (family == PF_UNSPEC) {
 		hp = getipnodebyname(_hostname, AF_INET6, AI_ALL |
-		    aip->ai_flags | AI_V4MAPPED, &errnum);
+		    aip->ai_flags | AI_V4MAPPED | AI_ADDRINFO, &errnum);
 	} else {
 		hp = getipnodebyname(_hostname, family, aip->ai_flags, &errnum);
 	}
--- a/usr/src/lib/libzfs/common/libzfs_iter.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_iter.c	Sun Jan 04 07:19:22 2015 -0800
@@ -22,7 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013 by Delphix. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <stdio.h>
@@ -186,9 +186,6 @@
 	fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATETXG));
 	fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATION));
 
-	/* Allocate an nvlist to hold the bookmarks. */
-	bmarks = fnvlist_alloc();
-
 	if ((err = lzc_get_bookmarks(zhp->zfs_name, props, &bmarks)) != 0)
 		goto out;
 
--- a/usr/src/lib/nsswitch/dns/Makefile.com	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/nsswitch/dns/Makefile.com	Sun Jan 04 07:19:22 2015 -0800
@@ -22,8 +22,6 @@
 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 # lib/nsswitch/dns/Makefile.com
 
 LIBRARY =	libnss_dns.a
@@ -46,5 +44,5 @@
 
 LINTFLAGS +=	-erroff=E_GLOBAL_COULD_BE_STATIC2
 
-LDLIBS +=	-lnsl
+LDLIBS +=	-lnsl -lsocket
 DYNLIB1 =	nss_dns.so$(VERS)
--- a/usr/src/lib/nsswitch/dns/common/dns_common.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/nsswitch/dns/common/dns_common.c	Sun Jan 04 07:19:22 2015 -0800
@@ -22,12 +22,19 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  *	dns_common.c
  */
 
 #include "dns_common.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <net/if.h>
 
 #pragma weak	dn_expand
 #pragma weak	res_ninit
@@ -321,6 +328,51 @@
 	return (NSS_NOTFOUND);
 }
 
+static int
+_nss_has_interfaces(boolean_t *v4, boolean_t *v6)
+{
+	struct ifaddrs *ifp, *i;
+	struct in_addr in4;
+	struct in6_addr in6;
+	const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+
+	*v4 = *v6 = B_FALSE;
+
+	if (getifaddrs(&ifp) != 0)
+		return (-1);
+
+	for (i = ifp; i != NULL; i = i->ifa_next) {
+		if (i->ifa_flags & IFF_LOOPBACK)
+			continue;
+		if ((i->ifa_flags & IFF_UP) == 0)
+			continue;
+
+		if (i->ifa_addr->sa_family == AF_INET) {
+			if (*v4 != B_FALSE)
+				continue;
+
+			if (((struct sockaddr_in *)i->ifa_addr)->
+			    sin_addr.s_addr == INADDR_ANY)
+				continue;
+			*v4 = B_TRUE;
+		}
+
+		if (i->ifa_addr->sa_family == AF_INET6) {
+			if (*v6 != B_FALSE)
+				continue;
+
+			if (memcmp(&in6addr_any,
+			    &((struct sockaddr_in6 *)i->ifa_addr)->sin6_addr,
+			    sizeof (struct in6_addr)) == 0)
+				continue;
+			*v6 = B_TRUE;
+		}
+	}
+
+	freeifaddrs(ifp);
+	return (0);
+}
+
 /*
  * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode)
  *      nss2 get hosts/ipnodes with ttl backend DNS search engine.
@@ -331,13 +383,6 @@
  * Additionally in the extended results a nssuint_t ttl is placed.
  * This ttl is the lessor of the ttl's extracted from the result.
  *
- * ***Currently the first version of this API only performs simple
- *    single res_nsearch lookups for with T_A or T_AAAA results.
- *    Other searches are deferred to the generic API w/t ttls.
- *
- *    This function is not a generic res_* operation.  It only performs
- *    a single T_A or T_AAAA lookups***
- *
  * RETURNS:  NSS_SUCCESS or NSS_ERROR
  *	If an NSS_ERROR result is returned, nscd is expected
  *	to resubmit the gethosts request using the old style
@@ -384,11 +429,14 @@
 	int		af;
 	char		*ap, *apc;
 	int		hlen = 0, alen, iplen, len, isans;
+	boolean_t	has_v4 = B_FALSE, has_v6 = B_FALSE;
+	int		flags, family, pass2 = 0;
 
 	statp = &stat;
 	(void) memset(statp, '\0', sizeof (struct __res_state));
-	if (res_ninit(statp) == -1)
+	if (res_ninit(statp) == -1) {
 		return (NSS_ERROR);
+	}
 
 	ap = apc = (char *)aliases;
 	alen = 0;
@@ -404,33 +452,152 @@
 		return (NSS_ERROR);
 	}
 
+	/*
+	 * There may be flags set when we are handling ipnode. There are three
+	 * different values for flags:
+	 *
+	 *  o AI_V4MAPPED
+	 *  o AI_ALL
+	 *  o AI_ADDRCONFIG
+	 *
+	 * The first two only have a meaning when af_family is ipv6. The latter
+	 * means something in both cases. These flags are documented in
+	 * getipnodebyname(3SOCKET), though the combinations leave a little
+	 * something to be desired. It would be great if we could actually use
+	 * getipnodebyname directly here since it already knows how to handle
+	 * this kind of logic; however, we're not quite so lucky. Ideally we
+	 * would add such an interface to libresolv.so.2 to handle this kind of
+	 * thing, but that's rather painful as well. We'll summarize what has to
+	 * happen below:
+	 *
+	 * AI_ALL is only meaningful when AI_V4MAPPED is also specified. Both
+	 * are ignored if the family is not AF_INET6
+	 *
+	 * family == AF_INET, flags | AI_ADDRCONFIG
+	 *  - lookup A records iff we have v4 plumbed
+	 * family == AF_INET, !(flags | AI_ADDRCONFIG)
+	 *  - lookup A records
+	 * family == AF_INET6, flags == 0 || flags == AI_ALL
+	 *  - lookup AAAA records
+	 * family == AF_INET6, flags | AI_V4MAPPED
+	 *  - lookup AAAA, if none, lookup A
+	 * family == AF_INET6, flags | AI_ADDRCONFIG
+	 *  - lookup AAAA records if ipv6
+	 * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ALL
+	 *  - lookup AAAA records, lookup A records
+	 * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ADDRCONFIG
+	 *  - lookup AAAA records if ipv6
+	 *  - If no AAAA && ipv4 exists, lookup A
+	 * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ADDRCONFIG &&
+	 * flags | AI_ALL
+	 *  - lookup AAAA records if ipv6
+	 *  - loookup A records if ipv4
+	 */
 	if (ipnode) {
 		/* initially only handle the simple cases */
-		if (arg.key.ipnode.flags != 0) {
-			res_ndestroy(statp);
-			return (NSS_ERROR);
+		name = arg.key.ipnode.name;
+		flags = arg.key.ipnode.flags;
+		family = arg.key.ipnode.af_family;
+		if (flags != 0) {
+			/*
+			 * Figure out our first pass. We'll determine if we need
+			 * to do a second pass afterwards once we successfully
+			 * finish our first pass.
+			 */
+			if ((flags & AI_ADDRCONFIG) != 0) {
+				if (_nss_has_interfaces(&has_v4, &has_v6) !=
+				    0) {
+					res_ndestroy(statp);
+					return (NSS_ERROR);
+				}
+				/* Impossible situations... */
+				if (family == AF_INET && has_v4 == B_FALSE) {
+					res_ndestroy(statp);
+					return (NSS_NOTFOUND);
+				}
+				if (family == AF_INET6 && has_v6 == B_FALSE &&
+				    !(flags & AI_V4MAPPED)) {
+					res_ndestroy(statp);
+					return (NSS_NOTFOUND);
+				}
+				if (family == AF_INET6 && has_v6)
+					qtype = T_AAAA;
+				if (family == AF_INET || (family == AF_INET6 &&
+				    has_v6 == B_FALSE && flags & AI_V4MAPPED))
+					qtype = T_A;
+			} else {
+				has_v4 = has_v6 = B_TRUE;
+				if (family == AF_INET6)
+					qtype = T_AAAA;
+				else
+					qtype = T_A;
+			}
+		} else {
+			if (family == AF_INET6)
+				qtype = T_AAAA;
+			else
+				qtype = T_A;
 		}
-		name = arg.key.ipnode.name;
-		if (arg.key.ipnode.af_family == AF_INET6)
-			qtype = T_AAAA;
-		else
-			qtype = T_A;
 	} else {
 		name = arg.key.name;
 		qtype = T_A;
 	}
+
+searchagain:
 	ret = res_nsearch(statp, name, C_IN, qtype, resbuf.buf, NS_MAXMSG);
 	if (ret == -1) {
-		if (statp->res_h_errno == HOST_NOT_FOUND) {
+		/*
+		 * We want to continue on unless we got NO_RECOVERY. Otherwise,
+		 * HOST_NOT_FOUND, TRY_AGAIN, and NO_DATA all suggest to me that
+		 * we should keep going.
+		 */
+		if (statp->res_h_errno == NO_RECOVERY) {
+			/* else lookup error - handle in general code */
+			res_ndestroy(statp);
+			return (NSS_ERROR);
+		}
+
+		/*
+		 * We found something on our first pass. Make sure that we do
+		 * not clobber this information. This ultimately means that we
+		 * were successful.
+		 */
+		if (pass2 == 2)
+			goto out;
+
+		/*
+		 * If we're on the second pass (eg. we need to check both for A
+		 * and AAAA records), or we were only ever doing a search for
+		 * one type of record and are not supposed to do a second pass,
+		 * then we need to return that we couldn't find anything to the
+		 * user.
+		 */
+		if (pass2 == 1 || flags == 0 || family == AF_INET ||
+		    (family == AF_INET6 && !(flags & AI_V4MAPPED))) {
 			pbuf->p_herrno = HOST_NOT_FOUND;
 			pbuf->p_status = NSS_NOTFOUND;
 			pbuf->data_len = 0;
 			res_ndestroy(statp);
 			return (NSS_NOTFOUND);
 		}
-		/* else lookup error - handle in general code */
-		res_ndestroy(statp);
-		return (NSS_ERROR);
+
+		/*
+		 * If we were only requested to search for flags on an IPv6
+		 * interface or we have no IPv4 interface, we stick to only
+		 * doing a single pass and bail now.
+		 */
+		if ((flags & AI_ADDRCONFIG) && !(flags & AI_ALL) &&
+		    has_v4 == B_FALSE) {
+			pbuf->p_herrno = HOST_NOT_FOUND;
+			pbuf->p_status = NSS_NOTFOUND;
+			pbuf->data_len = 0;
+			res_ndestroy(statp);
+			return (NSS_NOTFOUND);
+		}
+		qtype = T_A;
+		flags = 0;
+		pass2 = 1;
+		goto searchagain;
 	}
 
 	cp = resbuf.buf;
@@ -579,6 +746,16 @@
 		*bptr++ = '\n';
 		blen++;
 	}
+
+	/* Depending on our flags we may need to go back another time. */
+	if (qtype == T_AAAA && family == AF_INET6 &&
+	    ((flags & AI_V4MAPPED) != 0) && ((flags & AI_ALL) != 0) &&
+	    has_v4 == B_TRUE) {
+		qtype = T_A;
+		pass2 = 2; /* Indicate that we found data this pass */
+		goto searchagain;
+	}
+
 	/* Presumably the buffer is now filled. */
 	len = ROUND_UP(blen, sizeof (nssuint_t));
 	/* still room? */
@@ -587,6 +764,7 @@
 		res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
+out:
 	pbuf->ext_off = pbuf->data_off + len;
 	pbuf->ext_len = sizeof (nssuint_t);
 	pbuf->data_len = blen;
--- a/usr/src/lib/pylibbe/common/libbe_py.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/lib/pylibbe/common/libbe_py.c	Sun Jan 04 07:19:22 2015 -0800
@@ -857,6 +857,11 @@
 		return (B_FALSE);
 	}
 
+	if (PyDict_SetItemString(*listDict, BE_ATTR_GLOBAL_ACTIVE,
+	    (be->be_global_active ? Py_True : Py_False)) != 0) {
+		return (B_FALSE);
+	}
+
 	if (be->be_space_used != 0) {
 		if (PyDict_SetItemString(*listDict, BE_ATTR_SPACE,
 		    PyLong_FromUnsignedLongLong(be->be_space_used)) != 0) {
--- a/usr/src/man/man1/Makefile	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1/Makefile	Sun Jan 04 07:19:22 2015 -0800
@@ -180,6 +180,7 @@
 	 	krb5-config.1			\
 	 	ksh93.1				\
 	 	ktutil.1			\
+		kvmstat.1			\
 	 	lari.1				\
 	 	last.1				\
 	 	lastcomm.1			\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/man/man1/kvmstat.1	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,118 @@
+.\"
+.\" 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 (c) 2014, Joyent, Inc.
+.\"
+.Dd Dec 20, 2014
+.Dt KVMSTAT 1
+.Os
+.Sh NAME
+.Nm kvmstat
+.Nd report KVM statistics
+.Sh SYNOPSIS
+.Nm kvmstat
+.Oo
+.Ar interval
+.Op Ar count
+.Oc
+.Sh DESCRIPTION
+.Nm
+reports the activity of running KVM virtual machines and their exit activity,
+injected interrupts, emulations, and more, on a per virtual CPU basis.
+.Lp
+.Nm
+should be used when trying to get a rough sense of guest activity from the
+hypervisor's perspective, and allows one to understand from a low-level
+perspective, what kind of activity is going on inside of the virtual machine. In
+addition,
+.Nm
+is useful for diagnosing reports of pathological or faulty behavior inside of
+guests. While there is no expected range of values for the fields displayed as
+that varies with the use of virtual machines, if all of the virtual CPUs for a
+given virtual machine are consistently zero, then that may indicate that a
+problem has occurred, for example, a panic inside of the guest or a bug in the
+hypervisor.
+.Lp
+If no operands are specified, then
+.Nm
+will display statistics every second until the program is terminated.
+.Ss Output Fields
+Every
+.Ar interval
+.Nm
+will report data with the following fields:
+.Bl -tag -width Ds
+.It Nm pid
+Identifier of the process controlling the virtual CPU.
+.It Nm vcpu
+Virtual CPU identifier relative to its virtual machine.
+.It Nm exits
+Count of all virtual machine exits for the virtual CPU over
+.Ar interval .
+.It Nm haltx
+Count of virtual machine exits due to the guest executing the
+.Sy HLT
+instruction for the virtual CPU over
+.Ar interval .
+.It Nm irqx
+Count of virtual machine exits due to a pending external interrupt arriving
+on the physical CPU that the virtual CPU was actively running on over
+.Ar interval .
+.It Nm irqwx
+Count of virtual machine exits due to an open interrupt window on the
+virtual CPU over
+.Ar interval .
+.It Nm iox
+Count of virtual machine exits due to the execution of an I/O instruction,
+such as
+.Sy inb ,
+on the virtual CPU over
+.Ar interval .
+.It Nm mmiox
+Count of virtual machine exits due to performing memory mapped I/O on the
+virtual CPU over
+.Ar interval .
+.It Nm irqs
+Count of interrupts injected into the virtual CPU over
+.Ar interval .
+.It Nm emul
+Count of instructions the hypervisor had to emulate on behalf of the guest
+virtual CPU over
+.Ar interval .
+.It Nm eptv
+Count of extended page table violations serviced on the virtual CPU over
+.Ar interval .
+.El
+.Sh OPERANDS
+The following operands are supported:
+.Bl -hang -width Ds
+.It Ar count
+.Bd -filled -compact
+Specifies the number of times that the statistics are repeated. If not
+specified,
+.Nm
+will continue until it is terminated.
+.Ed
+.It Ar interval
+.Bd -filled -compact
+Specifies the number of seconds between reports of statistics. If not specified,
+reports are generated every second.
+.Ed
+.El
+.Sh STABILITY
+The arguments are
+.Sy committed ,
+while the output format is
+.Sy Not an interface .
+.Sh SEE ALSO
+.Xr iostat 1M ,
+.Xr mpstat 1M ,
+.Xr attributes 5
--- a/usr/src/man/man1/mailx.1	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1/mailx.1	Sun Jan 04 07:19:22 2015 -0800
@@ -9,7 +9,7 @@
 .\" 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]
-.TH MAILX 1 "Sep 19, 2001"
+.TH MAILX 1 "Dec 18, 2014"
 .SH NAME
 mailx \- interactive message processing system
 .SH SYNOPSIS
@@ -36,7 +36,6 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The mail utilities listed above provide a comfortable, flexible environment for
 sending and receiving mail messages electronically.
@@ -64,7 +63,6 @@
 \fBCommands\fR as in the primary \fBmailbox\fR. This gives rise within these
 pages to the notion of a current \fBmailbox\fR.
 .SH OPTIONS
-.sp
 .LP
 On the command line options start with a dash (\(mi). Any other arguments are
 taken to be destinations (recipients). If no recipients are specified,
@@ -294,7 +292,6 @@
 .RE
 
 .SH OPERANDS
-.sp
 .LP
 The following operands are supported:
 .sp
@@ -308,7 +305,6 @@
 
 .SH USAGE
 .SS "Starting Mail"
-.sp
 .LP
 At startup time, \fBmailx\fR executes the system startup file
 \fB/etc/mail/mailx.rc\fR. If invoked as \fBmail\fR or \fBMail\fR, the system
@@ -380,7 +376,6 @@
 escape character followed by a single command letter and optional arguments.
 See \fBTilde Escapes\fR for a summary of these commands.
 .SS "Reading Mail"
-.sp
 .LP
 Each message is assigned a sequential number, and there is at any time the
 notion of a current message, marked by a right angle bracket (>) in the header
@@ -544,20 +539,23 @@
 shell conventions (see \fBsh\fR(1)). Special characters are recognized by
 certain commands and are documented with the commands below.
 .SS "Sending Mail"
-.sp
 .LP
 Recipients listed on the command line may be of three types: login names, shell
 commands, or alias groups. Login names may be any network address, including
 mixed network addressing. If mail is found to be undeliverable, an attempt is
-made to return it to the sender's \fBmailbox\fR. If the recipient name begins
-with a pipe symbol ( | ), the rest of the name is taken to be a shell command
-to pipe the message through. This provides an automatic interface with any
-program that reads the standard input, such as \fBlp\fR(1) for recording
-outgoing mail on paper. Alias groups are set by the \fBa\fRlias command (see
-\fBCommands\fR below) or in a system startup file (for example,
-\fB$HOME/.mailrc\fR). Aliases are lists of recipients of any type.
+made to return it to the sender's \fBmailbox\fR. If the \fBexpandaddr\fR option
+is not set (the default), then the following rules do not apply and the name of
+the recipient must be a local mailbox or network address. If the recipient name
+begins with a pipe symbol ( | ), the rest of the name is taken to be a shell
+command to pipe the message through. This provides an automatic interface with
+any program that reads the standard input, such as \fBlp\fR(1) for recording
+outgoing mail on paper.
+.sp
+.LP
+Alias groups are set by the \fBa\fRlias command (see \fBCommands\fR below) or in
+a system startup file (for example, \fB$HOME/.mailrc\fR). Aliases are lists of
+recipients of any type.
 .SS "Forwarding Mail"
-.sp
 .LP
 To forward a specific message, include it in a message to the desired
 recipients with the \fB~f\fR or \fB~m\fR tilde escapes. See \fBTilde\fR
@@ -569,7 +567,6 @@
 your mail to a new host by forwarding it to your new address if it is not yet
 listed in the \fBNIS\fR aliases domain.
 .SS "Commands"
-.sp
 .LP
 Regular commands are of the form
 .sp
@@ -768,6 +765,18 @@
 .sp
 .ne 2
 .na
+\fB\fBexpandaddr\fR\fR
+.ad
+.sp .6
+.RS 4n
+Causes recipient addresses to be expanded based on the discussion in the section
+\fBSending Mail\fR. Note that enabling this option allows for addresses that can
+cause arbitrary command execution by starting with the \fB|\fR character.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fBex\fRit\fR
 .ad
 .br
@@ -1621,7 +1630,6 @@
 .RE
 
 .SS "Tilde Escapes"
-.sp
 .LP
 The following tilde escape commands can be used when composing mail to send.
 These may be entered only from \fIinput mode\fR, by beginning a line with the
@@ -1905,7 +1913,6 @@
 .RE
 
 .SS "Internal Variables"
-.sp
 .LP
 The following variables are internal variables. They may be imported from the
 execution environment or set using the \fBse\fRt command at any time. The
@@ -2539,12 +2546,10 @@
 .RE
 
 .SS "Large File Behavior"
-.sp
 .LP
 See \fBlargefile\fR(5) for the description of the behavior of \fBmailx\fR when
 encountering files greater than or equal to 2 Gbyte ( 2^31 bytes).
 .SH ENVIRONMENT VARIABLES
-.sp
 .LP
 See \fBenviron\fR(5) for descriptions of the following environment variables
 that affect the execution of \fBmailx\fR: \fBHOME\fR, \fBLANG\fR,
@@ -2661,7 +2666,6 @@
 .RE
 
 .SH EXIT STATUS
-.sp
 .LP
 When the \fB-e\fR option is specified, the following exit values are returned:
 .sp
@@ -2706,7 +2710,6 @@
 .RE
 
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB$HOME/.mailrc\fR\fR
@@ -2788,7 +2791,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -2804,7 +2806,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBbiff\fR(1B), \fBecho\fR(1), \fBed\fR(1), \fBex\fR(1), \fBfmt\fR(1),
 \fBlp\fR(1), \fBls\fR(1), \fBmail\fR(1), \fBmail\fR(1B), \fBmailcompat\fR(1),
@@ -2813,7 +2814,6 @@
 \fBpasswd\fR(4), \fBattributes\fR(5), \fBenviron\fR(5), \fBlargefile\fR(5),
 \fBstandards\fR(5)
 .SH NOTES
-.sp
 .LP
 Where \fIshell-command\fR is shown as valid, arguments are not always allowed.
 Experimentation is recommended.
--- a/usr/src/man/man1m/ipf.1m	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1m/ipf.1m	Sun Jan 04 07:19:22 2015 -0800
@@ -2,19 +2,19 @@
 .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
 .\" location.
 .\" Portions Copyright (c) 2009, Sun Microsystems Inc. All Rights Reserved.
-.TH IPF 1M "Feb 25, 2009"
+.\" Portions Copyright (c) 2014, Joyent, Inc. All Rights Reserved.
+.TH IPF 1M "Oct 7, 2014"
 .SH NAME
 ipf \- alter packet filtering lists for IP packet input and output
 .SH SYNOPSIS
 .LP
 .nf
-\fBipf\fR [\fB-6AdDEInoPRrsvVyzZ\fR] [\fB-l\fR block | pass | nomatch]
+\fBipf\fR [\fB-6AdDEGInoPRrsvVyzZ\fR] [\fB-l\fR block | pass | nomatch]
      [\fB-T\fR \fIoptionlist\fR] [\fB-F\fR i | o | a | s | S] \fB-f\fR \fIfilename\fR
-     [\fB-f\fR \fIfilename\fR...]
+     [\fB-f\fR \fIfilename\fR...] [\fIzonename\fR]
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBipf\fR utility is part of a suite of commands associated with the
 Solaris IP Filter feature. See \fBipfilter\fR(5).
@@ -34,7 +34,6 @@
 \fB/dev/ipl\fR, and \fB/dev/ipstate\fR. The default permissions of these files
 require \fBipf\fR to be run as root for all operations.
 .SS "Enabling Solaris IP Filter Feature"
-.sp
 .LP
 Solaris IP Filter is installed with the Solaris operating system. However,
 packet filtering is not enabled by default. Use the following procedure to
@@ -159,7 +158,6 @@
 activated.
 .RE
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -257,6 +255,17 @@
 .sp
 .ne 2
 .na
+\fB\fB-G\fR\fR
+.ad
+.sp .6
+.RS 4n
+Make changes to the Global Zone-controlled ipfilter for the zone given as an
+argument. See the \fBZONES\fR section for more information.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-I\fR\fR
 .ad
 .sp .6
@@ -459,8 +468,25 @@
 affect fragment or state statistics.
 .RE
 
+.SH ZONES
+.LP
+Each non-global zone has two ipfilter instances: the in-zone ipfilter, which
+can be controlled from both the zone itself and the global zone, and the
+Global Zone-controlled (GZ-controlled) instance, which can only be controlled
+from the Global Zone. The non-global zone is not able to observe or control
+the GZ-controlled ipfilter.
+
+ipf optionally takes a zone name as an argument, which will change the
+ipfilter settings for that zone, rather than the current one. The zonename
+option is only available in the Global Zone. Using it in any other zone will
+return an error. If the \fB-G\fR option is specified with this argument, the
+Global Zone-controlled ipfilter is operated on. If \fB-G\fR is not specified,
+the in-zone ipfilter is operated on. Note that ipf differs from the other
+ipfilter tools in how the zone name is specified. It takes the zone name as the
+last argument, while all of the other tools take the zone name as an argument
+to the \fB-G\fR and \fB-z\fR options.
+
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/dev/ipauth\fR\fR
@@ -499,7 +525,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -515,16 +540,14 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBipfstat\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBippool\fR(1M),
 \fBsvcadm\fR(1M), \fBsvc.ipfd\fR(1M), \fBipf\fR(4), \fBipnat.conf\fR(4),
-\fBippool\fR(4), \fBattributes\fR(5), \fBipfilter\fR(5)
+\fBippool\fR(4), \fBattributes\fR(5), \fBipfilter\fR(5), \fBzones(5)\fR
 .sp
 .LP
 \fI\fR
 .SH DIAGNOSTICS
-.sp
 .LP
 Needs to be run as root for the packet filtering lists to actually be affected
 inside the kernel.
--- a/usr/src/man/man1m/ipfs.1m	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1m/ipfs.1m	Sun Jan 04 07:19:22 2015 -0800
@@ -2,47 +2,47 @@
 .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
 .\" location.
 .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPFS 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPFS 1M "Oct 30, 2013"
 .SH NAME
 ipfs \- saves and restores information for NAT and state tables
 .SH SYNOPSIS
 .LP
 .nf
-\fBipfs\fR [\fB-nv\fR] \fB-l\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] \fB-l\fR
 .fi
 
 .LP
 .nf
-\fBipfs\fR [\fB-nv\fR] \fB-u\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] \fB-u\fR
 .fi
 
 .LP
 .nf
-\fBipfs\fR [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-R\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-R\fR
 .fi
 
 .LP
 .nf
-\fBipfs\fR [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-W\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-W\fR
 .fi
 
 .LP
 .nf
-\fBipfs\fR [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-r\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-r\fR
 .fi
 
 .LP
 .nf
-\fBipfs\fR [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-w\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-w\fR
 .fi
 
 .LP
 .nf
-\fBipfs\fR [\fB-nNSv\fR] \fB-f\fR \fIfilename\fR \fB-i\fR \fI<if1>\fR,\fI<if2>\fR
+\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] \fB-f\fR \fIfilename\fR \fB-i\fR \fI<if1>\fR,\fI<if2>\fR
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBipfs\fR utility enables the saving of state information across reboots.
 Specifically, the utility allows state information created for NAT entries and
@@ -50,7 +50,6 @@
 to disk. Then, after a reboot, that information is restored. The result of this
 state-saving is that connections are not interrupted.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -164,6 +163,30 @@
 beginning of this operation and unlocked once complete.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.RS 6n
+Operate on the in-zone state information for the specified zone. If neither
+this option nor \fB-G\fR is specified, the current zone is used. This command
+is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for
+more information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.RS 6n
+Operate on the global zone controlled state information for the specified
+zone. If neither this option nor \fB-z\fR is specified, the current zone is
+used. This command is only available in the Global Zone. See \fBZONES\fR in
+\fBipf\fR(1m) for more information.
+.RE
+
 .SH FILES
 .RS +4
 .TP
@@ -196,7 +219,6 @@
 \fB/dev/ipnat\fR
 .RE
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -212,11 +234,10 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
-\fBipf\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5)
+\fBipf\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5),
+\fBzones(5)\fR
 .SH DIAGNOSTICS
-.sp
 .LP
 Arguably, the \fB-W\fR and \fB-R\fR operations should set the locking and,
 rather than undo it, restore it to what it was previously.
--- a/usr/src/man/man1m/ipfstat.1m	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1m/ipfstat.1m	Sun Jan 04 07:19:22 2015 -0800
@@ -2,7 +2,8 @@
 .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
 .\" location.
 .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPFSTAT 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPFSTAT 1M "Oct 30, 2013"
 .SH NAME
 ipfstat \- reports on packet filter statistics and filter list
 .SH SYNOPSIS
@@ -14,11 +15,10 @@
 .LP
 .nf
 \fBipfstat\fR [\fB-C\fR] [\fB-D\fR \fIaddrport\fR] [\fB-P\fR \fIprotocol\fR] [\fB-S\fR \fIaddrport\fR]
-     [\fB-T\fR \fIrefreshtime\fR]
+     [\fB-T\fR \fIrefreshtime\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR]
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBipfstat\fR command is part of a suite of commands associated with the
 Solaris IP Filter feature. See \fBipfilter\fR(5).
@@ -132,7 +132,6 @@
 displayed (where \fIX\fR is the number of rows on the display). There is no way
 to see additional entries.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -351,6 +350,30 @@
 Turn verbose mode on. Displays additional debugging information.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.RS 18n
+Report the in-zone statistics for the specified zone. If neither this option
+nor \fB-G\fR is specified, the current zone is used. This command is only
+available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.RS 18n
+Report the global zone controlled statistics for the specified zone. If
+neither this option nor \fB-z\fR is specified, the current zone is used. This
+command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m)
+for more information.
+.RE
+
 .SH FILES
 .RS +4
 .TP
@@ -377,7 +400,6 @@
 \fB/dev/ipstate\fR
 .RE
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -393,10 +415,9 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBipf\fR(1M), \fBkstat\fR(1M), \fBkstat\fR(3KSTAT), \fBattributes\fR(5),
-\fBipfilter\fR(5)
+\fBipfilter\fR(5), \fBzones(5)\fR
 .sp
 .LP
 \fI\fR
--- a/usr/src/man/man1m/ipmon.1m	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1m/ipmon.1m	Sun Jan 04 07:19:22 2015 -0800
@@ -2,18 +2,18 @@
 .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
 .\" location.
 .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPMON 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPMON 1M "Oct 30, 2013"
 .SH NAME
 ipmon \- monitors /dev/ipl for logged packets
 .SH SYNOPSIS
 .LP
 .nf
 \fBipmon\fR [\fB-abDFhnpstvxX\fR] [\fB-N\fR \fIdevice\fR] [ [o] [NSI]] [\fB-O\fR [NSI]]
-     [\fB-P\fR \fIpidfile\fR] [\fB-S\fR \fIdevice\fR] [\fB-f\fR \fIdevice\fR] [\fIfilename\fR]
+     [\fB-P\fR \fIpidfile\fR] [\fB-S\fR \fIdevice\fR] [\fB-f\fR \fIdevice\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fIfilename\fR]
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBipmon\fR command is part of a suite of commands associated with the
 Solaris IP Filter feature. See \fBipfilter\fR(5).
@@ -102,7 +102,6 @@
 separated by a slash. For example, \fBicmp 3/3\fR for a port unreachable
 message.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -343,6 +342,32 @@
 Show the log header record data in hex.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.sp .6
+.RS 4n
+Monitor packets the specified zone's in-zone filter. If neither this option
+nor \fB-G\fR is specified, the current zone is used. This command is only
+available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.sp .6
+.RS 4n
+Monitor packets for the specified zone's global zone controlled filter. If
+neither this option nor \fB-z\fR is specified, the current zone is used. This
+command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m)
+for more information.
+.RE
+
 .SH FILES
 .RS +4
 .TP
@@ -363,7 +388,6 @@
 \fB/dev/ipstate\fR
 .RE
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -379,15 +403,13 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5),
-\fBipfilter\fR(5)
+\fBipfilter\fR(5), \fBzones(5)\fR
 .sp
 .LP
 \fI\fR
 .SH DIAGNOSTICS
-.sp
 .LP
 \fBipmon\fR expects data that it reads to be consistent with how it should be
 saved and aborts if it fails an assertion which detects an anomaly in the
--- a/usr/src/man/man1m/ipnat.1m	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1m/ipnat.1m	Sun Jan 04 07:19:22 2015 -0800
@@ -2,17 +2,17 @@
 .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
 .\" location.
 .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPNAT 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
+.TH IPNAT 1M "Oct 30, 2013"
 .SH NAME
 ipnat \- user interface to the NAT subsystem
 .SH SYNOPSIS
 .LP
 .nf
-\fBipnat\fR [\fB-CdFhlnRrsv\fR] \fB-f\fR \fIfilename\fR
+\fBipnat\fR [\fB-CdFhlnRrsv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] \fB-f\fR \fIfilename\fR
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBipnat\fR utility opens a specified file (treating \fB-\fR as stdin) and
 parses it for a set of rules that are to be added or removed from the IP NAT.
@@ -32,7 +32,6 @@
 permissions of \fB/dev/ipnat\fR require \fBipnat\fR to be run as root for all
 operations.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -140,8 +139,31 @@
 active rules/table entries.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.RS 15n
+Operate on the in-zone IP NAT for the specified zone. If neither this option
+nor \fB-G\fR is specified, the current zone is used. This command is only
+available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.RS 15n
+Operate on the global zone controlled IP NAT for the specified zone. If
+neither this option nor \fB-z\fR is specified, the current zone is used. This
+command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m)
+for more information.
+.RE
+
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/dev/ipnat\fR\fR
@@ -182,7 +204,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -198,6 +219,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
-\fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(4), \fBattributes\fR(5)
+\fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(4), \fBattributes\fR(5),
+\fBzones(5)\fR
--- a/usr/src/man/man1m/ippool.1m	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1m/ippool.1m	Sun Jan 04 07:19:22 2015 -0800
@@ -2,60 +2,60 @@
 .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
 .\" location.
 .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved.
-.TH IPPOOL 1M "Apr 3, 2008"
+.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
+.TH IPPOOL 1M "Nov 26, 2012"
 .SH NAME
 ippool \- user interface to the IP Filter pools
 .SH SYNOPSIS
 .LP
 .nf
-\fBippool\fR \fB-a\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR
+\fBippool\fR \fB-a\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR
      [/\fInetmask\fR]
 .fi
 
 .LP
 .nf
-\fBippool\fR \fB-A\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-S\fR \fIseed\fR]
+\fBippool\fR \fB-A\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-S\fR \fIseed\fR]
      [\fB-t\fR \fItype\fR]
 .fi
 
 .LP
 .nf
-\fBippool\fR \fB-f\fR \fIfile\fR [\fB-dnuv\fR]
+\fBippool\fR \fB-f\fR \fIfile\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-dnuv\fR]
 .fi
 
 .LP
 .nf
-\fBippool\fR \fB-F\fR [\fB-dv\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR]
+\fBippool\fR \fB-F\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR]
 .fi
 
 .LP
 .nf
-\fBippool\fR \fB-h\fR [\fB-dv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR]
+\fBippool\fR \fB-h\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR]
 .fi
 
 .LP
 .nf
-\fBippool\fR \fB-l\fR [\fB-dv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR]
+\fBippool\fR \fB-l\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR]
 .fi
 
 .LP
 .nf
-\fBippool\fR \fB-r\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR
+\fBippool\fR \fB-r\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR
      [/\fInetmask\fR]
 .fi
 
 .LP
 .nf
-\fBippool\fR \fB-R\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR]
+\fBippool\fR \fB-R\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR]
 .fi
 
 .LP
 .nf
-\fBippool\fR \fB-s\fR [\fB-dtv\fR] [\fB-M\fR \fIcore\fR] [\fB-N\fR \fInamelist\fR]
+\fBippool\fR \fB-s\fR [\fB-dtv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-M\fR \fIcore\fR] [\fB-N\fR \fInamelist\fR]
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBippool\fR utility is used to manage information stored in the IP pools
 subsystem of IP Filter software. Configuration file information can be parsed
@@ -76,11 +76,9 @@
 \fB/dev/ipl\fR, and \fB/dev/ipstate\fR. The default permissions of these files
 require \fBippool\fR to be run as root for all operations.
 .SH OPTIONS
-.sp
 .LP
 \fBippool\fR supports the option categories described below.
 .SS "Global Options"
-.sp
 .LP
 The following global options are supported:
 .sp
@@ -111,8 +109,31 @@
 Turn verbose mode on.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fB-z\fR \fIzonename\fR\fR
+.ad
+.RS 6n
+Manage the specified zone's in-zone IP pools. If neither this option nor
+\fB-G\fR is specified, the current zone is used. This command is only
+available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-G\fR \fIzonename\fR\fR
+.ad
+.RS 6n
+Manage the specified zone's global zone controlled IP pools. If neither this
+option nor \fB-z\fR is specified, the current zone is used. This command is
+only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more
+information.
+.RE
+
 .SS "Instance-Specific Options"
-.sp
 .LP
 The following instance-specific options are supported:
 .sp
@@ -198,7 +219,6 @@
 .RE
 
 .SS "Other Options"
-.sp
 .LP
 The following, additional options are supported:
 .sp
@@ -282,7 +302,6 @@
 .RE
 
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/dev/ippool\fR\fR
@@ -310,7 +329,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -326,6 +344,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
-\fBipf\fR(1M), \fBipfstat\fR(1M), \fBippool\fR(4), \fBattributes\fR(5)
+\fBipf\fR(1M), \fBipfstat\fR(1M), \fBippool\fR(4), \fBattributes\fR(5),
+\fBzones(5)\fR
--- a/usr/src/man/man1m/ypinit.1m	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1m/ypinit.1m	Sun Jan 04 07:19:22 2015 -0800
@@ -4,17 +4,19 @@
 .\" 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]
-.TH YPINIT 1M "Dec 20, 2007"
+.\" Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+.TH YPINIT 1M "Dec 15, 2014"
 .SH NAME
 ypinit \- set up NIS client
 .SH SYNOPSIS
 .LP
 .nf
-\fB/usr/sbin/ypinit\fR [\fB-c\fR] [\fB-m\fR] [\fB-s\fR \fImaster_server\fR]
+\fB/usr/sbin/ypinit\fR \fB-m\fR
+\fB/usr/sbin/ypinit\fR \fB-s\fR [\fImaster_server\fR]
+\fB/usr/sbin/ypinit\fR \fB-c\fR [\fIserver_name...\fR]
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 \fBypinit\fR can be used to set up an \fBNIS\fR client system. You must be the
 superuser to run this command. This script need not be used at all if
@@ -40,14 +42,15 @@
 \fB/var/yp/binding/\fIdomain\fR/ypservers\fR. This file is used by \fBypbind\fR
 when run without the \fB-broadcast\fR option.
 .SH OPTIONS
-.sp
 .ne 2
 .na
-\fB\fB-c\fR\fR
+\fB\fB-c\fR\fR [\fIserver_name...\fR]
 .ad
 .sp .6
 .RS 4n
-Set up a \fBypclient\fR system.
+Set up a \fBypclient\fR system. If \fIserver_name\fR is specified, it will
+replace currently configured list of servers. \fIserver_name\fR could be
+represented by IPv4/v6 address as well as by hostname.
 .RE
 
 .sp
@@ -72,7 +75,6 @@
 .RE
 
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/etc/hosts\fR\fR
@@ -93,12 +95,10 @@
 .RE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBsvcs\fR(1), \fBypwhich\fR(1), \fBsvcadm\fR(1M), \fBypbind\fR(1M),
 \fBsysinfo\fR(2), \fBhosts\fR(4), \fBattributes\fR(5), \fBsmf\fR(5)
 .SH NOTES
-.sp
 .LP
 The \fBNIS client\fR service is managed by the service management facility,
 \fBsmf\fR(5), under the service identifier:
@@ -116,7 +116,6 @@
 requesting restart, can be performed using \fBsvcadm\fR(1M). The service's
 status can be queried using the \fBsvcs\fR(1) command.
 .SH BUGS
-.sp
 .LP
 \fBypinit\fR sets up the list of \fBNIS\fR servers only for the current domain
 on the system when it is run, that is, the domain returned by the
--- a/usr/src/man/man1m/zoneadm.1m	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man1m/zoneadm.1m	Sun Jan 04 07:19:22 2015 -0800
@@ -4,7 +4,7 @@
 .\" 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]
-.TH ZONEADM 1M "Oct 30, 2013"
+.TH ZONEADM 1M "Dec 26, 2014"
 .SH NAME
 zoneadm \- administer zones
 .SH SYNOPSIS
@@ -26,17 +26,14 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBzoneadm\fR utility is used to administer system zones. A zone is an
 application container that is maintained by the operating system runtime.
 .SH SECURITY
-.sp
 .LP
 Once a process has been placed in a zone other than zone \fB0\fR, the process
 or any of its children cannot change zones.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -74,7 +71,6 @@
 .RE
 
 .SH SUBCOMMANDS
-.sp
 .LP
 Subcommands which can result in destructive actions or loss of work have a
 \fB-F\fR flag to force the action. If input is from a terminal device, the user
@@ -279,8 +275,8 @@
 .sp .6
 .RS 4n
 Install the specified zone on the system. This subcommand automatically
-attempts to verify first. It refuses to install if the verify step fails. See
-the \fBverify\fR subcommand.
+attempts to verify first, most verification errors are fatal. See the
+\fBverify\fR subcommand.
 .sp
 .ne 2
 .na
@@ -599,7 +595,6 @@
 .sp
 
 .SH EXIT STATUS
-.sp
 .LP
 The following exit values are returned:
 .sp
@@ -633,7 +628,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -649,7 +643,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBread\fR(1), \fBsvcs\fR(1), \fBzlogin\fR(1), \fBzonename\fR(1),
 \fBinit\fR(1M), \fBkernel\fR(1M), \fBsvcadm\fR(1M), \fBsvc.startd\fR(1M),
@@ -657,7 +650,6 @@
 \fBattributes\fR(5), \fBbrands\fR(5), \fBnative\fR(5), \fBsmf\fR(5),
 \fBzones\fR(5)
 .SH NOTES
-.sp
 .LP
 The \fBzones\fR(5) service is managed by the service management facility,
 \fBsmf\fR(5), under the service identifier:
--- a/usr/src/man/man2/Makefile	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man2/Makefile	Sun Jan 04 07:19:22 2015 -0800
@@ -185,6 +185,7 @@
 	 	facl.2				\
 	 	fchdir.2			\
 	 	fchmod.2			\
+	 	fchmodat.2			\
 	 	fchown.2			\
 	 	fchownat.2			\
 	 	fchroot.2			\
@@ -213,11 +214,12 @@
 	 	lchown.2			\
 		linkat.2			\
 	 	lstat.2				\
-	 	mkdirat.2			\
-	 	mknodat.2			\
+		mkdirat.2			\
+		mknodat.2			\
 	 	openat.2			\
 	 	pathconf.2			\
 		pipe2.2				\
+		ppoll.2				\
 	 	pread.2				\
 	 	pset_assign.2			\
 	 	pset_destroy.2			\
@@ -225,8 +227,8 @@
 	 	putacct.2			\
 	 	putpmsg.2			\
 	 	pwrite.2			\
+		readlinkat.2			\
 	 	readv.2				\
-	 	readlinkat.2			\
 	 	renameat.2			\
 	 	sbrk.2				\
 	 	semtimedop.2			\
@@ -279,6 +281,7 @@
 fchdir.2			:= LINKSRC = chdir.2
 
 fchmod.2			:= LINKSRC = chmod.2
+fchmodat.2			:= LINKSRC = chmod.2
 
 fchown.2			:= LINKSRC = chown.2
 fchownat.2			:= LINKSRC = chown.2
@@ -351,6 +354,8 @@
 
 pipe2.2				:= LINKSRC = pipe.2
 
+ppoll.2				:= LINKSRC = poll.2
+
 pset_assign.2			:= LINKSRC = pset_create.2
 pset_destroy.2			:= LINKSRC = pset_create.2
 
--- a/usr/src/man/man2/open.2	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man2/open.2	Sun Jan 04 07:19:22 2015 -0800
@@ -10,7 +10,7 @@
 .\" 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]
-.TH OPEN 2 "Nov 16, 2013"
+.TH OPEN 2 "Dec 23, 2014"
 .SH NAME
 open, openat \- open a file
 .SH SYNOPSIS
@@ -30,7 +30,6 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBopen()\fR function establishes the connection between a file and a file
 descriptor. It creates an open file description that refers to a file and a
@@ -168,6 +167,19 @@
 .sp
 .ne 2
 .na
+.B O_EXEC
+.na
+.ad
+.sp .6
+.RS 4n
+If set, indicates that the file should be opened for execute permission.
+This option is only valid for regular files, an error will be returned
+if it is not.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fBO_LARGEFILE\fR\fR
 .ad
 .sp .6
@@ -296,6 +308,18 @@
 .sp
 .ne 2
 .na
+.B O_SEARCH
+.ad
+.sp .6
+.RS 4n
+If set, indicates that the directory should be opened for searching.
+This option is only valid for a directory, an error will be returned if
+it is not.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fBO_SYNC\fR\fR
 .ad
 .sp .6
@@ -420,14 +444,12 @@
 The largest value that can be represented correctly in an object of type
 \fBoff_t\fR is established as the offset maximum in the open file description.
 .SH RETURN VALUES
-.sp
 .LP
 Upon successful completion, the \fBopen()\fR function opens the file and return
 a non-negative integer representing the lowest numbered unused file descriptor.
 Otherwise, \fB\(mi1\fR is returned, \fBerrno\fR is set to indicate the error,
 and no files are created or modified.
 .SH ERRORS
-.sp
 .LP
 The \fBopen()\fR and \fBopenat()\fR functions will fail if:
 .sp
@@ -632,6 +654,16 @@
 .sp
 .ne 2
 .na
+.B ENOEXEC
+.ad
+.RS 16n
+The \fBO_EXEC\fR flag is set and \fIpath\fR does not point to a regular
+file.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fBENOLINK\fR\fR
 .ad
 .RS 16n
@@ -676,7 +708,8 @@
 .RS 16n
 A component of the path prefix is not a directory or a relative path was
 supplied to \fBopenat()\fR, the \fBO_XATTR\fR flag was not supplied, and the
-file descriptor does not refer to a directory.
+file descriptor does not refer to a directory. The \fBO_SEARCH\fR flag
+was passed and \fIpath\fR does not refer to a directory.
 .RE
 
 .sp
@@ -877,13 +910,11 @@
 .in -2
 
 .SH USAGE
-.sp
 .LP
 The \fBopen()\fR function has a transitional interface for 64-bit file offsets.
 See \fBlf64\fR(5). Note that using \fBopen64()\fR is equivalent to using
 \fBopen()\fR with \fBO_LARGEFILE\fR set in \fIoflag\fR.
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -903,7 +934,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBIntro\fR(2), \fBchmod\fR(2), \fBclose\fR(2), \fBcreat\fR(2), \fBdup\fR(2),
 \fBexec\fR(2), \fBfcntl\fR(2), \fBgetmsg\fR(2), \fBgetrlimit\fR(2),
@@ -912,7 +942,6 @@
 \fBunlockpt\fR(3C), \fBattributes\fR(5), \fBlf64\fR(5), \fBprivileges\fR(5),
 \fBstandards\fR(5), \fBconnld\fR(7M), \fBstreamio\fR(7I)
 .SH NOTES
-.sp
 .LP
 Hierarchical Storage Management (HSM) file systems can sometimes cause long
 delays when opening a file, since HSM files must be recalled from secondary
--- a/usr/src/man/man2/poll.2	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man2/poll.2	Sun Jan 04 07:19:22 2015 -0800
@@ -1,4 +1,5 @@
 '\" te
+.\" Copyright (c) 2014, Joyent, Inc.
 .\"  Copyright 1989 AT&T  Copyright (c) 2001, Sun Microsystems, Inc.  All Rights Reserved  Portions Copyright (c) 1992, X/Open Company Limited  All Rights Reserved
 .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at
 .\" http://www.opengroup.org/bookstore/.
@@ -16,18 +17,41 @@
 #include <poll.h>
 
 \fBint\fR \fBpoll\fR(\fBstruct pollfd\fR \fIfds[]\fR, \fBnfds_t\fR \fInfds\fR, \fBint\fR \fItimeout\fR);
+
+\fBint\fR \fBppoll\fR(\fBstruct pollfd *restrict\fR \fIfds\fR, \fBnfds_t\fR \fInfds\fR,
+    \fBconst struct timespec *restrict\fR \fItsp\fR, \fBconst sigset_t *restrict\fR \fIsigmask\fR);
 .fi
 
 .SH DESCRIPTION
+.LP
+The \fBpoll()\fR and \fBppoll()\fR functions provides applications with a
+mechanism for multiplexing input/output over a set of file descriptors.  For
+each member of the array pointed to by \fIfds\fR, \fBpoll()\fR and \fBppoll()\fR
+examine the given file descriptor for the event(s) specified in \fIevents\fR.
+The number of \fBpollfd\fR structures in the \fIfds\fR array is specified by
+\fInfds\fR. The \fBpoll()\fR and \fBppoll()\fR functions identify those file
+descriptors on which an application can read or write data, or on which certain
+events have occurred.
 .sp
 .LP
-The \fBpoll()\fR function provides applications with a mechanism for
-multiplexing input/output over a set of file descriptors.  For each member of
-the array pointed to by \fIfds\fR, \fBpoll()\fR examines the given file
-descriptor for the event(s) specified in \fIevents\fR. The number of
-\fBpollfd\fR structures in the \fIfds\fR array is specified by \fInfds\fR. The
-\fBpoll()\fR function identifies those file descriptors on which an application
-can read or write data, or on which certain events have occurred.
+The \fBppoll()\fR function behaves identically to \fBpoll()\fR, except as follows:
+.RS +4
+.TP
+.ie t \(bu
+.el o
+For the \fBppoll\fR function, the timeout period is given in seconds and
+nanoseconds in an argument of type \fBstruct timespec\fR, where as \fBpoll()\fR
+takes a timeout in milliseconds in the form of an integer argument.
+.RE
+.RS +4
+.TP
+.ie t \(bu
+.el o
+The \fBppoll()\fR function takes an optional \fIsigmask\fR argument. When a
+non-\fBNULL\fR pointer is passed, the calling threads signal mask is replaced by
+the one specified in \fIsigset\fR before examining file descriptors, and
+restored before returning.
+.RE
 .sp
 .LP
 The \fIfds\fR argument specifies the file descriptors to be examined and the
@@ -152,35 +176,36 @@
 .sp
 .LP
 If the value \fBfd\fR is less than 0, \fBevents\fR is ignored and \fBrevents\fR
-is set to 0 in that entry on return from  \fBpoll()\fR.
+is set to 0 in that entry on return from \fBpoll()\fR and \fBppoll()\fR.
 .sp
 .LP
-The results of the \fBpoll()\fR query are stored in the \fBrevents\fR member in
-the \fBpollfd\fR structure. Bits are set in the \fBrevents\fR bitmask to
-indicate which of the requested events are true. If none are true, none of the
-specified bits are set in \fBrevents\fR when the \fBpoll()\fR call returns. The
-event flags  \fBPOLLHUP\fR, \fBPOLLERR\fR, and  \fBPOLLNVAL\fR are always  set
-in \fBrevents\fR if the conditions they indicate are true; this occurs even
-though these flags were not present in \fBevents\fR.
+The results of the \fBpoll()\fR or \fBppoll()\fR query are stored in the
+\fBrevents\fR member in the \fBpollfd\fR structure. Bits are set in the
+\fBrevents\fR bitmask to indicate which of the requested events are true. If
+none are true, none of the specified bits are set in \fBrevents\fR when either
+the \fBpoll()\fR or \fBppoll()\fR call returns. The event flags  \fBPOLLHUP\fR,
+\fBPOLLERR\fR, and  \fBPOLLNVAL\fR are always  set in \fBrevents\fR if the
+conditions they indicate are true; this occurs even though these flags were not
+present in \fBevents\fR.
 .sp
 .LP
 If none of the defined events have occurred on any selected file descriptor,
-\fBpoll()\fR waits at least \fItimeout\fR milliseconds for an event to occur on
-any of the selected file descriptors. On a computer where millisecond timing
-accuracy is not available, \fItimeout\fR is rounded up to the nearest legal
-value available on that system. If the value \fItimeout\fR is 0, \fBpoll()\fR
-returns immediately. If the value of \fItimeout\fR is  \(mi1, \fBpoll()\fR
-blocks until a requested event occurs or until the call is interrupted.  The
-\fBpoll()\fR function is not affected by the \fBO_NDELAY\fR and
-\fBO_NONBLOCK\fR flags.
+\fBpoll()\fR and \fBppoll()\fR wait at least \fItimeout\fR milliseconds for an
+event to occur on any of the selected file descriptors. On a computer where
+millisecond timing accuracy is not available, \fItimeout\fR is rounded up to the
+nearest legal value available on that system. If the value \fItimeout\fR is 0,
+\fBpoll()\fR returns immediately. If the value of \fItimeout\fR is  \(mi1,
+\fBpoll()\fR blocks until a requested event occurs or until the call is
+interrupted. If the value of \fBtsp\fR is \fBNULL\fR, then \fBppoll()\fR blocks
+until a requested event occurs or until the call is interrupted. The
+\fBpoll()\fR and \fBppoll()\fR functions are not affected by the \fBO_NDELAY\fR
+and \fBO_NONBLOCK\fR flags.
 .sp
 .LP
-The \fBpoll()\fR function supports regular files, terminal and pseudo-terminal
-devices, streams-based files, FIFOs and pipes.  The behavior of \fBpoll()\fR on
-elements of \fIfds\fR that refer to other types of file is unspecified.
-.sp
-.LP
-The \fBpoll()\fR function supports sockets.
+The \fBpoll()\fR and \fBppoll()\fR functions support regular files, terminal and
+pseudo-terminal devices, streams-based files, FIFOs, pipes, and sockets.  The
+behavior of \fBpoll()\fR and \fBppoll()\fR on elements of \fIfds\fR that refer
+to other types of file is unspecified.
 .sp
 .LP
 A file descriptor for a socket that is listening for connections will indicate
@@ -189,9 +214,9 @@
 is ready for writing, once a connection has been established.
 .sp
 .LP
-Regular files always \fBpoll()\fR \fBTRUE\fR for reading and writing.
+Regular files always \fBpoll()\fR and \fBppoll()\fR \fBTRUE\fR for reading and
+writing.
 .SH RETURN VALUES
-.sp
 .LP
 Upon successful completion, a non-negative value is returned. A positive value
 indicates the total number of file descriptors that has been selected (that is,
@@ -200,9 +225,8 @@
 selected. Upon failure, \fB\(mi1\fR is returned and \fBerrno\fR is set to
 indicate the error.
 .SH ERRORS
-.sp
 .LP
-The \fBpoll()\fR function will fail if:
+The \fBpoll()\fR and \fBppoll()\fR functions will fail if:
 .sp
 .ne 2
 .na
@@ -228,7 +252,7 @@
 \fB\fBEINTR\fR\fR
 .ad
 .RS 10n
-A signal was caught during the \fBpoll()\fR function.
+A signal was caught during the \fBpoll()\fR or \fBppoll()\fR function.
 .RE
 
 .sp
@@ -243,7 +267,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -259,7 +282,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBIntro\fR(2), \fBgetmsg\fR(2), \fBgetrlimit\fR(2), \fBputmsg\fR(2),
 \fBread\fR(2), \fBwrite\fR(2), \fBselect\fR(3C), \fBattributes\fR(5),
@@ -268,7 +290,6 @@
 .LP
 \fISTREAMS Programming Guide\fR
 .SH NOTES
-.sp
 .LP
 Non-STREAMS drivers use  \fBchpoll\fR(9E) to implement  \fBpoll()\fR on these
 devices.
--- a/usr/src/man/man3c/Makefile	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/Makefile	Sun Jan 04 07:19:22 2015 -0800
@@ -60,6 +60,7 @@
 	 	catopen.3c					\
 	 	cfgetispeed.3c					\
 	 	cfsetispeed.3c					\
+		clearenv.3c					\
 	 	clock.3c					\
 	 	clock_nanosleep.3c				\
 	 	clock_settime.3c				\
@@ -112,6 +113,7 @@
 	 	exit.3c						\
 	 	fattach.3c					\
 	 	fclose.3c					\
+		fcloseall.3c					\
 	 	fdatasync.3c					\
 	 	fdetach.3c					\
 	 	fdopen.3c					\
@@ -159,12 +161,14 @@
 	 	getlogin.3c					\
 	 	getmntent.3c					\
 	 	getnetgrent.3c					\
+		get_nprocs.3c					\
 	 	getopt.3c					\
 	 	getpagesize.3c					\
 	 	getpagesizes.3c					\
 	 	getpass.3c					\
 	 	getpeerucred.3c					\
 	 	getpriority.3c					\
+		getprogname.3c					\
 	 	getpw.3c					\
 	 	getpwnam.3c					\
 	 	getrusage.3c					\
@@ -406,6 +410,7 @@
 	 	sigwaitinfo.3c					\
 	 	sleep.3c					\
 	 	ssignal.3c					\
+		smt_pause.3c					\
 	 	stack_getbounds.3c				\
 	 	stack_inbounds.3c				\
 	 	stack_setbounds.3c				\
@@ -671,6 +676,7 @@
 	 	btowc_l.3c				\
 	 	bzero.3c				\
 	 	calloc.3c				\
+		canonicalize_file_name.3c		\
 	 	catclose.3c				\
 	 	cfgetospeed.3c				\
 	 	cfsetospeed.3c				\
@@ -734,6 +740,8 @@
 	 	fdopendir.3c				\
 	 	fdwalk.3c				\
 	 	feof.3c					\
+		ffsl.3c					\
+		ffsll.3c				\
 	 	fgetgrent.3c				\
 	 	fgetgrent_r.3c				\
 	 	fgetpwent.3c				\
@@ -746,6 +754,9 @@
 	 	file_to_decimal.3c			\
 	 	fileno.3c				\
 	 	finite.3c				\
+		fls.3c					\
+		flsl.3c					\
+		flsll.3c				\
 	 	fpclass.3c				\
 	 	fpgetmask.3c				\
 	 	fpgetsticky.3c				\
@@ -783,6 +794,7 @@
 	 	getlogin_r.3c				\
 	 	getmntany.3c				\
 	 	getnetgrent_r.3c			\
+		get_nprocs_conf.3c			\
 	 	getpassphrase.3c			\
 	 	getpwent.3c				\
 	 	getpwent_r.3c				\
@@ -914,11 +926,12 @@
 	 	memchr.3c				\
 	 	memcmp.3c				\
 	 	memcpy.3c				\
+	 	memmem.3c				\
 	 	memmove.3c				\
 	 	memset.3c				\
 	 	minor.3c				\
 	 	mkdtemp.3c				\
-	 	mkfifoat.3c				\
+		mkfifoat.3c				\
 		mkostemp.3c				\
 		mkostemps.3c				\
 	 	mkstemps.3c				\
@@ -1009,7 +1022,7 @@
 	 	pthread_mutexattr_setprioceiling.3c	\
 	 	pthread_mutexattr_setprotocol.3c	\
 	 	pthread_mutexattr_setpshared.3c		\
-		pthread_mutexattr_setrobust.3c		\
+	 	pthread_mutexattr_setrobust.3c		\
 	 	pthread_mutexattr_settype.3c		\
 	 	pthread_rwlock_destroy.3c		\
 	 	pthread_rwlock_reltimedrdlock_np.3c	\
@@ -1090,6 +1103,7 @@
 	 	setlogmask.3c				\
 	 	setnetgrent.3c				\
 	 	setpriority.3c				\
+		setprogname.3c				\
 	 	setpwent.3c				\
 	 	setspent.3c				\
 	 	setstate.3c				\
@@ -1124,15 +1138,21 @@
 		stderr.3c				\
 		stdin.3c				\
 		stdout.3c				\
+		stpcpy.3c				\
+		stpncpy.3c				\
 	 	strcasecmp.3c				\
 	 	strcasecmp_l.3c				\
+		strcasestr.3c				\
+		strcasestr_l.3c				\
 	 	strcat.3c				\
 	 	strchr.3c				\
+		strchrnul.3c				\
 	 	strcmp.3c				\
 	 	strcoll_l.3c				\
 	 	strcpy.3c				\
 	 	strcspn.3c				\
 	 	strdup.3c				\
+	 	strdupa.3c				\
 	 	strerror_r.3c				\
 	 	strfmon_l.3c				\
 	 	strftime_l.3c				\
@@ -1144,7 +1164,10 @@
 	 	strncat.3c				\
 	 	strncmp.3c				\
 	 	strncpy.3c				\
+		strndup.3c				\
+		strndupa.3c				\
 	 	strnlen.3c				\
+		strnstr.3c				\
 	 	strpbrk.3c				\
 	 	strptime_l.3c				\
 	 	strrchr.3c				\
@@ -1440,6 +1463,8 @@
 
 btowc_l.3c				:= LINKSRC = btowc.3c
 
+canonicalize_file_name.3c		:= LINKSRC = realpath.3c
+
 catclose.3c				:= LINKSRC = catopen.3c
 
 cfgetospeed.3c				:= LINKSRC = cfgetispeed.3c
@@ -1562,6 +1587,12 @@
 feof.3c					:= LINKSRC = ferror.3c
 fileno.3c				:= LINKSRC = ferror.3c
 
+ffsl.3c					:= LINKSRC = ffs.3c
+ffsll.3c				:= LINKSRC = ffs.3c
+fls.3c					:= LINKSRC = ffs.3c
+flsl.3c					:= LINKSRC = ffs.3c
+flsll.3c				:= LINKSRC = ffs.3c
+
 fsetattr.3c				:= LINKSRC = fgetattr.3c
 getattrat.3c				:= LINKSRC = fgetattr.3c
 setattrat.3c				:= LINKSRC = fgetattr.3c
@@ -1643,10 +1674,14 @@
 innetgr.3c				:= LINKSRC = getnetgrent.3c
 setnetgrent.3c				:= LINKSRC = getnetgrent.3c
 
+get_nprocs_conf.3c			:= LINKSRC = get_nprocs.3c
+
 getpassphrase.3c			:= LINKSRC = getpass.3c
 
 setpriority.3c				:= LINKSRC = getpriority.3c
 
+setprogname.3c				:= LINKSRC = getprogname.3c
+
 endpwent.3c				:= LINKSRC = getpwnam.3c
 fgetpwent.3c				:= LINKSRC = getpwnam.3c
 fgetpwent_r.3c				:= LINKSRC = getpwnam.3c
@@ -1809,6 +1844,7 @@
 memchr.3c				:= LINKSRC = memory.3c
 memcmp.3c				:= LINKSRC = memory.3c
 memcpy.3c				:= LINKSRC = memory.3c
+memmem.3c				:= LINKSRC = memory.3c
 memmove.3c				:= LINKSRC = memory.3c
 memset.3c				:= LINKSRC = memory.3c
 
@@ -2113,14 +2149,20 @@
 cftime.3c				:= LINKSRC = strftime.3c
 strftime_l.3c				:= LINKSRC = strftime.3c
 
+stpcpy.3c				:= LINKSRC = string.3c
+stpncpy.3c				:= LINKSRC = string.3c
 strcasecmp.3c				:= LINKSRC = string.3c
 strcasecmp_l.3c				:= LINKSRC = string.3c
+strcasestr.3c				:= LINKSRC = string.3c
+strcasestr_l.3c				:= LINKSRC = string.3c
 strcat.3c				:= LINKSRC = string.3c
 strchr.3c				:= LINKSRC = string.3c
+strchrnul.3c				:= LINKSRC = string.3c
 strcmp.3c				:= LINKSRC = string.3c
 strcpy.3c				:= LINKSRC = string.3c
 strcspn.3c				:= LINKSRC = string.3c
 strdup.3c				:= LINKSRC = string.3c
+strdupa.3c				:= LINKSRC = string.3c
 strlcat.3c				:= LINKSRC = string.3c
 strlcpy.3c				:= LINKSRC = string.3c
 strlen.3c				:= LINKSRC = string.3c
@@ -2129,7 +2171,10 @@
 strncat.3c				:= LINKSRC = string.3c
 strncmp.3c				:= LINKSRC = string.3c
 strncpy.3c				:= LINKSRC = string.3c
+strndup.3c				:= LINKSRC = string.3c
+strndupa.3c				:= LINKSRC = string.3c
 strnlen.3c				:= LINKSRC = string.3c
+strnstr.3c				:= LINKSRC = string.3c
 strpbrk.3c				:= LINKSRC = string.3c
 strrchr.3c				:= LINKSRC = string.3c
 strsep.3c				:= LINKSRC = string.3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/man/man3c/clearenv.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,64 @@
+.\"
+.\" 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 (c) 2014, Joyent, Inc.
+.\"
+.Dd "Dec 20, 2014"
+.Dt CLEARENV 3C
+.Os
+.Sh NAME
+.Nm clearenv
+.Nd clear environment
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fo clearenv
+.Fa void
+.Fc
+.Sh DESCRIPTION
+The
+.Fn clearenv
+function clears the contents of the environment. All environment variables in
+the calling process are removed as though the function
+.Xr unsetenv 3C
+had been called on every environment variable. Until subsequent calls to
+.Xr putenv 3C
+or
+.Xr setenv 3C
+are made, calls to
+.Xr getenv 3C
+will always return
+.Sy NULL .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn clearenv
+returns
+.Sy 0 .
+Otherwise, it returns a non-zero value and sets
+.Sy errno
+to indicate the error. At this time, no errors are defined for
+.Fn clearenv ,
+it will always succeed. Portable applications should always check the return
+value of
+.Fn clearenv .
+.Sh ERRORS
+No errors are defined.
+.Sh INTERFACE STABILITY
+.Sy Committed .
+.Sh MT-LEVEL
+.Sy Mt-Safe .
+.Sh SEE ALSO
+.Xr getenv 3C ,
+.Xr unsetenv 3C ,
+.Xr setenv 3C ,
+.Xr attributes 5 ,
+.Xr environ 5 ,
+.Xr standards 5
--- a/usr/src/man/man3c/fclose.3c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/fclose.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -19,7 +19,6 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBfclose()\fR function causes the stream pointed to by \fIstream\fR to be
 flushed and the associated file to be closed. Any unwritten buffered data for
@@ -42,12 +41,10 @@
 The \fBfclose()\fR function is performed automatically for all open files upon
 calling \fBexit\fR(2).
 .SH RETURN VALUES
-.sp
 .LP
 Upon successful completion, \fBfclose()\fR returns \fB0\fR. Otherwise, it
 returns \fBEOF\fR and sets \fBerrno\fR to indicate the error.
 .SH ERRORS
-.sp
 .LP
 The \fBfclose()\fR function will fail if:
 .sp
@@ -135,7 +132,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -153,7 +149,7 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBclose\fR(2), \fBexit\fR(2), \fBgetrlimit\fR(2), \fBulimit\fR(2),
-\fBfopen\fR(3C), \fBstdio\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5)
+\fBfcloseall\fR(3C), \fBfopen\fR(3C), \fBstdio\fR(3C),
+\fBattributes\fR(5), \fBstandards\fR(5)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/man/man3c/fcloseall.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,53 @@
+.\"
+.\" 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 (c) 2014, Joyent, Inc.
+.\"
+.Dd "Dec 20, 2014"
+.Dt FCLOSEALL 3C
+.Os
+.Sh NAME
+.Nm fcloseall
+.Nd close all standard I/O streams
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fo fcloseall
+.Fa void
+.Fc
+.Sh DESCRIPTION
+The
+.Fn fcloseall
+function closes all open standard I/O streams. The equivalent of
+.Xr fflush 3C
+is called on each stream before closing, thus any buffered or pending
+input is discarded while any buffered or pending output is written out
+to the underlying file. This includes the standard streams,
+.Vt stdin ,
+.Vt stdout ,
+and
+.Vt stderr .
+.Sh RETURN VALUES
+Currently, the function
+.Fn fcloseall
+always returns
+.Sy 0 .
+Note, portable applications should always check the return value.
+.Sh INTERFACE STABILITY
+.Sy Committed .
+.Sh MT-LEVEL
+.Sy Mt-Safe .
+.Sh SEE ALSO
+.Xr close 3C ,
+.Xr fflush 3C ,
+.Xr attributes 5 ,
+.Xr environ 5 ,
+.Xr standards 5
--- a/usr/src/man/man3c/ffs.3c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/ffs.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -1,4 +1,5 @@
 '\" te
+.\" Copyright (c) 2014, Joyent, Inc.
 .\"  Copyright 1989 AT&T  Copyright (c) 2002, Sun Microsystems, Inc.  All Rights Reserved  Portions Copyright (c) 1992, X/Open Company Limited  All Rights Reserved
 .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at
 .\" http://www.opengroup.org/bookstore/.
@@ -15,26 +16,41 @@
 .nf
 #include <strings.h>
 
-\fBint\fR \fBffs\fR(\fBconst int\fR \fIi\fR);
+\fBint\fR \fBffs\fR(\fBint\fR \fIi\fR);
+
+\fBint\fR \fBffsl\fR(\flong\fR \fIi\fR);
+
+\fBint\fR \fBffsll\fR(\fBlong long\fR \fIi\fR);
+
+\fBint\fR \fBfls\fR(\fBint\fR \fIi\fR);
+
+\fBint\fR \fBflsl\fR(\fBlong\fR \fIi\fR);
+
+\fBint\fR \fBflsl\fR(\fBlong long\fR \fIi\fR);
 .fi
 
 .SH DESCRIPTION
+.LP
+The \fBffs()\fR, \fBffsl()\, and \fBffsll()\fR functions finds the first bit set
+(beginning with the least significant bit) and return the index of that bit.
+Bits are numbered starting at one (the least significant bit).
 .sp
 .LP
-The \fBffs()\fR function finds the first bit set (beginning with the least
-significant bit) and returns the index of that bit.  Bits are numbered starting
-at one (the least significant bit).
+The \fBfls()\fR, \fBflsl()\fR, and \fBflsll()\fR functions find the last bit set
+(beginning with the most significant bit) and return the index of that bit.
+Bits are numbered starting at one (the least significant bit).
 .SH RETURN VALUES
+.LP
+The \fBffs()\fR, \fBffsl()\fR, and \fBffsll()\fR functions returns the index of
+the first bit set.  If \fIi\fR is 0, then they return 0.
 .sp
 .LP
-The \fBffs()\fR function returns the index of the first bit set.  If \fIi\fR is
-0, then \fBffs()\fR returns 0.
+The \fBfls()\fR, \fBflsl()\fR, and \fBflsll()\fR functions return the index of
+the last bit set.  If \fIi\fR is 0, then they return 0.
 .SH ERRORS
-.sp
 .LP
 No errors are defined.
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -46,12 +62,11 @@
 l | l .
 ATTRIBUTE TYPE	ATTRIBUTE VALUE
 _
-Interface Stability	Standard
+Interface Stability	Committed
 _
 MT-Level	MT-Safe
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBattributes\fR(5), \fBstandards\fR(5)
--- a/usr/src/man/man3c/fopen.3c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/fopen.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -4,7 +4,7 @@
 .\" Copyright (c) 2006, Sun Microsystems, Inc.  All Rights Reserved.
 .\" Portions Copyright (c) 1992, X/Open Company Limited.  All Rights Reserved.
 .\" Portions Copyright (c) 2013, OmniTI Computer Consulting, Inc.  All Rights Reserved.
-.\" Portions Copyright (c) 2013, Joyent, Inc.  All Rights Reserved.
+.\" Portions Copyright (c) 2014, Joyent, Inc.  All Rights Reserved.
 .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at
 .\" http://www.opengroup.org/bookstore/.
 .\" The Institute of Electrical and Electronics Engineers and The Open Group, have given us permission to reprint portions of their documentation. In the following statement, the phrase "this text" refers to portions of the system documentation. Portions of this text are reprinted and reproduced in electronic form in the Sun OS Reference Manual, from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any discrepancy between these versions and the original IEEE and The Open Group Standard, the original IEEE and The Open Group Standard is the referee document. The original Standard can be obtained online at http://www.opengroup.org/unix/online.html.
@@ -402,6 +402,7 @@
 respects this function is Standard.
 .SH SEE ALSO
 .LP
-\fBenable_extended_FILE_stdio\fR(3C), \fBfclose\fR(3C), \fBfdopen\fR(3C),
-\fBfflush\fR(3C), \fBfreopen\fR(3C), \fBfsetpos\fR(3C), \fBrewind\fR(3C),
-\fBopen\fR(2), \fBattributes\fR(5), \fBlf64\fR(5), \fBstandards\fR(5)
+\fBenable_extended_FILE_stdio\fR(3C), \fBfclose\fR(3C),
+\fRfcloseall\fR(3C), \fBfdopen\fR(3C), \fBfflush\fR(3C),
+\fBfreopen\fR(3C), \fBfsetpos\fR(3C), \fBrewind\fR(3C), \fBopen\fR(2),
+\fBattributes\fR(5), \fBlf64\fR(5), \fBstandards\fR(5)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/man/man3c/get_nprocs.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,59 @@
+.\"
+.\" 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 (c) 2014 Joyent, Inc.
+.\"
+.Dd "Dec 21, 2014"
+.Dt GET_NPROCS 3C
+.Os
+.Sh NAME
+.Nm get_nprocs ,
+.Nm get_nprocs_conf
+.Nd get number of processors
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fo get_nprocs
+.Fa void
+.Fc
+.Ft int
+.Fo get_nprocs_conf
+.Fa void
+.Fc
+.Sh DESCRIPTION
+The
+.Fn get_nprocs
+and
+.Fn get_nprocs_conf
+functions are provided for compatibility with other systems and are
+equivalent to calling
+.Fn sysconf _SC_NPROCESSORS_ONLN
+and
+.Fn sysconf _SC_NPROCESSORS_CONF
+respectively.
+.Sh RETURN VALUES
+The
+.Fn get_nprocs
+function returns the number of processors that are currently online. The
+.Fn get_nprocs_conf
+function returns the number of processors that the operating system has
+configured.
+.Sh INTERFACE STABILITY
+.Sy Committed .
+.Sh MT-LEVEL
+.Sy MT-Safe ,
+.Sy Async-Signal-Safe
+.Sh SEE ALSO
+.Xr psrinfo 1M ,
+.Xr processor_info 2 ,
+.Xr sysconf 3C ,
+.Xr attributes 5 ,
+.Xr standards 5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/man/man3c/getprogname.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,77 @@
+.\"
+.\" 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 (c) 2014, Joyent, Inc.
+.\"
+.Dd "Dec 22, 2014"
+.Dt GETPROGNAME 3C
+.Os
+.Sh NAME
+.Nm getprogname ,
+.Nm setprogname
+.Nd get or set the program name
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft const char *
+.Fo getprogname
+.Fa void
+.Fc
+.Ft void
+.Fo setprogname
+.Fa "const char *progname"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn getprogname
+function is used to obtain the program name. The program name is set at
+program start-up, before
+.Fn main
+is called. Note, other operating systems, do not guarantee that a
+program name has been set at start up time and therefore may return a
+null pointer if
+.Fn setprogname
+has not been called.
+.Lp
+The
+.Fn setprogname
+function is used to change the program name to another value. The
+argument
+.Fa progname
+must contain a null terminatd character string, whose last component
+which will become the new program name.
+.Sh RETURN VALUES
+The
+.Fn getprogname
+function always returns the current program name. The program name is
+always set, it will not return a null pointer.
+.Sh INTERFACE STABILITY
+.Sy Committed
+.Sh MT-LEVEL
+.Fn getprogname
+is
+.Sy MT-Safe .
+.Lp
+.Fn setprogname
+is
+.Sy Unsafe .
+.Sh SEE ALSO
+.Xr err 3c ,
+.Xr attributes 5
+.Sh NOTES
+The use of
+.Fn setprogname
+does not modify the program name as reported by utilities like
+.Xr ps 1
+or
+.Xr pargs 1 ;
+however, it does ensure a consistent program name for the
+.Xr err 3C
+family of functions.
--- a/usr/src/man/man3c/mbsrtowcs.3c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/mbsrtowcs.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -10,7 +10,7 @@
 .\" 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]
 .TH MBSRTOWCS 3C "Jun 28, 2014"
 .SH NAME
-mbsnrtwocs, mbsnrtowcs_l, mbsrtowcs, mbsrtowcs_l \- convert a character string
+mbsnrtowcs, mbsnrtowcs_l, mbsrtowcs, mbsrtowcs_l \- convert a character string
 to a wide-character string (restartable)
 .SH SYNOPSIS
 .LP
--- a/usr/src/man/man3c/memory.3c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/memory.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -1,4 +1,5 @@
 '\" te
+.\" Copyright (c) 2014, Joyent, Inc.
 .\" Copyright (c) 2009, Sun Microsystems, Inc.  All Rights Reserved.
 .\" Copyright 1989 AT&T
 .\" 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.
@@ -6,7 +7,7 @@
 .\" 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]
 .TH MEMORY 3C "Feb 4, 2009"
 .SH NAME
-memory, memccpy, memchr, memcmp, memcpy, memmove, memset \- memory operations
+memory, memccpy, memchr, memcmp, memcpy, memmem, memmove, memset \- memory operations
 .SH SYNOPSIS
 .LP
 .nf
@@ -33,6 +34,11 @@
 
 .LP
 .nf
+\fBvoid *\fR\fBmemmem\fR(\fBconst void *\fR\fIl\fR, \fBsize_t\fR \fIl_len\fR, \fBconst void *\fR\fIs\fR, \fBsize_t\fR \fIs_len\fR);
+.fi
+
+.LP
+.nf
 \fBvoid *\fR\fBmemmove\fR(\fBvoid *\fR\fIs1\fR, \fBconst void *\fR\fIs2\fR, \fBsize_t\fR \fIn\fR);
 .fi
 
@@ -57,7 +63,6 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 These functions operate as efficiently as possible on memory areas (arrays of
 bytes bounded by a count, not terminated by a null character). They do not
@@ -90,6 +95,13 @@
 overlap, the behavior is undefined.
 .sp
 .LP
+The \fBmemmem()\fR function searches for the \fIs_len\fR long byte pattern
+\fIs\fR in the memory region starting at \fBl\fR for \fl_len\fR bytes. If a
+match is found, a pointer to the starting location in \fIl\fR is returned. If no
+match is found, \fIl_len\fR is zero, \fIs_len\fR is zero, or \fIl_len\fR is less
+than \fIs_len\fR, then a null pointer is return.
+.sp
+.LP
 The \fBmemmove()\fR function copies \fIn\fR bytes from memory area \fIs2\fR to
 memory area \fIs1\fR. Copying between objects that overlap will take place
 correctly. It returns \fIs1\fR.
@@ -99,12 +111,10 @@
 to the value of \fIc\fR (converted to an \fBunsigned char\fR). It returns
 \fIs\fR.
 .SH USAGE
-.sp
 .LP
 Using \fBmemcpy()\fR might be faster than using \fBmemmove()\fR if the
 application knows that the objects being copied do not overlap.
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -124,11 +134,9 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBstring\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5)
 .SH NOTES
-.sp
 .LP
 Overlap between objects being copied can arise even when their (virtual)
 address ranges appear to be disjoint; for example, as a result of
--- a/usr/src/man/man3c/realpath.3c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/realpath.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -1,4 +1,5 @@
 '\" te
+.\" Copyright (c) 2014, Joyent, Inc.
 .\" Copyright 1989 AT&T.  Copyright (c) 2003, Sun Microsystems, Inc.  All Rights Reserved.  Portions Copyright (c) 1992, X/Open Company Limited.  All Rights Reserved.
 .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at
 .\" http://www.opengroup.org/bookstore/.
@@ -7,7 +8,7 @@
 .\" 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]
-.TH REALPATH 3C "Oct 9, 2003"
+.TH REALPATH 3C "Dec 20, 2014"
 .SH NAME
 realpath \- resolve pathname
 .SH SYNOPSIS
@@ -17,10 +18,11 @@
 
 \fBchar *\fR\fBrealpath\fR(\fBconst char *restrict\fR \fIfile_name\fR,
      \fBchar *restrict\fR \fIresolved_name\fR);
+
+\fBchar *\fR\fBcanonicalize_file_name\fR(\fBconst char *\fR\fIpath\fR);
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBrealpath()\fR function derives, from the pathname pointed to by
 \fIfile_name\fR, an absolute pathname that names the same file, whose
@@ -28,15 +30,18 @@
 generated pathname is stored as a null-terminated string, up to a maximum of
 {\fBPATH_MAX\fR} bytes (defined in \fBlimits.h\fR(3HEAD)), in the buffer
 pointed to by \fIresolved_name\fR.
+.sp
+.LP
+The \fBcanonicalize_file_name()\fR function is equivalent to calling
+\fBrealpath\fR(\fIpath\fR, \fINULL\fR). This function is only provided for
+compatibility.
 .SH RETURN VALUES
-.sp
 .LP
 On successful completion, \fBrealpath()\fR returns a pointer to the resolved
 name.  Otherwise, \fBrealpath()\fR returns a null pointer and sets \fBerrno\fR
 to indicate the error, and the contents of the buffer pointed to by
 \fIresolved_name\fR are left in an indeterminate state.
 .SH ERRORS
-.sp
 .LP
 The \fBrealpath()\fR function will fail if:
 .sp
@@ -137,7 +142,6 @@
 .RE
 
 .SH USAGE
-.sp
 .LP
 The \fBrealpath()\fR function operates on null-terminated strings.
 .sp
@@ -149,7 +153,6 @@
 The \fBrealpath()\fR function might fail to return to the current directory if
 an error occurs.
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -167,7 +170,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBgetcwd\fR(3C), \fBlimits.h\fR(3HEAD), \fBsysconf\fR(3C),
 \fBattributes\fR(5), \fBstandards\fR(5)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/man/man3c/smt_pause.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -0,0 +1,38 @@
+.\"
+.\" 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 (c) 2014, Joyent, Inc. 
+.\"
+.Dd "Dec 22, 2014"
+.Dt SMT_PAUSE 3C
+.Os
+.Sh NAME
+.Nm smt_pause
+.Nd hardware-aware busy wait
+.Sh SYNOPSIS
+.In synch.h
+.Ft void
+.Fo smt_pause
+.Fa void
+.Fc
+.Sh DESCRIPTION
+The
+.Fn smt_pause
+function performs a busy-wait for an implementation defined period of
+time. On hardware platforms that support it, it notifies the hardware
+that this is occurring in an effort to minimize resource usage. This is
+commonly used in the implementation of spin loops.
+.Sh INTERFACE STABILITY
+.Sy Committed
+.Sh MT-LEVEL
+.Sy MT-Safe
+.Sh SEE ALSO
+.Xr attributes 5
--- a/usr/src/man/man3c/string.3c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/string.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -1,5 +1,6 @@
 '\" te
 .\" Copyright 2014 Garrett D'Amore <garrett@damore.org>
+.\" Copyright (c) 2014, Joyent, Inc.
 .\" Copyright (c) 2008, Sun Microsystems, Inc.  All Rights Reserved.
 .\" Copyright 1989 AT&T
 .\" Portions Copyright (c) 1994 Man-cgi 1.15, Panagiotis Christias (christia@softlab.ntua.gr)
@@ -12,12 +13,13 @@
 .\" 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]
-.TH STRING 3C "Jun 21, 2013"
+.TH STRING 3C "Dec 20, 2014"
 .SH NAME
 string, strcasecmp, strcasecmp_l, strncasecmp, strncasecmp_l, strcat, strncat,
-strlcat, strchr, strrchr,
-strcmp, strncmp, strcpy, strncpy, strlcpy, strcspn, strspn, strdup, strlen,
-strnlen, strpbrk, strsep, strstr, strtok, strtok_r \- string operations
+strlcat, strchr, strchrnul, strrchr, strcmp, strncmp, stpcpy, stpncpy, strcpy,
+strncpy, strlcpy, strcspn, strspn, strdup, strndup, strdupa, strndupa, strlen,
+strnlen, strpbrk, strsep, strstr, strnstr, strcasestr, strtok, strtok_r \-
+string operations
 .SH SYNOPSIS
 .LP
 .nf
@@ -69,6 +71,14 @@
 .fi
 .LP
 .nf
+\fBchar *\fR\fBstpcpy\fR(\fBchar *restrict\fR \fIs1\fR, \fBconst char *restrict\fR \fIs2\fR);
+.fi
+.LP
+.nf
+\fBchar *\fR\fBstpncpy\fR(\fBchar *restrict\fR \fIs1\fR, \fBconst char *restrict\fR \fIs2\fR, \fBsize_t\fR \fIn\fR);
+.fi
+.LP
+.nf
 \fBchar *\fR\fBstrcpy\fR(\fBchar *restrict\fR \fIs1\fR, \fBconst char *restrict\fR \fIs2\fR);
 .fi
 .LP
@@ -93,6 +103,18 @@
 .fi
 .LP
 .nf
+\fBchar *\fR\fBstrndup\fR(\fBconst char *\fR\fIs1\fR, \fBsize_t\fR \fIn\fR);
+.fi
+.LP
+.nf
+\fBchar *\fR\fBstrdupa\fR(\fBconst char *\fR\fIs1\fR);
+.fi
+.LP
+.nf
+\fBchar *\fR\fBstrndupa\fR(\fBconst char *\fR\fIs1\fR, \fBsize_t\fR \fIn\fR);
+.fi
+.LP
+.nf
 \fBsize_t\fR \fBstrlen\fR(\fBconst char *\fR\fIs\fR);
 .fi
 .LP
@@ -113,6 +135,18 @@
 .fi
 .LP
 .nf
+\fBchar *\fR\fBstrnstr\fR(\fBconst char *\fR\fIs1\fR, \fBconst char *\fR\fIs2\fR, \fBsize_t\fR \fIn\fR);
+.fi
+.LP
+.nf
+\fBchar *\fR\fBstrcasestr\fR(\fBconst char *\fR\fIs1\fR, \fBconst char *\fR\fIs2\fR);
+.fi
+.LP
+.nf
+\fBchar *\fR\fBstrcasestr_l\fR(\fBconst char *\fR\fIs1\fR, \fBconst char *\fR\fIs2\fR, \fBlocale_t\fR \fIloc\fR);
+.fi
+.LP
+.nf
 \fBchar *\fR\fBstrtok\fR(\fBchar *restrict\fR \fIs1\fR, \fBconst char *restrict\fR \fIs2\fR);
 .fi
 .LP
@@ -129,6 +163,10 @@
 .fi
 .LP
 .nf
+\fBconst char *\fR\fBstrchrnul\fR(\fBconst char *\fR\fIs\fR, \fBint\fR \fIc\fR);
+.fi
+.LP
+.nf
 \fBconst char *\fR\fBstrpbrk\fR(\fBconst char *\fR\fIs1\fR, \fBconst char *\fR\fIs2\fR);
 .fi
 .LP
@@ -160,13 +198,13 @@
 .SH DESCRIPTION
 .LP
 The arguments \fIs\fR, \fIs1\fR, and \fIs2\fR point to strings (arrays of
-characters terminated by a null character). The \fBstrcat()\fR,
-\fBstrncat()\fR, \fBstrlcat()\fR, \fBstrcpy()\fR, \fBstrncpy()\fR,
-\fBstrlcpy()\fR, \fBstrsep()\fR, \fBstrtok()\fR, and \fBstrtok_r()\fR functions
-all alter their first argument. Additionally, the \fBstrcat()\fR and
-\fBstrcpy()\fR functions do not check for overflow of the array.
+characters terminated by a null character). The \fBstrcat()\fR, \fBstrncat()\fR,
+\fBstrlcat()\fR, \fBstrcpy()\fR, \fBstpcpy()\fR, \fBstpncpy()\fR,
+\fBstrncpy()\fR, \fBstrlcpy()\fR, \fBstrsep()\fR, \fBstrtok()\fR, and
+\fBstrtok_r()\fR functions all alter their first argument. Additionally, the
+\fBstrcat()\fR, \fBstpcpy()\fR, and \fBstrcpy()\fR functions do not check for
+overflow of the array.
 .SS "\fBstrcasecmp()\fR, \fBstrncasecmp()\fR"
-.sp
 .LP
 The \fBstrcasecmp()\fR and \fBstrncasecmp()\fR functions are case-insensitive
 versions of  \fBstrcmp()\fR and \fBstrncmp()\fR respectively, described below.
@@ -220,13 +258,16 @@
         return \(mi1;
 .fi
 .in -2
-.SS "\fBstrchr()\fR, \fBstrrchr()\fR"
+.SS "\fBstrchr()\fR, \fBstrrchr()\fR, \fBstrchrnul()\fR"
 .LP
 The \fBstrchr()\fR function returns a pointer to the first occurrence of
 \fIc\fR (converted to a  \fBchar\fR) in string \fIs\fR, or a null pointer if
 \fIc\fR does not occur in the string. The \fBstrrchr()\fR function returns a
 pointer to the last occurrence of \fIc\fR. The null character terminating a
-string is considered to be part of the string.
+string is considered to be part of the string. The \fBstrchrnul()\fR function
+behaves similarly to \fBstrchr()\fR, except when the character \fBc\fR is not
+found, it returns a pointer to the null terminator of the string \fBs\fR and not
+a null pointer.
 .SS "\fBstrcmp()\fR, \fBstrncmp()\fR"
 .LP
 The \fBstrcmp()\fR function compares two strings byte-by-byte, according to the
@@ -260,23 +301,35 @@
         return \(mi1;
 .fi
 .in -2
-
+.SS "\fBstpcpy()\fR, \fBstpncpy()\fR"
+.LP
+The \fBstpcpy()\fR and \fBstpncpy()\fR functions behave identically to
+\fBstrcpy()\fR and \fBstrncpy()\fR respectively; however, instead of returning a
+pointer to the beginning of \fIs1\fR, they return a pointer to the terminating
+null character.
 .SS "\fBstrcspn()\fR, \fBstrspn()\fR"
 .LP
 The \fBstrcspn()\fR function returns the length of the initial segment of
 string \fIs1\fR that consists entirely of characters not from string \fIs2\fR.
 The \fBstrspn()\fR function returns the length of the initial segment of string
 \fIs1\fR that consists entirely of characters from string \fIs2\fR.
-.SS "\fBstrdup()\fR"
+.SS "\fBstrdup()\fR, \fBstrndup()\fR, \fBstrdupa()\fR, \fBstrndupa()\fR"
 .LP
 The \fBstrdup()\fR function returns a pointer to a new string that is a
 duplicate of the string pointed to by  \fIs1\fR. The returned pointer can be
 passed to \fBfree()\fR. The space for the new string is obtained using
 \fBmalloc\fR(3C). If the new string cannot be created, a null pointer is
 returned and \fBerrno\fR may be set to \fBENOMEM\fR to indicate that the
-storage space available is insufficient.
+storage space available is insufficient. The \fBstrndup()\fR function is
+identical to \fBstrdup()\fR, execept it copies at most \fIn\fR bytes from
+\fBs1\fR and ensures the copied string is awlays null terminated.
+.LP
+The functions \fBstrdupa()\fR and \fBstrndupa()\fR behave identically to
+\fBstrdup()\fr and \fBstrndup()\fR respectively; however, instead of allocating
+memory using \fBmalloc\fR(3C), they use \fBalloca\fR(3C). These functions are
+provided for compatibility only, their use is strongly discouraged due to their
+use of \fBalloca\fR(3C).
 .SS "\fBstrlen()\fR, \fBstrnlen()\fR"
-.sp
 The \fBstrlen()\fR function returns the number of bytes in \fIs\fR, not
 including the terminating null character.
 .LP
@@ -303,13 +356,22 @@
 \fBstrsep()\fR to `\e0'.
 .LP
 If *\fIstringp\fR is initially \fINULL\fR, \fBstrsep()\fR returns \fINULL\fR.
-.SS "\fBstrstr()\fR"
+.SS "\fBstrstr()\fR, \fBstrnstr()\fR, \fBstrcasestr()\fR, \fBstrcasestr_l()\fR"
 .LP
 The \fBstrstr()\fR function locates the first occurrence of the string \fIs2\fR
 (excluding the terminating null character) in string \fIs1\fR and returns a
 pointer to the located string, or a null pointer if the string is not found. If
 \fIs2\fR points to a string with zero length (that is, the string \fB""\fR),
-the function returns  \fIs1\fR.
+the function returns  \fIs1\fR. The \fBstrnstr()\fR function performs the same
+search as \fBstrstr()\fR, but only considers up to \fIn\fR bytes of \fIs1\fR.
+Bytes following a null byte are not compared.
+.sp
+.LP
+The \fBstrcasestr()\fR and \fBstrcasestr_l()\fR functions are similar to
+\fBstrstr()\fR, but both functions ignore the case of both \fBs1\fR and
+\fBs2\fR. Where as the \fBstrcasestr()\fR function operates in the current
+locale, the \fBstrcasestr_l()\fR function operates in the locale specified by
+\fIloc\fR.
 .SS "\fBstrtok()\fR"
 .LP
 A sequence of calls to \fBstrtok()\fR breaks the string pointed to by \fIs1\fR
@@ -487,8 +549,8 @@
 \fBstrlcat()\fR, \fBstrlcpy()\fR, and \fBstrsep()\fR functions are Committed.
 All the rest are Standard.
 .LP
-The \fBstrtok()\fR and \fBstrdup()\fR functions are MT-Safe. The remaining
-functions are Async-Signal-Safe.
+The \fBstrtok()\fR, \fBstrdup()\fR, and \fBstrndup()\fR functions are MT-Safe.
+The remaining functions are Async-Signal-Safe.
 .LP
 For all except \fBstrlcat()\fR, \fBstrlcpy()\fR, and \fBstrsep()\fR, see
 \fBstandards\fR(5).
--- a/usr/src/man/man3c/unsetenv.3c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3c/unsetenv.3c	Sun Jan 04 07:19:22 2015 -0800
@@ -8,7 +8,7 @@
 .\" 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]
-.TH UNSETENV 3C "Nov 1, 2003"
+.TH UNSETENV 3C "Dec 20, 2014"
 .SH NAME
 unsetenv \- remove an environment variable
 .SH SYNOPSIS
@@ -20,7 +20,6 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBunsetenv()\fR function removes an environment variable from the
 environment of the calling process. The \fIname\fR argument points to a string
@@ -34,12 +33,10 @@
 the behavior of \fBunsetenv()\fR is undefined. The \fBunsetenv()\fR function
 updates the list of pointers to which \fIenviron\fR points.
 .SH RETURN VALUES
-.sp
 .LP
 Upon successful completion, 0 is returned. Otherwise, -1 is returned,
 \fBerrno\fR set to indicate the error, and the environment is left unchanged.
 .SH ERRORS
-.sp
 .LP
 The \fBunsetenv()\fR function will fail if:
 .sp
@@ -53,7 +50,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -71,6 +67,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
-\fBgetenv\fR(3C), \fBsetenv\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5)
+\fBclearenv\fR(3C), \fBgetenv\fR(3C), \fBsetenv\fR(3C), \fBattributes\fR(5),
+\fBstandards\fR(5)
--- a/usr/src/man/man3lib/libc.3lib	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man3lib/libc.3lib	Sun Jan 04 07:19:22 2015 -0800
@@ -156,13 +156,15 @@
 \fBbsearch\fR
 \fBbtowc\fR	\fBbtowc_l\fR
 \fBbzero\fR	\fBcalloc\fR
+\fBcanonicalize_file_name\fR
 \fBcatclose\fR	\fBcatgets\fR
 \fBcatopen\fR	\fBcfgetispeed\fR
 \fBcfgetospeed\fR	\fBcfsetispeed\fR
 \fBcfsetospeed\fR	\fBcftime\fR
 \fBchdir\fR	\fBchmod\fR
 \fBchown\fR	\fBchroot\fR
-\fBclearerr\fR	\fBclock\fR
+\fBclearerr\fR	\fBclearenv\fR
+\fBclock\fR
 \fBclock_getres\fR	\fBclock_gettime\fR
 \fBclock_nanosleep\fR	\fBclock_settime\fR
 \fBclose\fR	\fBclosedir\fR
@@ -223,14 +225,16 @@
 \fBfchmod\fR	\fBfchmodat\fR
 \fBfchown\fR	\fBfchownat\fR
 \fBfchroot\fR	\fBfclose\fR
-\fBfcntl\fR	\fBfconvert\fR
-\fBfcvt\fR	\fBfdatasync\fR
-\fBfdetach\fR	
+\fBfcloseall\fR	\fBfcntl\fR
+\fBfconvert\fR	\fBfcvt\fR
+\fBfdatasync\fR	\fBfdetach\fR	
 \fBfdopen\fR	\fBfdopendir\fR
 \fBfdwalk\fR	\fBfeof\fR
 \fBferror\fR	\fBfflush\fR
-\fBffs\fR	\fBfgetattr\fR
-\fBfgetc\fR	
+\fBffs\fR	\fBffsl\fR
+\fBffsll\fR	\fBfls\fR
+\fBflsl\fR	\fBflsll\fR
+\fBfgetattr\fR	\fBfgetc\fR	
 \fBfgetgrent\fR	\fBfgetgrent_r\fR
 \fBfgetpos\fR	\fBfgetpwent\fR
 \fBfgetpwent_r\fR	\fBfgets\fR
@@ -287,6 +291,7 @@
 \fBgetloadavg\fR	\fBgetlogin\fR
 \fBgetlogin_r\fR	\fBgetmntany\fR
 \fBgetmntent\fR	\fBgetmsg\fR
+\fBget_nprocs\fR	\fBget_nprocs_conf\fR
 \fBgetnetgrent\fR	\fBgetnetgrent_r\fR
 \fBgetopt\fR	\fBgetopt_clip\fR
 \fBgetopt_long\fR	\fBgetopt_long_only\fR
@@ -296,7 +301,8 @@
 \fBgetpgid\fR	\fBgetpgrp\fR
 \fBgetpid\fR	\fBgetpmsg\fR
 \fBgetppid\fR	\fBgetppriv\fR
-\fBgetpriority\fR	\fBgetprojid\fR
+\fBgetpriority\fR	\fbgetprogname\fR
+\fBgetprojid\fR
 \fBgetpw\fR	\fBgetpwent\fR
 \fBgetpwent_r\fR	\fBgetpwnam\fR
 \fBgetpwnam_r\fR	\fBgetpwuid\fR
@@ -381,8 +387,7 @@
 \fBldivide\fR	\fBlexp10\fR
 \fBlfind\fR	\fBlfmt\fR
 \fBlink\fR	\fBlinkat\fR
-\fBlio_listio\fR
-\fBllabs\fR	
+\fBlio_listio\fR	\fBllabs\fR	
 \fBlldiv\fR	\fBllog10\fR
 \fBllseek\fR	\fBlltostr\fR
 \fBlocaleconv\fR	\fBlocaltime\fR
@@ -408,7 +413,8 @@
 \fBmembar_producer\fR	\fBmemccpy\fR
 \fBmemchr\fR	\fBmemcmp\fR
 \fBmemcntl\fR	\fBmemcpy\fR
-\fBmeminfo\fR	\fBmemmove\fR
+\fBmeminfo\fR	\fBmemmem\fR
+\fBmemmove\fR
 \fBmemset\fR	\fBmincore\fR
 \fBmkdir\fR	\fBmkdirat\fR
 \fBmkfifo\fR	\fBmkfifoat\fR
@@ -577,8 +583,8 @@
 \fBrctlblk_set_value\fR	\fBrctlblk_size\fR
 \fBre_comp\fR	\fBre_exec\fR
 \fBread\fR	\fBreaddir\fR
-\fBreaddir_r\fR
-\fBreadlink\fR	\fBreadlinkat\fR
+\fBreaddir_r\fR	\fBreadlink\fR
+\fBreadlinkat\fR
 \fBreadv\fR	\fBrealloc\fR
 \fBrealpath\fR	\fBreboot\fR
 \fBregcmp\fR	\fBregcomp\fR
@@ -628,7 +634,8 @@
 \fBsetlogmask\fR	\fBsetnetgrent\fR
 \fBsetpflags\fR	\fBsetpgid\fR
 \fBsetpgrp\fR	\fBsetppriv\fR
-\fBsetpriority\fR	\fBsetpwent\fR
+\fBsetpriority\fR	\fBsetprogname\fR
+\fBsetpwent\fR
 \fBsetrctl\fR	\fBsetregid\fR
 \fBsetreuid\fR	\fBsetrlimit\fR
 \fBsetsid\fR	\fBsetspent\fR
@@ -656,7 +663,8 @@
 \fBsigstack\fR	\fBsigsuspend\fR
 \fBsigtimedwait\fR	\fBsigwait\fR
 \fBsigwaitinfo\fR	\fBsingle_to_decimal\fR
-\fBsleep\fR	\fBsnprintf\fR
+\fBsleep\fR	\fBsmt_pause\fR
+\fBsnprintf\fR
 \fBsprintf\fR	\fBsrand\fR
 \fBsrand48\fR	\fBsrandom\fR
 \fBsscanf\fR	\fBssignal\fR
@@ -675,10 +683,10 @@
 \fBstrftime\fR	\fBstrftime_l\fR
 \fBstring_to_decimal\fR
 \fBstrlcat\fR	\fBstrlcpy\fR
-\fBstrlen\fR
-\fBstrncasecmp\fR	\fBstrncasecmp_l\fR
-\fBstrncat\fR	\fBstrncmp\fR
-\fBstrncpy\fR	\fBstrpbrk\fR
+\fBstrlen\fR	\fBstrncasecmp\fR
+\fBstrncasecmp_l\fR	\fBstrncat\fR
+\fBstrncmp\fR	\fBstrncpy\fR
+\fBstrnstr\fR	\fBstrpbrk\fR
 \fBstrptime\fR	\fBstrptime_l\fR
 \fBstrrchr\fR	\fBstrsep\fR	
 \fBstrsignal\fR	\fBstrspn\fR
@@ -691,8 +699,7 @@
 \fBstrtows\fR	\fBstrxfrm\fR
 \fBswab\fR	\fBswapcontext\fR
 \fBswapctl\fR	\fBswprintf\fR
-\fBswscanf\fR
-\fBsymlink\fR
+\fBswscanf\fR	\fBsymlink\fR
 \fBsymlinkat\fR
 \fBsync\fR	\fBsync_instruction_memory\fR
 \fBsysconf\fR	\fBsysfs\fR
@@ -1014,13 +1021,13 @@
 \fBgetpwent()\fR with completely different semantics. Standard-conforming
 applications may not define and use function names with leading underscores.
 .LP
-Solaris system libraries are now built with direct binding. This means that a
+illumos system libraries are now built with direct binding. This means that a
 system library that calls \fBgetpwent()\fR will bind directly to the instance
 of \fBgetpwent()\fR in \fBlibc\fR, even if the application to which it is
 linked defines a different \fBgetpwent()\fR for its own use. The application
 binds to its instance of \fBgetpwent()\fR and there is no resulting conflict.
 The direct binding mechanism is equally available to libraries not delivered
-with Solaris.
+with illumos.
 .LP
 As a result of this evolution, most of the leading-underscore synonym symbols
 have been removed from \fBlibc\fR.  This means that applications that call
--- a/usr/src/man/man5/ipfilter.5	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man5/ipfilter.5	Sun Jan 04 07:19:22 2015 -0800
@@ -2,11 +2,11 @@
 .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed
 .\" location.
 .\" Portions Copyright (c) 2009, Sun Microsystems Inc. All Rights Reserved.
-.TH IPFILTER 5 "May 20, 2009"
+.\" Portions Copyright (c) 2014, Joyent, Inc. All Rights Reserved.
+.TH IPFILTER 5 "Oct 7, 2014"
 .SH NAME
 ipfilter \- IP packet filtering software
 .SH DESCRIPTION
-.sp
 .LP
 IP Filter is software that provides packet filtering capabilities on a Solaris
 system. On a properly setup system, it can be used to build a firewall.
@@ -16,7 +16,6 @@
 packet filtering is not enabled by default. See \fBipf\fR(1M) for a procedure
 to enable and activate the IP Filter feature.
 .SH HOST-BASED FIREWALL
-.sp
 .LP
 To simplify IP Filter configuration management, a firewall framework is created
 to allow users to configure IP Filter by expressing firewall policy at system
@@ -34,14 +33,13 @@
 advantage of the framework. See \fBipf\fR(1M) and \fBipf\fR(4).
 .RE
 .SS "Model"
-.sp
 .LP
 This section describes the host-based firewall framework. See svc.ipfd(1M) for
 details on how to configure firewall policies.
 .sp
 .LP
-A three-layer approach with different precedence levels helps the user achieve
-the desired behaviors.
+In a given zone, a three-layer approach with different precedence levels helps
+the user achieve the desired behaviors.
 .sp
 .ne 2
 .na
@@ -127,7 +125,6 @@
 .RE
 
 .SS "Layers in Detail"
-.sp
 .LP
 The first system-wide layer, Global Default, defines a firewall policy that
 applies to \fBany\fR incoming traffic, for example, allowing or blocking all
@@ -157,7 +154,6 @@
 network services. The example is when it is desirable to block known malicious
 source(s) regardless of services' policies.
 .SS "User Interaction"
-.sp
 .LP
 This framework leverages IP Filter functionality and is active only when
 \fBsvc:/network/ipfilter\fR is enabled and inactive when \fBnetwork/ipfilter\fR
@@ -207,9 +203,94 @@
 .el o
 changes to system-wide or per-service firewall policy results in an update to
 the system's firewall rules
-.RE
+
+.SS "In-Zone and Global Zone Controlled firewalls"
+.LP
+Each non-global zone in the system can potentially have two firewalls
+configured: the in-zone firewall and the Global Zone controlled (GZ-controlled)
+firewall. The in-zone firewall can be controlled and observed inside the zone
+using the framework detailed above, or from the Global Zone. The GZ-controlled
+firewall can only be controlled and observed from the Global Zone. The
+GZ-controlled firewall is always "outermost" with respect to the zone.
+.sp
+.LP
+For inbound traffic (from an external source to the zone), the traffic flow looks
+like the following diagram. Traffic blocked by the GZ-controlled firewall will
+not be processed by the in-zone firewall.
+.sp
+.in +2
+.nf
+  External Source
+        |
+        |
+GZ-controlled Firewall
+        |
+        |
+  In-Zone Firewall
+        |
+        |
+      Zone
+.fi
+.in -2
+.sp
+.LP
+For outbound traffic (from the zone to an external destination), the traffic
+flow looks like the following diagram. Traffic blocked by the in-zone firewall
+will not be processed by the GZ-controlled firewall.
+.sp
+.in +2
+.nf
+      Zone
+        |
+        |
+  In-Zone Firewall
+        |
+        |
+GZ-controlled Firewall
+        |
+        |
+ External Destination
+.fi
+.in -2
+.sp
+.LP
+Either of the in-Zone or GZ-controlled firewalls can be enabled, or both at the
+same time.
+.sp
+.LP
+The Global Zone does not have a GZ-controlled firewall, only an
+in-zone firewall.  For inbound traffic (from an external source to the global
+zone), the traffic flow therefore looks like the following diagram.
+.sp
+.in +2
+.nf
+  External Source
+        |
+        |
+  In-Zone Firewall
+        |
+        |
+      Zone
+.fi
+.in -2
+.sp
+.LP
+For outbound traffic (from the global zone to an external destination), the
+traffic flow looks like the following diagram.
+.sp
+.in +2
+.nf
+      Zone
+        |
+        |
+  In-Zone Firewall
+        |
+        |
+ External Destination
+.fi
+.in -2
+
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for a description of the following attributes:
 .sp
@@ -225,7 +306,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBsvcs\fR(1), \fBipf\fR(1M), \fBipnat\fR(1M), \fBsvcadm\fR(1M),
 \fBsvc.ipfd\fR(1M), \fBipf\fR(4), \fBipnat\fR(4), \fBattributes\fR(5),
@@ -234,7 +314,6 @@
 .LP
 \fISystem Administration Guide: IP Services\fR
 .SH NOTES
-.sp
 .LP
 The \fBipfilter\fR service is managed by the service management facility,
 \fBsmf\fR(5), under the service identifier:
--- a/usr/src/man/man9f/Intro.9f	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man9f/Intro.9f	Sun Jan 04 07:19:22 2015 -0800
@@ -61,25 +61,29 @@
 the kernel. In a block device driver, the
 .Xr strategy 9E
 entry point may be
-called by the page daemon to write pages to the device. The page daemon has no
+called by the page daemon to write pages to the device.
+The page daemon has no
 relation to the current user thread, so in this case
 .Xr strategy 9E
 has kernel context.
 .Lp
 .Em Interrupt context
 is kernel context, but also has an interrupt level
-associated with it. Driver interrupt routines have interrupt context.
+associated with it.
+Driver interrupt routines have interrupt context.
 .Lp
 Note that a mutex acquired in user or kernel context that can also be acquired
 in interrupt context means that the user or kernel context thread holding that
 mutex is subject to all the restrictions imposed by interrupt context, for the
-duration of the ownership of that mutex. Please see the
+duration of the ownership of that mutex.
+Please see the
 .Xr mutex 9F
 man page for a more complete discussion of proper mutex handling for drivers.
 .Lp
 .Em High-level interrupt context
 is a more restricted form of interrupt
-context. If a driver interrupt priority returned from
+context.
+If a driver interrupt priority returned from
 .Xr ddi_intr_get_pri 9F
 is greater than the priority returned from
 .Xr ddi_intr_get_hilevel_pri 9F
@@ -117,7 +121,7 @@
 .It Sy Routine	Sy Type
 .It Sy adjmsg	DDI/DKI
 .It Sy allocb	DDI/DKI
-.It Sy allocb_tmpl	Solaris DDI
+.It Sy allocb_tmpl	illumos DDI
 .It Sy backq	DDI/DKI
 .It Sy bcanput	DDI/DKI
 .It Sy bcanputnext	DDI/DKI
@@ -127,10 +131,10 @@
 .It Sy clrbuf	DDI/DKI
 .It Sy copyb	DDI/DKI
 .It Sy copymsg	DDI/DKI
-.It Sy DB_BASE	Solaris DDI
-.It Sy DB_LIM	Solaris DDI
-.It Sy DB_REF	Solaris DDI
-.It Sy DB_TYPE	Solaris DDI
+.It Sy DB_BASE	illumos DDI
+.It Sy DB_LIM	illumos DDI
+.It Sy DB_REF	illumos DDI
+.It Sy DB_TYPE	illumos DDI
 .It Sy datamsg	DDI/DKI
 .It Sy dupb	DDI/DKI
 .It Sy dupmsg	DDI/DKI
@@ -143,28 +147,28 @@
 .It Sy freemsg	DDI/DKI
 .It Sy freezestr	DDI/DKI
 .It Sy getq	DDI/DKI
-.It Sy IOC_CONVERT_FROM	Solaris DDI
+.It Sy IOC_CONVERT_FROM	illumos DDI
 .It Sy insq	DDI/DKI
 .It Sy linkb	DDI/DKI
-.It Sy MBLKHEAD	Solaris DDI
-.It Sy MBLKIN	Solaris DDI
-.It Sy MBLKL	Solaris DDI
-.It Sy MBLKSIZE	Solaris DDI
-.It Sy MBLKTAIL	Solaris DDI
-.It Sy mcopyin	Solaris DDI
-.It Sy mcopymsg	Solaris DDI
-.It Sy mcopyout	Solaris DDI
-.It Sy merror	Solaris DDI
-.It Sy mexchange	Solaris DDI
-.It Sy mioc2ack	Solaris DDI
-.It Sy miocack	Solaris DDI
-.It Sy mexchange	Solaris DDI
-.It Sy miocpullup	Solaris DDI
-.It Sy mkiocb	Solaris DDI
+.It Sy MBLKHEAD	illumos DDI
+.It Sy MBLKIN	illumos DDI
+.It Sy MBLKL	illumos DDI
+.It Sy MBLKSIZE	illumos DDI
+.It Sy MBLKTAIL	illumos DDI
+.It Sy mcopyin	illumos DDI
+.It Sy mcopymsg	illumos DDI
+.It Sy mcopyout	illumos DDI
+.It Sy merror	illumos DDI
+.It Sy mexchange	illumos DDI
+.It Sy mioc2ack	illumos DDI
+.It Sy miocack	illumos DDI
+.It Sy mexchange	illumos DDI
+.It Sy miocpullup	illumos DDI
+.It Sy mkiocb	illumos DDI
 .It Sy msgdsize	DDI/DKI
 .It Sy msgpullup	DDI/DKI
-.It Sy msgsize	Solaris DDI
-.It Sy mt-streams	Solaris DDI
+.It Sy msgsize	illumos DDI
+.It Sy mt-streams	illumos DDI
 .It Sy noenable	DDI/DKI
 .It Sy OTHERQ	DDI/DKI
 .It Sy pullupmsg	DDI/DKI
@@ -175,19 +179,19 @@
 .It Sy putnext	DDI/DKI
 .It Sy putnextctl	DDI/DKI
 .It Sy putq	DDI/DKI
-.It Sy qassociate	Solaris DDI
-.It Sy qbufcall	Solaris DDI
+.It Sy qassociate	illumos DDI
+.It Sy qbufcall	illumos DDI
 .It Sy qenable	DDI/DKI
 .It Sy qprocson	DDI/DKI
 .It Sy qprocsoff	DDI/DKI
 .It Sy qreply	DDI/DKI
 .It Sy qsize	DDI/DKI
-.It Sy qtimeout	Solaris DDI
-.It Sy qunbufcall	Solaris DDI
-.It Sy quntimeout	Solaris DDI
-.It Sy qwait	Solaris DDI
-.It Sy qwait_sig	Solaris DDI
-.It Sy qwriter	Solaris DDI
+.It Sy qtimeout	illumos DDI
+.It Sy qunbufcall	illumos DDI
+.It Sy quntimeout	illumos DDI
+.It Sy qwait	illumos DDI
+.It Sy qwait_sig	illumos DDI
+.It Sy qwriter	illumos DDI
 .It Sy RD	DDI/DKI
 .It Sy rmvb	DDI/DKI
 .It Sy rmvq	DDI/DKI
@@ -206,8 +210,8 @@
 .Bl -column usb_pipe_get_max_bulk_transfer_size
 .It Sy Routine	Sy Type
 .It Sy ASSERT	DDI/DKI
-.It Sy anocancel	Solaris DDI
-.It Sy aphysio	Solaris DDI
+.It Sy anocancel	illumos DDI
+.It Sy aphysio	illumos DDI
 .It Sy atomic_add	DDI/DKI
 .It Sy atomic_and	DDI/DKI
 .It Sy atomic_bits	DDI/DKI
@@ -219,14 +223,14 @@
 .It Sy atomic_swap	DDI/DKI
 .It Sy bcmp	DDI/DKI
 .It Sy bcopy	DDI/DKI
-.It Sy bioclone	Solaris DDI
+.It Sy bioclone	illumos DDI
 .It Sy biodone	DDI/DKI
-.It Sy biofini	Solaris DDI
-.It Sy bioinit	Solaris DDI
-.It Sy biomodified	Solaris DDI
-.It Sy biosize	Solaris DDI
-.It Sy bioerror	Solaris DDI
-.It Sy bioreset	Solaris DDI
+.It Sy biofini	illumos DDI
+.It Sy bioinit	illumos DDI
+.It Sy biomodified	illumos DDI
+.It Sy biosize	illumos DDI
+.It Sy bioerror	illumos DDI
+.It Sy bioreset	illumos DDI
 .It Sy biowait	DDI/DKI
 .It Sy bp_copyin	DDI/DKI
 .It Sy bp_copyout	DDI/DKI
@@ -236,543 +240,545 @@
 .It Sy btopr	DDI/DKI
 .It Sy bzero	DDI/DKI
 .It Sy cmn_err	DDI/DKI
-.It Sy condvar	Solaris DDI
+.It Sy condvar	illumos DDI
 .It Sy copyin	DDI/DKI
 .It Sy copyout	DDI/DKI
-.It Sy cv_broadcast	Solaris DDI
-.It Sy cv_destroy	Solaris DDI
-.It Sy cv_init	Solaris DDI
-.It Sy cv_signal	Solaris DDI
-.It Sy cv_timedwait	Solaris DDI
-.It Sy cv_wait	Solaris DDI
-.It Sy cv_wait_sig	Solaris DDI
-.It Sy ddi_add_event_handler	Solaris DDI
-.It Sy ddi_add_intr	Solaris DDI
-.It Sy ddi_add_softintr	Solaris DDI
-.It Sy ddi_binding_name	Solaris DDI
-.It Sy ddi_btop	Solaris DDI
-.It Sy ddi_btopr	Solaris DDI
-.It Sy ddi_can_receive_sig	Solaris DDI
-.It Sy ddi_check_acc_handle	Solaris DDI
-.It Sy ddi_copyin	Solaris DDI
-.It Sy ddi_copyout	Solaris DDI
-.It Sy ddi_create_minor_node	Solaris DDI
-.It Sy ddi_cred	Solaris DDI
-.It Sy ddi_dev_is_sid	Solaris DDI
-.It Sy ddi_dev_nintrs	Solaris DDI
-.It Sy ddi_dev_nregs	Solaris DDI
-.It Sy ddi_dev_regsize	Solaris DDI
-.It Sy ddi_device_copy	Solaris DDI
-.It Sy ddi_device_zero	Solaris DDI
-.It Sy ddi_devmap_segmap	Solaris DDI
-.It Sy ddi_dma_addr_bind_handle	Solaris DDI
-.It Sy ddi_dma_alloc_handle	Solaris DDI
-.It Sy ddi_dma_buf_bind_handle	Solaris DDI
-.It Sy ddi_dma_burstsizes	Solaris DDI
-.It Sy ddi_dma_free_handle	Solaris DDI
-.It Sy ddi_dma_getwin	Solaris DDI
-.It Sy ddi_dma_mem_alloc	Solaris DDI
-.It Sy ddi_dma_mem_free	Solaris DDI
-.It Sy ddi_dma_nextcookie	Solaris DDI
-.It Sy ddi_dma_numwin	Solaris DDI
-.It Sy ddi_dma_set_sbus64	Solaris DDI
-.It Sy ddi_dma_sync	Solaris DDI
-.It Sy ddi_dma_unbind_handle	Solaris DDI
-.It Sy ddi_dmae	Solaris x86 DDI
-.It Sy ddi_dmae_1stparty	Solaris x86 DDI
-.It Sy ddi_dmae_alloc	Solaris x86 DDI
-.It Sy ddi_dmae_disable	Solaris x86 DDI
-.It Sy ddi_dmae_enable	Solaris x86 DDI
-.It Sy ddi_dmae_getattr	Solaris x86 DDI
-.It Sy ddi_dmae_getcnt	Solaris x86 DDI
-.It Sy ddi_dmae_getlim	Solaris x86 DDI
-.It Sy ddi_dmae_prog	Solaris x86 DDI
-.It Sy ddi_dmae_release	Solaris x86 DDI
-.It Sy ddi_dmae_stop	Solaris x86 DDI
-.It Sy ddi_driver_major	Solaris DDI
-.It Sy ddi_driver_name	Solaris DDI
-.It Sy ddi_enter_critical	Solaris DDI
-.It Sy ddi_exit_critical	Solaris DDI
-.It Sy ddi_ffs	Solaris DDI
-.It Sy ddi_fls	Solaris DDI
-.It Sy ddi_fm_acc_err_clear	Solaris DDI
-.It Sy ddi_fm_acc_err_get	Solaris DDI
-.It Sy ddi_fm_ereport_post	Solaris DDI
-.It Sy ddi_fm_handler_register	Solaris DDI
-.It Sy ddi_fm_init	Solaris DDI
-.It Sy ddi_fm_service_impact	Solaris DDI
-.It Sy ddi_get16	Solaris DDI
-.It Sy ddi_get32	Solaris DDI
-.It Sy ddi_get64	Solaris DDI
-.It Sy ddi_get8	Solaris DDI
-.It Sy ddi_get_cred	Solaris DDI
-.It Sy ddi_get_devstate	Solaris DDI
-.It Sy ddi_get_driver_private	Solaris DDI
-.It Sy ddi_get_eventcookie	Solaris DDI
-.It Sy ddi_get_iblock_cookie	Solaris DDI
-.It Sy ddi_get_iminor	Solaris DDI
-.It Sy ddi_get_instance	Solaris DDI
-.It Sy ddi_get_kt_did	Solaris DDI
-.It Sy ddi_get_lbolt	Solaris DDI
-.It Sy ddi_get_name	Solaris DDI
-.It Sy ddi_get_parent	Solaris DDI
-.It Sy ddi_get_pid	Solaris DDI
-.It Sy ddi_get_soft_iblock_cookie	Solaris DDI
-.It Sy ddi_get_soft_state	Solaris DDI
-.It Sy ddi_getb	Solaris DDI
-.It Sy ddi_getl	Solaris DDI
-.It Sy ddi_getll	Solaris DDI
-.It Sy ddi_getlongprop	Solaris DDI
-.It Sy ddi_getlongprop_buf	Solaris DDI
-.It Sy ddi_getprop	Solaris DDI
-.It Sy ddi_getproplen	Solaris DDI
-.It Sy ddi_getw	Solaris DDI
-.It Sy ddi_intr_add_handler	Solaris DDI
-.It Sy ddi_intr_add_softint	Solaris DDI
-.It Sy ddi_intr_alloc	Solaris DDI
-.It Sy ddi_intr_block_disable	Solaris DDI
-.It Sy ddi_intr_block_enable	Solaris DDI
-.It Sy ddi_intr_clr_mask	Solaris DDI
-.It Sy ddi_intr_dup_handler	Solaris DDI
-.It Sy ddi_intr_disable	Solaris DDI
-.It Sy ddi_intr_enable	Solaris DDI
-.It Sy ddi_intr_free	Solaris DDI
-.It Sy ddi_intr_get_cap	Solaris DDI
-.It Sy ddi_intr_get_hilevel_pri	Solaris DDI
-.It Sy ddi_intr_get_navail	Solaris DDI
-.It Sy ddi_intr_get_nintrs	Solaris DDI
-.It Sy ddi_intr_get_pending	Solaris DDI
-.It Sy ddi_intr_get_pri	Solaris DDI
-.It Sy ddi_intr_get_softint_pri	Solaris DDI
-.It Sy ddi_intr_get_supported_types	Solaris DDI
-.It Sy ddi_intr_remove_handler	Solaris DDI
-.It Sy ddi_intr_remove_softint	Solaris DDI
-.It Sy ddi_intr_set_cap	Solaris DDI
-.It Sy ddi_intr_set_mask	Solaris DDI
-.It Sy ddi_intr_set_pri	Solaris DDI
-.It Sy ddi_intr_set_softint_pri	Solaris DDI
-.It Sy ddi_intr_trigger_softint	Solaris DDI
-.It Sy ddi_io_get16	Solaris DDI
-.It Sy ddi_io_get32	Solaris DDI
-.It Sy ddi_io_get8	Solaris DDI
-.It Sy ddi_io_getb	Solaris DDI
-.It Sy ddi_io_getl	Solaris DDI
-.It Sy ddi_io_getw	Solaris DDI
-.It Sy ddi_io_put16	Solaris DDI
-.It Sy ddi_io_put32	Solaris DDI
-.It Sy ddi_io_put8	Solaris DDI
-.It Sy ddi_io_putb	Solaris DDI
-.It Sy ddi_io_putl	Solaris DDI
-.It Sy ddi_io_putw	Solaris DDI
-.It Sy ddi_io_rep_get16	Solaris DDI
-.It Sy ddi_io_rep_get32	Solaris DDI
-.It Sy ddi_io_rep_get8	Solaris DDI
-.It Sy ddi_io_rep_getb	Solaris DDI
-.It Sy ddi_io_rep_getl	Solaris DDI
-.It Sy ddi_io_rep_getw	Solaris DDI
-.It Sy ddi_io_rep_put16	Solaris DDI
-.It Sy ddi_io_rep_put32	Solaris DDI
-.It Sy ddi_io_rep_put8	Solaris DDI
-.It Sy ddi_io_rep_putb	Solaris DDI
-.It Sy ddi_io_rep_putl	Solaris DDI
-.It Sy ddi_io_rep_putw	Solaris DDI
-.It Sy ddi_iomin	Solaris DDI
-.It Sy ddi_log_sysevent	Solaris DDI
-.It Sy ddi_map_regs	Solaris DDI
-.It Sy ddi_mapdev	Solaris DDI
-.It Sy ddi_mapdev_intercept	Solaris DDI
-.It Sy ddi_mapdev_nointercept	Solaris DDI
-.It Sy ddi_mapdev_set_device_acc_attr	Solaris DDI
-.It Sy ddi_mem_get16	Solaris DDI
-.It Sy ddi_mem_get32	Solaris DDI
-.It Sy ddi_mem_get64	Solaris DDI
-.It Sy ddi_mem_get8	Solaris DDI
-.It Sy ddi_mem_getb	Solaris DDI
-.It Sy ddi_mem_getl	Solaris DDI
-.It Sy ddi_mem_getll	Solaris DDI
-.It Sy ddi_mem_getw	Solaris DDI
-.It Sy ddi_mem_put16	Solaris DDI
-.It Sy ddi_mem_put32	Solaris DDI
-.It Sy ddi_mem_put64	Solaris DDI
-.It Sy ddi_mem_put8	Solaris DDI
-.It Sy ddi_mem_putb	Solaris DDI
-.It Sy ddi_mem_putl	Solaris DDI
-.It Sy ddi_mem_putll	Solaris DDI
-.It Sy ddi_mem_putw	Solaris DDI
-.It Sy ddi_mem_rep_get16	Solaris DDI
-.It Sy ddi_mem_rep_get32	Solaris DDI
-.It Sy ddi_mem_rep_get64	Solaris DDI
-.It Sy ddi_mem_rep_get8	Solaris DDI
-.It Sy ddi_mem_rep_getb	Solaris DDI
-.It Sy ddi_mem_rep_getl	Solaris DDI
-.It Sy ddi_mem_rep_getll	Solaris DDI
-.It Sy ddi_mem_rep_getw	Solaris DDI
-.It Sy ddi_mem_rep_put16	Solaris DDI
-.It Sy ddi_mem_rep_put32	Solaris DDI
-.It Sy ddi_mem_rep_put64	Solaris DDI
-.It Sy ddi_mem_rep_put8	Solaris DDI
-.It Sy ddi_mem_rep_putb	Solaris DDI
-.It Sy ddi_mem_rep_putl	Solaris DDI
-.It Sy ddi_mem_rep_putll	Solaris DDI
-.It Sy ddi_mem_rep_putw	Solaris DDI
-.It Sy ddi_mmap_get_model	Solaris DDI
-.It Sy ddi_model_convert_from	Solaris DDI
-.It Sy ddi_modopen	Solaris DDI
-.It Sy ddi_no_info	Solaris DDI
-.It Sy ddi_node_name	Solaris DDI
-.It Sy ddi_peek16	Solaris DDI
-.It Sy ddi_peek32	Solaris DDI
-.It Sy ddi_peek64	Solaris DDI
-.It Sy ddi_peek8	Solaris DDI
-.It Sy ddi_peekc	Solaris DDI
-.It Sy ddi_peekd	Solaris DDI
-.It Sy ddi_peekl	Solaris DDI
-.It Sy ddi_peeks	Solaris DDI
-.It Sy ddi_periodic_add	Solaris DDI
-.It Sy ddi_periodic_delete	Solaris DDI
-.It Sy ddi_poke16	Solaris DDI
-.It Sy ddi_poke32	Solaris DDI
-.It Sy ddi_poke64	Solaris DDI
-.It Sy ddi_poke8	Solaris DDI
-.It Sy ddi_pokec	Solaris DDI
-.It Sy ddi_poked	Solaris DDI
-.It Sy ddi_pokel	Solaris DDI
-.It Sy ddi_pokes	Solaris DDI
-.It Sy ddi_prop_create	Solaris DDI
-.It Sy ddi_prop_exists	Solaris DDI
-.It Sy ddi_prop_free	Solaris DDI
-.It Sy ddi_prop_get_int	Solaris DDI
-.It Sy ddi_prop_lookup	Solaris DDI
-.It Sy ddi_prop_lookup_byte_array	Solaris DDI
-.It Sy ddi_prop_lookup_int_array	Solaris DDI
-.It Sy ddi_prop_lookup_string	Solaris DDI
-.It Sy ddi_prop_lookup_string_array	Solaris DDI
-.It Sy ddi_prop_modify	Solaris DDI
-.It Sy ddi_prop_op	Solaris DDI
-.It Sy ddi_prop_remove	Solaris DDI
-.It Sy ddi_prop_remove_all	Solaris DDI
-.It Sy ddi_prop_undefine	Solaris DDI
-.It Sy ddi_prop_update	Solaris DDI
-.It Sy ddi_prop_update_byte_array	Solaris DDI
-.It Sy ddi_prop_update_int	Solaris DDI
-.It Sy ddi_prop_update_int_array	Solaris DDI
-.It Sy ddi_prop_update_string	Solaris DDI
-.It Sy ddi_prop_update_string_array	Solaris DDI
-.It Sy ddi_ptob	Solaris DDI
-.It Sy ddi_put16	Solaris DDI
-.It Sy ddi_put32	Solaris DDI
-.It Sy ddi_put64	Solaris DDI
-.It Sy ddi_put8	Solaris DDI
-.It Sy ddi_putb	Solaris DDI
-.It Sy ddi_putl	Solaris DDI
-.It Sy ddi_putll	Solaris DDI
-.It Sy ddi_putw	Solaris DDI
-.It Sy ddi_regs_map_free	Solaris DDI
-.It Sy ddi_regs_map_setup	Solaris DDI
-.It Sy ddi_remove_event_handler	Solaris DDI
-.It Sy ddi_remove_intr	Solaris DDI
-.It Sy ddi_remove_minor_node	Solaris DDI
-.It Sy ddi_remove_softintr	Solaris DDI
-.It Sy ddi_removing_power	Solaris DDI
-.It Sy ddi_rep_get16	Solaris DDI
-.It Sy ddi_rep_get32	Solaris DDI
-.It Sy ddi_rep_get64	Solaris DDI
-.It Sy ddi_rep_get8	Solaris DDI
-.It Sy ddi_rep_getb	Solaris DDI
-.It Sy ddi_rep_getl	Solaris DDI
-.It Sy ddi_rep_getll	Solaris DDI
-.It Sy ddi_rep_getw	Solaris DDI
-.It Sy ddi_rep_put16	Solaris DDI
-.It Sy ddi_rep_put32	Solaris DDI
-.It Sy ddi_rep_put64	Solaris DDI
-.It Sy ddi_rep_put8	Solaris DDI
-.It Sy ddi_rep_putb	Solaris DDI
-.It Sy ddi_rep_putl	Solaris DDI
-.It Sy ddi_rep_putll	Solaris DDI
-.It Sy ddi_rep_putw	Solaris DDI
-.It Sy ddi_report_dev	Solaris DDI
-.It Sy ddi_root_node	Solaris DDI
-.It Sy ddi_segmap	Solaris DDI
-.It Sy ddi_segmap_setup	Solaris DDI
-.It Sy ddi_set_driver_private	Solaris DDI
-.It Sy ddi_slaveonly	Solaris DDI
-.It Sy ddi_soft_state	Solaris DDI
-.It Sy ddi_soft_state_fini	Solaris DDI
-.It Sy ddi_soft_state_free	Solaris DDI
-.It Sy ddi_soft_state_init	Solaris DDI
-.It Sy ddi_soft_state_zalloc	Solaris DDI
-.It Sy ddi_strlol	Solaris DDI
-.It Sy ddi_strloul	Solaris DDI
-.It Sy ddi_trigger_softintr	Solaris DDI
-.It Sy ddi_umem_alloc	Solaris DDI
-.It Sy ddi_umem_free	Solaris DDI
-.It Sy ddi_umem_iosetup	Solaris DDI
-.It Sy ddi_umem_lock	Solaris DDI
-.It Sy ddi_unmap_regs	Solaris DDI
+.It Sy cv_broadcast	illumos DDI
+.It Sy cv_destroy	illumos DDI
+.It Sy cv_init	illumos DDI
+.It Sy cv_signal	illumos DDI
+.It Sy cv_reltimedwait	illumos DDI
+.It Sy cv_reltimedwait_sig	illumos DDI
+.It Sy cv_timedwait	illumos DDI
+.It Sy cv_wait	illumos DDI
+.It Sy cv_wait_sig	illumos DDI
+.It Sy ddi_add_event_handler	illumos DDI
+.It Sy ddi_add_intr	illumos DDI
+.It Sy ddi_add_softintr	illumos DDI
+.It Sy ddi_binding_name	illumos DDI
+.It Sy ddi_btop	illumos DDI
+.It Sy ddi_btopr	illumos DDI
+.It Sy ddi_can_receive_sig	illumos DDI
+.It Sy ddi_check_acc_handle	illumos DDI
+.It Sy ddi_copyin	illumos DDI
+.It Sy ddi_copyout	illumos DDI
+.It Sy ddi_create_minor_node	illumos DDI
+.It Sy ddi_cred	illumos DDI
+.It Sy ddi_dev_is_sid	illumos DDI
+.It Sy ddi_dev_nintrs	illumos DDI
+.It Sy ddi_dev_nregs	illumos DDI
+.It Sy ddi_dev_regsize	illumos DDI
+.It Sy ddi_device_copy	illumos DDI
+.It Sy ddi_device_zero	illumos DDI
+.It Sy ddi_devmap_segmap	illumos DDI
+.It Sy ddi_dma_addr_bind_handle	illumos DDI
+.It Sy ddi_dma_alloc_handle	illumos DDI
+.It Sy ddi_dma_buf_bind_handle	illumos DDI
+.It Sy ddi_dma_burstsizes	illumos DDI
+.It Sy ddi_dma_free_handle	illumos DDI
+.It Sy ddi_dma_getwin	illumos DDI
+.It Sy ddi_dma_mem_alloc	illumos DDI
+.It Sy ddi_dma_mem_free	illumos DDI
+.It Sy ddi_dma_nextcookie	illumos DDI
+.It Sy ddi_dma_numwin	illumos DDI
+.It Sy ddi_dma_set_sbus64	illumos DDI
+.It Sy ddi_dma_sync	illumos DDI
+.It Sy ddi_dma_unbind_handle	illumos DDI
+.It Sy ddi_dmae	illumos x86 DDI
+.It Sy ddi_dmae_1stparty	illumos x86 DDI
+.It Sy ddi_dmae_alloc	illumos x86 DDI
+.It Sy ddi_dmae_disable	illumos x86 DDI
+.It Sy ddi_dmae_enable	illumos x86 DDI
+.It Sy ddi_dmae_getattr	illumos x86 DDI
+.It Sy ddi_dmae_getcnt	illumos x86 DDI
+.It Sy ddi_dmae_getlim	illumos x86 DDI
+.It Sy ddi_dmae_prog	illumos x86 DDI
+.It Sy ddi_dmae_release	illumos x86 DDI
+.It Sy ddi_dmae_stop	illumos x86 DDI
+.It Sy ddi_driver_major	illumos DDI
+.It Sy ddi_driver_name	illumos DDI
+.It Sy ddi_enter_critical	illumos DDI
+.It Sy ddi_exit_critical	illumos DDI
+.It Sy ddi_ffs	illumos DDI
+.It Sy ddi_fls	illumos DDI
+.It Sy ddi_fm_acc_err_clear	illumos DDI
+.It Sy ddi_fm_acc_err_get	illumos DDI
+.It Sy ddi_fm_ereport_post	illumos DDI
+.It Sy ddi_fm_handler_register	illumos DDI
+.It Sy ddi_fm_init	illumos DDI
+.It Sy ddi_fm_service_impact	illumos DDI
+.It Sy ddi_get16	illumos DDI
+.It Sy ddi_get32	illumos DDI
+.It Sy ddi_get64	illumos DDI
+.It Sy ddi_get8	illumos DDI
+.It Sy ddi_get_cred	illumos DDI
+.It Sy ddi_get_devstate	illumos DDI
+.It Sy ddi_get_driver_private	illumos DDI
+.It Sy ddi_get_eventcookie	illumos DDI
+.It Sy ddi_get_iblock_cookie	illumos DDI
+.It Sy ddi_get_iminor	illumos DDI
+.It Sy ddi_get_instance	illumos DDI
+.It Sy ddi_get_kt_did	illumos DDI
+.It Sy ddi_get_lbolt	illumos DDI
+.It Sy ddi_get_name	illumos DDI
+.It Sy ddi_get_parent	illumos DDI
+.It Sy ddi_get_pid	illumos DDI
+.It Sy ddi_get_soft_iblock_cookie	illumos DDI
+.It Sy ddi_get_soft_state	illumos DDI
+.It Sy ddi_getb	illumos DDI
+.It Sy ddi_getl	illumos DDI
+.It Sy ddi_getll	illumos DDI
+.It Sy ddi_getlongprop	illumos DDI
+.It Sy ddi_getlongprop_buf	illumos DDI
+.It Sy ddi_getprop	illumos DDI
+.It Sy ddi_getproplen	illumos DDI
+.It Sy ddi_getw	illumos DDI
+.It Sy ddi_intr_add_handler	illumos DDI
+.It Sy ddi_intr_add_softint	illumos DDI
+.It Sy ddi_intr_alloc	illumos DDI
+.It Sy ddi_intr_block_disable	illumos DDI
+.It Sy ddi_intr_block_enable	illumos DDI
+.It Sy ddi_intr_clr_mask	illumos DDI
+.It Sy ddi_intr_dup_handler	illumos DDI
+.It Sy ddi_intr_disable	illumos DDI
+.It Sy ddi_intr_enable	illumos DDI
+.It Sy ddi_intr_free	illumos DDI
+.It Sy ddi_intr_get_cap	illumos DDI
+.It Sy ddi_intr_get_hilevel_pri	illumos DDI
+.It Sy ddi_intr_get_navail	illumos DDI
+.It Sy ddi_intr_get_nintrs	illumos DDI
+.It Sy ddi_intr_get_pending	illumos DDI
+.It Sy ddi_intr_get_pri	illumos DDI
+.It Sy ddi_intr_get_softint_pri	illumos DDI
+.It Sy ddi_intr_get_supported_types	illumos DDI
+.It Sy ddi_intr_remove_handler	illumos DDI
+.It Sy ddi_intr_remove_softint	illumos DDI
+.It Sy ddi_intr_set_cap	illumos DDI
+.It Sy ddi_intr_set_mask	illumos DDI
+.It Sy ddi_intr_set_pri	illumos DDI
+.It Sy ddi_intr_set_softint_pri	illumos DDI
+.It Sy ddi_intr_trigger_softint	illumos DDI
+.It Sy ddi_io_get16	illumos DDI
+.It Sy ddi_io_get32	illumos DDI
+.It Sy ddi_io_get8	illumos DDI
+.It Sy ddi_io_getb	illumos DDI
+.It Sy ddi_io_getl	illumos DDI
+.It Sy ddi_io_getw	illumos DDI
+.It Sy ddi_io_put16	illumos DDI
+.It Sy ddi_io_put32	illumos DDI
+.It Sy ddi_io_put8	illumos DDI
+.It Sy ddi_io_putb	illumos DDI
+.It Sy ddi_io_putl	illumos DDI
+.It Sy ddi_io_putw	illumos DDI
+.It Sy ddi_io_rep_get16	illumos DDI
+.It Sy ddi_io_rep_get32	illumos DDI
+.It Sy ddi_io_rep_get8	illumos DDI
+.It Sy ddi_io_rep_getb	illumos DDI
+.It Sy ddi_io_rep_getl	illumos DDI
+.It Sy ddi_io_rep_getw	illumos DDI
+.It Sy ddi_io_rep_put16	illumos DDI
+.It Sy ddi_io_rep_put32	illumos DDI
+.It Sy ddi_io_rep_put8	illumos DDI
+.It Sy ddi_io_rep_putb	illumos DDI
+.It Sy ddi_io_rep_putl	illumos DDI
+.It Sy ddi_io_rep_putw	illumos DDI
+.It Sy ddi_iomin	illumos DDI
+.It Sy ddi_log_sysevent	illumos DDI
+.It Sy ddi_map_regs	illumos DDI
+.It Sy ddi_mapdev	illumos DDI
+.It Sy ddi_mapdev_intercept	illumos DDI
+.It Sy ddi_mapdev_nointercept	illumos DDI
+.It Sy ddi_mapdev_set_device_acc_attr	illumos DDI
+.It Sy ddi_mem_get16	illumos DDI
+.It Sy ddi_mem_get32	illumos DDI
+.It Sy ddi_mem_get64	illumos DDI
+.It Sy ddi_mem_get8	illumos DDI
+.It Sy ddi_mem_getb	illumos DDI
+.It Sy ddi_mem_getl	illumos DDI
+.It Sy ddi_mem_getll	illumos DDI
+.It Sy ddi_mem_getw	illumos DDI
+.It Sy ddi_mem_put16	illumos DDI
+.It Sy ddi_mem_put32	illumos DDI
+.It Sy ddi_mem_put64	illumos DDI
+.It Sy ddi_mem_put8	illumos DDI
+.It Sy ddi_mem_putb	illumos DDI
+.It Sy ddi_mem_putl	illumos DDI
+.It Sy ddi_mem_putll	illumos DDI
+.It Sy ddi_mem_putw	illumos DDI
+.It Sy ddi_mem_rep_get16	illumos DDI
+.It Sy ddi_mem_rep_get32	illumos DDI
+.It Sy ddi_mem_rep_get64	illumos DDI
+.It Sy ddi_mem_rep_get8	illumos DDI
+.It Sy ddi_mem_rep_getb	illumos DDI
+.It Sy ddi_mem_rep_getl	illumos DDI
+.It Sy ddi_mem_rep_getll	illumos DDI
+.It Sy ddi_mem_rep_getw	illumos DDI
+.It Sy ddi_mem_rep_put16	illumos DDI
+.It Sy ddi_mem_rep_put32	illumos DDI
+.It Sy ddi_mem_rep_put64	illumos DDI
+.It Sy ddi_mem_rep_put8	illumos DDI
+.It Sy ddi_mem_rep_putb	illumos DDI
+.It Sy ddi_mem_rep_putl	illumos DDI
+.It Sy ddi_mem_rep_putll	illumos DDI
+.It Sy ddi_mem_rep_putw	illumos DDI
+.It Sy ddi_mmap_get_model	illumos DDI
+.It Sy ddi_model_convert_from	illumos DDI
+.It Sy ddi_modopen	illumos DDI
+.It Sy ddi_no_info	illumos DDI
+.It Sy ddi_node_name	illumos DDI
+.It Sy ddi_peek16	illumos DDI
+.It Sy ddi_peek32	illumos DDI
+.It Sy ddi_peek64	illumos DDI
+.It Sy ddi_peek8	illumos DDI
+.It Sy ddi_peekc	illumos DDI
+.It Sy ddi_peekd	illumos DDI
+.It Sy ddi_peekl	illumos DDI
+.It Sy ddi_peeks	illumos DDI
+.It Sy ddi_periodic_add	illumos DDI
+.It Sy ddi_periodic_delete	illumos DDI
+.It Sy ddi_poke16	illumos DDI
+.It Sy ddi_poke32	illumos DDI
+.It Sy ddi_poke64	illumos DDI
+.It Sy ddi_poke8	illumos DDI
+.It Sy ddi_pokec	illumos DDI
+.It Sy ddi_poked	illumos DDI
+.It Sy ddi_pokel	illumos DDI
+.It Sy ddi_pokes	illumos DDI
+.It Sy ddi_prop_create	illumos DDI
+.It Sy ddi_prop_exists	illumos DDI
+.It Sy ddi_prop_free	illumos DDI
+.It Sy ddi_prop_get_int	illumos DDI
+.It Sy ddi_prop_lookup	illumos DDI
+.It Sy ddi_prop_lookup_byte_array	illumos DDI
+.It Sy ddi_prop_lookup_int_array	illumos DDI
+.It Sy ddi_prop_lookup_string	illumos DDI
+.It Sy ddi_prop_lookup_string_array	illumos DDI
+.It Sy ddi_prop_modify	illumos DDI
+.It Sy ddi_prop_op	illumos DDI
+.It Sy ddi_prop_remove	illumos DDI
+.It Sy ddi_prop_remove_all	illumos DDI
+.It Sy ddi_prop_undefine	illumos DDI
+.It Sy ddi_prop_update	illumos DDI
+.It Sy ddi_prop_update_byte_array	illumos DDI
+.It Sy ddi_prop_update_int	illumos DDI
+.It Sy ddi_prop_update_int_array	illumos DDI
+.It Sy ddi_prop_update_string	illumos DDI
+.It Sy ddi_prop_update_string_array	illumos DDI
+.It Sy ddi_ptob	illumos DDI
+.It Sy ddi_put16	illumos DDI
+.It Sy ddi_put32	illumos DDI
+.It Sy ddi_put64	illumos DDI
+.It Sy ddi_put8	illumos DDI
+.It Sy ddi_putb	illumos DDI
+.It Sy ddi_putl	illumos DDI
+.It Sy ddi_putll	illumos DDI
+.It Sy ddi_putw	illumos DDI
+.It Sy ddi_regs_map_free	illumos DDI
+.It Sy ddi_regs_map_setup	illumos DDI
+.It Sy ddi_remove_event_handler	illumos DDI
+.It Sy ddi_remove_intr	illumos DDI
+.It Sy ddi_remove_minor_node	illumos DDI
+.It Sy ddi_remove_softintr	illumos DDI
+.It Sy ddi_removing_power	illumos DDI
+.It Sy ddi_rep_get16	illumos DDI
+.It Sy ddi_rep_get32	illumos DDI
+.It Sy ddi_rep_get64	illumos DDI
+.It Sy ddi_rep_get8	illumos DDI
+.It Sy ddi_rep_getb	illumos DDI
+.It Sy ddi_rep_getl	illumos DDI
+.It Sy ddi_rep_getll	illumos DDI
+.It Sy ddi_rep_getw	illumos DDI
+.It Sy ddi_rep_put16	illumos DDI
+.It Sy ddi_rep_put32	illumos DDI
+.It Sy ddi_rep_put64	illumos DDI
+.It Sy ddi_rep_put8	illumos DDI
+.It Sy ddi_rep_putb	illumos DDI
+.It Sy ddi_rep_putl	illumos DDI
+.It Sy ddi_rep_putll	illumos DDI
+.It Sy ddi_rep_putw	illumos DDI
+.It Sy ddi_report_dev	illumos DDI
+.It Sy ddi_root_node	illumos DDI
+.It Sy ddi_segmap	illumos DDI
+.It Sy ddi_segmap_setup	illumos DDI
+.It Sy ddi_set_driver_private	illumos DDI
+.It Sy ddi_slaveonly	illumos DDI
+.It Sy ddi_soft_state	illumos DDI
+.It Sy ddi_soft_state_fini	illumos DDI
+.It Sy ddi_soft_state_free	illumos DDI
+.It Sy ddi_soft_state_init	illumos DDI
+.It Sy ddi_soft_state_zalloc	illumos DDI
+.It Sy ddi_strlol	illumos DDI
+.It Sy ddi_strloul	illumos DDI
+.It Sy ddi_trigger_softintr	illumos DDI
+.It Sy ddi_umem_alloc	illumos DDI
+.It Sy ddi_umem_free	illumos DDI
+.It Sy ddi_umem_iosetup	illumos DDI
+.It Sy ddi_umem_lock	illumos DDI
+.It Sy ddi_unmap_regs	illumos DDI
 .It Sy delay	DDI/DKI
-.It Sy devmap_default_access	Solaris DDI
-.It Sy devmap_devmem_setup	Solaris DDI
-.It Sy devmap_do_ctxmgt	Solaris DDI
-.It Sy devmap_load	Solaris DDI
-.It Sy devmap_set_ctx_timeout	Solaris DDI
-.It Sy devmap_setup	Solaris DDI
-.It Sy devmap_umem_setup	Solaris DDI
-.It Sy devmap_unload	Solaris DDI
-.It Sy disksort	Solaris DDI
-.It Sy dlbindack	Solaris DDI
+.It Sy devmap_default_access	illumos DDI
+.It Sy devmap_devmem_setup	illumos DDI
+.It Sy devmap_do_ctxmgt	illumos DDI
+.It Sy devmap_load	illumos DDI
+.It Sy devmap_set_ctx_timeout	illumos DDI
+.It Sy devmap_setup	illumos DDI
+.It Sy devmap_umem_setup	illumos DDI
+.It Sy devmap_unload	illumos DDI
+.It Sy disksort	illumos DDI
+.It Sy dlbindack	illumos DDI
 .It Sy drv_getparm	DDI/DKI
 .It Sy drv_hztousec	DDI/DKI
 .It Sy drv_priv	DDI/DKI
 .It Sy drv_usectohz	DDI/DKI
 .It Sy drv_usecwait	DDI/DKI
-.It Sy free_pktiopb	Solaris DDI
+.It Sy free_pktiopb	illumos DDI
 .It Sy freerbuf	DDI/DKI
-.It Sy get_pktiopb	Solaris DDI
+.It Sy get_pktiopb	illumos DDI
 .It Sy geterror	DDI/DKI
 .It Sy gethrtime	DDI/DKI
 .It Sy getmajor	DDI/DKI
 .It Sy getminor	DDI/DKI
 .It Sy getrbuf	DDI/DKI
-.It Sy gld	Solaris DDI
+.It Sy gld	illumos DDI
 .It Sy hat_getkpfnum	DKI only
-.It Sy id32_alloc	Solaris DDI
-.It Sy inb	Solaris x86 DDI
-.It Sy inl	Solaris x86 DDI
-.It Sy inw	Solaris x86 DDI
-.It Sy kiconv	Solaris DDI
-.It Sy kiconv_close	Solaris DDI
-.It Sy kiconv_open	Solaris DDI
-.It Sy kiconvstr	Solaris DDI
+.It Sy id32_alloc	illumos DDI
+.It Sy inb	illumos x86 DDI
+.It Sy inl	illumos x86 DDI
+.It Sy inw	illumos x86 DDI
+.It Sy kiconv	illumos DDI
+.It Sy kiconv_close	illumos DDI
+.It Sy kiconv_open	illumos DDI
+.It Sy kiconvstr	illumos DDI
 .It Sy kmem_alloc	DDI/DKI
-.It Sy kmem_cache_create	Solaris DDI
+.It Sy kmem_cache_create	illumos DDI
 .It Sy kmem_free	DDI/DKI
 .It Sy kmem_zalloc	DDI/DKI
-.It Sy kstat_create	Solaris DDI
-.It Sy kstat_delete	Solaris DDI
-.It Sy kstat_install	Solaris DDI
-.It Sy kstat_named_init	Solaris DDI
-.It Sy kstat_queue	Solaris DDI
-.It Sy kstat_runq_back_to_waitq	Solaris DDI
-.It Sy kstat_runq_enter	Solaris DDI
-.It Sy kstat_runq_exit	Solaris DDI
-.It Sy kstat_waitq_enter	Solaris DDI
-.It Sy kstat_waitq_exit	Solaris DDI
-.It Sy kstat_waitq_to_runq	Solaris DDI
-.It Sy ldi_add_event_handler	Solaris DDI
-.It Sy ldi_aread	Solaris DDI
-.It Sy ldi_devmap	Solaris DDI
-.It Sy ldi_dump	Solaris DDI
-.It Sy ldi_ev_finalize	Solaris DDI
-.It Sy ldi_ev_get_cookie	Solaris DDI
-.It Sy ldi_ev_get_type	Solaris DDI
-.It Sy ldi_ev_notify	Solaris DDI
-.It Sy ldi_ev_register_callbacks	Solaris DDI
-.It Sy ldi_ev_remove_callbacks	Solaris DDI
-.It Sy ldi_get_dev	Solaris DDI
-.It Sy ldi_get_eventcookie	Solaris DDI
-.It Sy ldi_get_size	Solaris DDI
-.It Sy ldi_ident_from_dev	Solaris DDI
-.It Sy ldi_ioctl	Solaris DDI
-.It Sy ldi_open_by_dev	Solaris DDI
-.It Sy ldi_poll	Solaris DDI
-.It Sy ldi_prop_exists	Solaris DDI
-.It Sy ldi_prop_get_int	Solaris DDI
-.It Sy ldi_prop_get_lookup_int_array	Solaris DDI
-.It Sy ldi_putmsg	Solaris DDI
-.It Sy ldi_read	Solaris DDI
-.It Sy ldi_remove_event_handler	Solaris DDI
-.It Sy ldi_strategy	Solaris DDI
-.It Sy makecom_g0	Solaris DDI
-.It Sy makecom_g0_s	Solaris DDI
-.It Sy makecom_g1	Solaris DDI
-.It Sy makecom_g5	Solaris DDI
+.It Sy kstat_create	illumos DDI
+.It Sy kstat_delete	illumos DDI
+.It Sy kstat_install	illumos DDI
+.It Sy kstat_named_init	illumos DDI
+.It Sy kstat_queue	illumos DDI
+.It Sy kstat_runq_back_to_waitq	illumos DDI
+.It Sy kstat_runq_enter	illumos DDI
+.It Sy kstat_runq_exit	illumos DDI
+.It Sy kstat_waitq_enter	illumos DDI
+.It Sy kstat_waitq_exit	illumos DDI
+.It Sy kstat_waitq_to_runq	illumos DDI
+.It Sy ldi_add_event_handler	illumos DDI
+.It Sy ldi_aread	illumos DDI
+.It Sy ldi_devmap	illumos DDI
+.It Sy ldi_dump	illumos DDI
+.It Sy ldi_ev_finalize	illumos DDI
+.It Sy ldi_ev_get_cookie	illumos DDI
+.It Sy ldi_ev_get_type	illumos DDI
+.It Sy ldi_ev_notify	illumos DDI
+.It Sy ldi_ev_register_callbacks	illumos DDI
+.It Sy ldi_ev_remove_callbacks	illumos DDI
+.It Sy ldi_get_dev	illumos DDI
+.It Sy ldi_get_eventcookie	illumos DDI
+.It Sy ldi_get_size	illumos DDI
+.It Sy ldi_ident_from_dev	illumos DDI
+.It Sy ldi_ioctl	illumos DDI
+.It Sy ldi_open_by_dev	illumos DDI
+.It Sy ldi_poll	illumos DDI
+.It Sy ldi_prop_exists	illumos DDI
+.It Sy ldi_prop_get_int	illumos DDI
+.It Sy ldi_prop_get_lookup_int_array	illumos DDI
+.It Sy ldi_putmsg	illumos DDI
+.It Sy ldi_read	illumos DDI
+.It Sy ldi_remove_event_handler	illumos DDI
+.It Sy ldi_strategy	illumos DDI
+.It Sy makecom_g0	illumos DDI
+.It Sy makecom_g0_s	illumos DDI
+.It Sy makecom_g1	illumos DDI
+.It Sy makecom_g5	illumos DDI
 .It Sy makedevice	DDI/DKI
 .It Sy max	DDI/DKI
-.It Sy membar_ops	Solaris DDI
-.It Sy memchr	Solaris DDI
+.It Sy membar_ops	illumos DDI
+.It Sy memchr	illumos DDI
 .It Sy min	DDI/DKI
-.It Sy minphys	Solaris DDI
-.It Sy mod_info	Solaris DDI
-.It Sy mod_install	Solaris DDI
-.It Sy mod_remove	Solaris DDI
-.It Sy mutex_destroy	Solaris DDI
-.It Sy mutex_enter	Solaris DDI
-.It Sy mutex_exit	Solaris DDI
-.It Sy mutex_init	Solaris DDI
-.It Sy mutex_owned	Solaris DDI
-.It Sy mutex_tryenter	Solaris DDI
-.It Sy nochpoll	Solaris DDI
+.It Sy minphys	illumos DDI
+.It Sy mod_info	illumos DDI
+.It Sy mod_install	illumos DDI
+.It Sy mod_remove	illumos DDI
+.It Sy mutex_destroy	illumos DDI
+.It Sy mutex_enter	illumos DDI
+.It Sy mutex_exit	illumos DDI
+.It Sy mutex_init	illumos DDI
+.It Sy mutex_owned	illumos DDI
+.It Sy mutex_tryenter	illumos DDI
+.It Sy nochpoll	illumos DDI
 .It Sy nodev	DDI/DKI
 .It Sy nulldev	DDI/DKI
-.It Sy numtos	Solaris DDI
-.It Sy nvlist_add_boolean	Solaris DDI
-.It Sy nvlist_alloc	Solaris DDI
-.It Sy nvlist_lookup_boolean	Solaris DDI
-.It Sy nvlist_lookup_nvpair	Solaris DDI
-.It Sy nvlist_next_nvpair	Solaris DDI
-.It Sy nvlist_remove	Solaris DDI
-.It Sy nvlist_value_byte	Solaris DDI
-.It Sy outb	Solaris x86 DDI
-.It Sy outl	Solaris x86 DDI
-.It Sy outw	Solaris x86 DDI
-.It Sy pci_config_get16	Solaris DDI
-.It Sy pci_config_get32	Solaris DDI
-.It Sy pci_config_get64	Solaris DDI
-.It Sy pci_config_get8	Solaris DDI
-.It Sy pci_config_getb	Solaris DDI
-.It Sy pci_config_getl	Solaris DDI
-.It Sy pci_config_getw	Solaris DDI
-.It Sy pci_config_put16	Solaris DDI
-.It Sy pci_config_put32	Solaris DDI
-.It Sy pci_config_put64	Solaris DDI
-.It Sy pci_config_put8	Solaris DDI
-.It Sy pci_config_putb	Solaris DDI
-.It Sy pci_config_putl	Solaris DDI
-.It Sy pci_config_putw	Solaris DDI
-.It Sy pci_config_setup	Solaris DDI
-.It Sy pci_config_teardown	Solaris DDI
-.It Sy pci_ereport_setup	Solaris DDI
-.It Sy pci_report_pmcap	Solaris DDI
-.It Sy pci_save_config_regs	Solaris DDI
-.It Sy physio	Solaris DDI
-.It Sy pm_busy_component	Solaris DDI
-.It Sy pm_power_has_changed	Solaris DDI
-.It Sy pm_raise_power	Solaris DDI
-.It Sy pm_trans_check	Solaris DDI
+.It Sy numtos	illumos DDI
+.It Sy nvlist_add_boolean	illumos DDI
+.It Sy nvlist_alloc	illumos DDI
+.It Sy nvlist_lookup_boolean	illumos DDI
+.It Sy nvlist_lookup_nvpair	illumos DDI
+.It Sy nvlist_next_nvpair	illumos DDI
+.It Sy nvlist_remove	illumos DDI
+.It Sy nvlist_value_byte	illumos DDI
+.It Sy outb	illumos x86 DDI
+.It Sy outl	illumos x86 DDI
+.It Sy outw	illumos x86 DDI
+.It Sy pci_config_get16	illumos DDI
+.It Sy pci_config_get32	illumos DDI
+.It Sy pci_config_get64	illumos DDI
+.It Sy pci_config_get8	illumos DDI
+.It Sy pci_config_getb	illumos DDI
+.It Sy pci_config_getl	illumos DDI
+.It Sy pci_config_getw	illumos DDI
+.It Sy pci_config_put16	illumos DDI
+.It Sy pci_config_put32	illumos DDI
+.It Sy pci_config_put64	illumos DDI
+.It Sy pci_config_put8	illumos DDI
+.It Sy pci_config_putb	illumos DDI
+.It Sy pci_config_putl	illumos DDI
+.It Sy pci_config_putw	illumos DDI
+.It Sy pci_config_setup	illumos DDI
+.It Sy pci_config_teardown	illumos DDI
+.It Sy pci_ereport_setup	illumos DDI
+.It Sy pci_report_pmcap	illumos DDI
+.It Sy pci_save_config_regs	illumos DDI
+.It Sy physio	illumos DDI
+.It Sy pm_busy_component	illumos DDI
+.It Sy pm_power_has_changed	illumos DDI
+.It Sy pm_raise_power	illumos DDI
+.It Sy pm_trans_check	illumos DDI
 .It Sy pollwakeup	DDI/DKI
-.It Sy pci_config_teardown	Solaris DDI
-.It Sy pci_config_teardown	Solaris DDI
-.It Sy priv_getbyname	Solaris DDI
-.It Sy priv_policy	Solaris DDI
-.It Sy proc_signal	Solaris DDI
-.It Sy proc_unref	Solaris DDI
+.It Sy pci_config_teardown	illumos DDI
+.It Sy pci_config_teardown	illumos DDI
+.It Sy priv_getbyname	illumos DDI
+.It Sy priv_policy	illumos DDI
+.It Sy proc_signal	illumos DDI
+.It Sy proc_unref	illumos DDI
 .It Sy ptob	DDI/DKI
-.It Sy repinsb	Solaris x86 DDI
-.It Sy repinsd	Solaris x86 DDI
-.It Sy repinsw	Solaris x86 DDI
-.It Sy repoutsb	Solaris x86 DDI
-.It Sy repoutsd	Solaris x86 DDI
-.It Sy repoutsw	Solaris x86 DDI
+.It Sy repinsb	illumos x86 DDI
+.It Sy repinsd	illumos x86 DDI
+.It Sy repinsw	illumos x86 DDI
+.It Sy repoutsb	illumos x86 DDI
+.It Sy repoutsd	illumos x86 DDI
+.It Sy repoutsw	illumos x86 DDI
 .It Sy rmalloc	DDI/DKI
 .It Sy rmalloc_wait	DDI/DKI
 .It Sy rmallocmap	DDI/DKI
 .It Sy rmallocmap_wait	DDI/DKI
 .It Sy rmfree	DDI/DKI
 .It Sy rmfreemap	DDI/DKI
-.It Sy rw_destroy	Solaris DDI
-.It Sy rw_downgrade	Solaris DDI
-.It Sy rw_enter	Solaris DDI
-.It Sy rw_exit	Solaris DDI
-.It Sy rw_init	Solaris DDI
-.It Sy rw_read_locked	Solaris DDI
-.It Sy rw_tryenter	Solaris DDI
-.It Sy rw_tryupgrade	Solaris DDI
-.It Sy scsi_abort	Solaris DDI
-.It Sy scsi_alloc_consistent_buf	Solaris DDI
-.It Sy scsi_cname	Solaris DDI
-.It Sy scsi_destroy_pkt	Solaris DDI
-.It Sy scsi_dmafree	Solaris DDI
-.It Sy scsi_dmaget	Solaris DDI
-.It Sy scsi_dname	Solaris DDI
-.It Sy scsi_errmsg	Solaris DDI
-.It Sy scsi_ext_sense_fields	Solaris DDI
-.It Sy scsi_find_sense_descr	Solaris DDI
-.It Sy scsi_free_consistent_buf	Solaris DDI
-.It Sy scsi_get_device_type_scsi_options	Solaris DDI
-.It Sy scsi_get_device_type_string	Solaris DDI
-.It Sy scsi_hba_attach_setup	Solaris DDI
-.It Sy scsi_hba_detach	Solaris DDI
-.It Sy scsi_hba_fini	Solaris DDI
-.It Sy scsi_hba_init	Solaris DDI
-.It Sy scsi_hba_lookup_capstr	Solaris DDI
-.It Sy scsi_hba_pkt_alloc	Solaris DDI
-.It Sy scsi_hba_pkt_free	Solaris DDI
-.It Sy scsi_hba_probe	Solaris DDI
-.It Sy scsi_hba_tran_alloc	Solaris DDI
-.It Sy scsi_hba_tran_free	Solaris DDI
-.It Sy scsi_ifgetcap	Solaris DDI
-.It Sy scsi_ifsetcap	Solaris DDI
-.It Sy scsi_init_pkt	Solaris DDI
-.It Sy scsi_log	Solaris DDI
-.It Sy scsi_mname	Solaris DDI
-.It Sy scsi_pktalloc	Solaris DDI
-.It Sy scsi_pktfree	Solaris DDI
-.It Sy scsi_poll	Solaris DDI
-.It Sy scsi_probe	Solaris DDI
-.It Sy scsi_resalloc	Solaris DDI
-.It Sy scsi_reset	Solaris DDI
-.It Sy scsi_reset_notify	Solaris DDI
-.It Sy scsi_resfree	Solaris DDI
-.It Sy scsi_rname	Solaris DDI
-.It Sy scsi_sense_key	Solaris DDI
-.It Sy scsi_setup_cdb	Solaris DDI
-.It Sy scsi_slave	Solaris DDI
-.It Sy scsi_sname	Solaris DDI
-.It Sy scsi_sync_pkt	Solaris DDI
-.It Sy scsi_transport	Solaris DDI
-.It Sy scsi_unprobe	Solaris DDI
-.It Sy scsi_unslave	Solaris DDI
-.It Sy scsi_validate_sense	Solaris DDI
-.It Sy scsi_vu_errmsg	Solaris DDI
-.It Sy sema_destroy	Solaris DDI
-.It Sy sema_init	Solaris DDI
-.It Sy sema_p	Solaris DDI
-.It Sy sema_p_sig	Solaris DDI
-.It Sy sema_tryp	Solaris DDI
-.It Sy sema_v	Solaris DDI
-.It Sy sprintf	Solaris DDI
-.It Sy stoi	Solaris DDI
-.It Sy strchr	Solaris DDI
-.It Sy strcmp	Solaris DDI
-.It Sy strcpy	Solaris DDI
-.It Sy strlen	Solaris DDI
-.It Sy strncmp	Solaris DDI
-.It Sy strncpy	Solaris DDI
-.It Sy STRUCT_DECL	Solaris DDI
+.It Sy rw_destroy	illumos DDI
+.It Sy rw_downgrade	illumos DDI
+.It Sy rw_enter	illumos DDI
+.It Sy rw_exit	illumos DDI
+.It Sy rw_init	illumos DDI
+.It Sy rw_read_locked	illumos DDI
+.It Sy rw_tryenter	illumos DDI
+.It Sy rw_tryupgrade	illumos DDI
+.It Sy scsi_abort	illumos DDI
+.It Sy scsi_alloc_consistent_buf	illumos DDI
+.It Sy scsi_cname	illumos DDI
+.It Sy scsi_destroy_pkt	illumos DDI
+.It Sy scsi_dmafree	illumos DDI
+.It Sy scsi_dmaget	illumos DDI
+.It Sy scsi_dname	illumos DDI
+.It Sy scsi_errmsg	illumos DDI
+.It Sy scsi_ext_sense_fields	illumos DDI
+.It Sy scsi_find_sense_descr	illumos DDI
+.It Sy scsi_free_consistent_buf	illumos DDI
+.It Sy scsi_get_device_type_scsi_options	illumos DDI
+.It Sy scsi_get_device_type_string	illumos DDI
+.It Sy scsi_hba_attach_setup	illumos DDI
+.It Sy scsi_hba_detach	illumos DDI
+.It Sy scsi_hba_fini	illumos DDI
+.It Sy scsi_hba_init	illumos DDI
+.It Sy scsi_hba_lookup_capstr	illumos DDI
+.It Sy scsi_hba_pkt_alloc	illumos DDI
+.It Sy scsi_hba_pkt_free	illumos DDI
+.It Sy scsi_hba_probe	illumos DDI
+.It Sy scsi_hba_tran_alloc	illumos DDI
+.It Sy scsi_hba_tran_free	illumos DDI
+.It Sy scsi_ifgetcap	illumos DDI
+.It Sy scsi_ifsetcap	illumos DDI
+.It Sy scsi_init_pkt	illumos DDI
+.It Sy scsi_log	illumos DDI
+.It Sy scsi_mname	illumos DDI
+.It Sy scsi_pktalloc	illumos DDI
+.It Sy scsi_pktfree	illumos DDI
+.It Sy scsi_poll	illumos DDI
+.It Sy scsi_probe	illumos DDI
+.It Sy scsi_resalloc	illumos DDI
+.It Sy scsi_reset	illumos DDI
+.It Sy scsi_reset_notify	illumos DDI
+.It Sy scsi_resfree	illumos DDI
+.It Sy scsi_rname	illumos DDI
+.It Sy scsi_sense_key	illumos DDI
+.It Sy scsi_setup_cdb	illumos DDI
+.It Sy scsi_slave	illumos DDI
+.It Sy scsi_sname	illumos DDI
+.It Sy scsi_sync_pkt	illumos DDI
+.It Sy scsi_transport	illumos DDI
+.It Sy scsi_unprobe	illumos DDI
+.It Sy scsi_unslave	illumos DDI
+.It Sy scsi_validate_sense	illumos DDI
+.It Sy scsi_vu_errmsg	illumos DDI
+.It Sy sema_destroy	illumos DDI
+.It Sy sema_init	illumos DDI
+.It Sy sema_p	illumos DDI
+.It Sy sema_p_sig	illumos DDI
+.It Sy sema_tryp	illumos DDI
+.It Sy sema_v	illumos DDI
+.It Sy sprintf	illumos DDI
+.It Sy stoi	illumos DDI
+.It Sy strchr	illumos DDI
+.It Sy strcmp	illumos DDI
+.It Sy strcpy	illumos DDI
+.It Sy strlen	illumos DDI
+.It Sy strncmp	illumos DDI
+.It Sy strncpy	illumos DDI
+.It Sy STRUCT_DECL	illumos DDI
 .It Sy swab	DDI/DKI
-.It Sy taskq	Solaris DDI
+.It Sy taskq	illumos DDI
 .It Sy timeout	DDI/DKI
-.It Sy u8_strcmp	Solaris DDI
-.It Sy u8_textprep_str	Solaris DDI
-.It Sy u8_validate	Solaris DDI
-.It Sy uconv_u16tou32	Solaris DDI
+.It Sy u8_strcmp	illumos DDI
+.It Sy u8_textprep_str	illumos DDI
+.It Sy u8_validate	illumos DDI
+.It Sy uconv_u16tou32	illumos DDI
 .It Sy uiomove	DDI/DKI
 .It Sy untimeout	DDI/DKI
 .It Sy ureadc	DDI/DKI
-.It Sy usb_alloc_request	Solaris DDI
-.It Sy usb_client_attach	Solaris DDI
-.It Sy usb_clr_feature	Solaris DDI
-.It Sy usb_create_pm_components	Solaris DDI
-.It Sy usb_get_addr	Solaris DDI
-.It Sy usb_get_alt_if	Solaris DDI
-.It Sy usb_get_cfg	Solaris DDI
-.It Sy usb_get_current_frame_number	Solaris DDI
-.It Sy usb_get_dev_data	Solaris DDI
-.It Sy usb_get_max_pkts_per_ioc_request	Solaris DDI
-.It Sy usb_get_status	Solaris DDI
-.It Sy usb_get_string_desc	Solaris DDI
-.It Sy usb_handle_remote_wakeup	Solaris DDI
-.It Sy usb_lookup_ep_data	Solaris DDI
-.It Sy usb_parse_data	Solaris DDI
-.It Sy usb_pipe_bulk_xfer	Solaris DDI
-.It Sy usb_pipe_close	Solaris DDI
-.It Sy usb_pipe_ctrl_xfer	Solaris DDI
-.It Sy usb_pipe_drain_reqs	Solaris DDI
-.It Sy usb_pipe_get_max_bulk_transfer_size	Solaris DDI
-.It Sy usb_pipe_get_state	Solaris DDI
-.It Sy usb_pipe_intr_xfer	Solaris DDI
-.It Sy usb_pipe_isoc_xfer	Solaris DDI
-.It Sy usb_pipe_open	Solaris DDI
-.It Sy usb_pipe_reset	Solaris DDI
-.It Sy usb_pipe_set_private	Solaris DDI
-.It Sy usb_register_hotplug_cbs	Solaris DDI
-.It Sy usb_reset_device	Solaris DDI
+.It Sy usb_alloc_request	illumos DDI
+.It Sy usb_client_attach	illumos DDI
+.It Sy usb_clr_feature	illumos DDI
+.It Sy usb_create_pm_components	illumos DDI
+.It Sy usb_get_addr	illumos DDI
+.It Sy usb_get_alt_if	illumos DDI
+.It Sy usb_get_cfg	illumos DDI
+.It Sy usb_get_current_frame_number	illumos DDI
+.It Sy usb_get_dev_data	illumos DDI
+.It Sy usb_get_max_pkts_per_ioc_request	illumos DDI
+.It Sy usb_get_status	illumos DDI
+.It Sy usb_get_string_desc	illumos DDI
+.It Sy usb_handle_remote_wakeup	illumos DDI
+.It Sy usb_lookup_ep_data	illumos DDI
+.It Sy usb_parse_data	illumos DDI
+.It Sy usb_pipe_bulk_xfer	illumos DDI
+.It Sy usb_pipe_close	illumos DDI
+.It Sy usb_pipe_ctrl_xfer	illumos DDI
+.It Sy usb_pipe_drain_reqs	illumos DDI
+.It Sy usb_pipe_get_max_bulk_transfer_size	illumos DDI
+.It Sy usb_pipe_get_state	illumos DDI
+.It Sy usb_pipe_intr_xfer	illumos DDI
+.It Sy usb_pipe_isoc_xfer	illumos DDI
+.It Sy usb_pipe_open	illumos DDI
+.It Sy usb_pipe_reset	illumos DDI
+.It Sy usb_pipe_set_private	illumos DDI
+.It Sy usb_register_hotplug_cbs	illumos DDI
+.It Sy usb_reset_device	illumos DDI
 .It Sy uwritec	DDI/DKI
-.It Sy va_arg	Solaris DDI
-.It Sy va_end	Solaris DDI
-.It Sy va_start	Solaris DDI
+.It Sy va_arg	illumos DDI
+.It Sy va_end	illumos DDI
+.It Sy va_start	illumos DDI
 .It Sy vcmn_err	DDI/DKI
-.It Sy vsprintf	Solaris DDI
+.It Sy vsprintf	illumos DDI
 .El
 .Sh SEE ALSO
 .Xr Intro 9E ,
--- a/usr/src/man/man9f/condvar.9f	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/man/man9f/condvar.9f	Sun Jan 04 07:19:22 2015 -0800
@@ -1,5 +1,6 @@
 '\" te
 .\"  Copyright (c) 2003, Sun Microsystems, Inc.  All Rights Reserved
+.\"  Copyright (c) 2014, Joyent, Inc.
 .\" 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]
@@ -52,12 +53,22 @@
 \fBclock_t\fR \fBcv_timedwait_sig\fR(\fBkcondvar_t *\fR\fIcvp\fR, \fBkmutex_t *\fR\fImp\fR, \fBclock_t\fR \fItimeout\fR);
 .fi
 
+.LP
+.nf
+\fBclock_t\fR \fBcv_reltimedwait\fR(\fBkcondvar_t *\fR\fIcvp\fR, \fBkmutex_t *\fR\fImp\fR, \fBclock_t\fR \fIdelta\fR,
+    \fBtime_res_t\fR \fIres\fR);
+.fi
+
+.LP
+.nf
+\fBclock_t\fR \fBcv_reltimedwait_sig\fR(\fBkcondvar_t *\fR\fIcvp\fR, \fBkmutex_t *\fR\fImp\fR, \fBclock_t\fR \fIdelta\fR,
+    \fBtime_res_t\fR \fIres\fR);
+.fi
+
 .SH INTERFACE LEVEL
-.sp
 .LP
 Solaris DDI specific (Solaris DDI).
 .SH PARAMETERS
-.sp
 .ne 2
 .na
 \fB\fIcvp\fR\fR
@@ -114,8 +125,56 @@
 \fBcv_timedwait_sig()\fR should return.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fIres\fR\fR
+.ad
+.RS 11n
+A value which describes the requested accuracy of the timeout argument.
+The system may anticipate or defer the timeout based on the requested
+accuracy to prevent unnecessary wakeups. The following identifiers are
+valid arguments for this type:
+.LP
+.RS 4n
+.B TR_NANOSEC
+.RS 16n
+Nanosecond granularity
+.RE
+.RE
+.RS 4n
+.B TR_MICROSEC
+.RS 16n
+Microsecond granularity
+.RE
+.RE
+.RS 4n
+.B TR_MILLISEC
+.RS 16n
+Millisecond granularity
+.RE
+.RE
+.RS 4n
+.B TR_SEC
+.RS 16n
+Second granularity
+.RE
+.RE
+.RS 4n
+.B TR_CLOCK_TICK
+.RS 16n
+Granularity of a kernel clock tick, commonly 100 or 1000 Hz.
+.RE
+.RE
+.LP
+Note that the granularity of these functions is in clock ticks,
+therefore the only values which will have an effect are:
+.B TR_SEC
+and
+.B TR_CLOCK_TICK .
+.RE
+
 .SH DESCRIPTION
-.sp
 .LP
 Condition variables are a standard form of thread synchronization. They are
 designed to be used with mutual exclusion locks (mutexes). The associated mutex
@@ -168,16 +227,32 @@
 For both \fBcv_timedwait()\fR and \fBcv_timedwait_sig()\fR, time is in absolute
 clock ticks since the last system reboot. The current time may be found by
 calling \fBddi_get_lbolt\fR(9F).
+.sp
+.LP
+The functions
+.B cv_reltimedwait()
+and
+.B cv_reltimedwait_sig()
+behave similarly to
+.B cv_timedwait() and
+.B cv_timedwait_sig()
+respectively, except instead of taking a time in absolute clock ticks,
+they take a relative number of clock ticks to wait. In addition, both
+functions take an additional argument
+.I res,
+which specifies the desired granularity that the system should default
+to, generally the value
+.B TR_CLOCK_TICK .
 .SH RETURN VALUES
-.sp
 .ne 2
 .na
 \fB\fB0\fR\fR
 .ad
 .RS 9n
-For \fBcv_wait_sig()\fR and \fBcv_timedwait_sig()\fR indicates that the
-condition was not necessarily signaled and the function returned because a
-signal (as in \fBkill\fR(2)) was pending.
+For \fBcv_wait_sig()\fR, \fBcv_timedwait_sig()\fR, and
+\fBcv_reltimedwait_sig()\fR indicates that the condition was not necessarily
+signaled and the function returned because a signal (as in \fBkill\fR(2)) was
+pending.
 .RE
 
 .sp
@@ -186,9 +261,9 @@
 \fB\fB\(mi1\fR\fR
 .ad
 .RS 9n
-For \fBcv_timedwait()\fR and \fBcv_timedwait_sig()\fR indicates that the
-condition was not necessarily signaled and the function returned because the
-timeout time was reached.
+For \fBcv_timedwait()\fR, \fBcv_timedwait_sig()\fR, \fBcv_reltimedwait()\fR, and
+\fBcv_reltimedwait_sig()\fR, indicates that the condition was not necessarily
+signaled and the function returned because the timeout time was reached.
 .RE
 
 .sp
@@ -197,23 +272,24 @@
 \fB\fB>0\fR\fR
 .ad
 .RS 9n
-For \fBcv_wait_sig()\fR, \fBcv_timedwait()\fR or \fBcv_timedwait_sig()\fR
-indicates that the condition was met and the function returned due to a call to
-\fBcv_signal()\fR or \fBcv_broadcast()\fR, or due to a premature wakeup (see
-NOTES).
+For \fBcv_wait_sig()\fR, \fBcv_timedwait()\fR, \fBcv_timedwait_sig()\fR,
+\fBcv_reltimedwait()\fR, and \fBcv_reltimedwait_sig()\fR, indicates that the
+condition was met and the function returned due to a call to \fBcv_signal()\fR
+or \fBcv_broadcast()\fR, or due to a premature wakeup (see NOTES).
 .RE
 
 .SH CONTEXT
-.sp
 .LP
 These functions can be called from user, kernel or interrupt context. In most
-cases, however, \fBcv_wait()\fR, \fBcv_timedwait()\fR, \fBcv_wait_sig()\fR, and
-\fBcv_timedwait_sig()\fR should not be called from interrupt context, and
+cases, however, \fBcv_wait()\fR, \fBcv_timedwait()\fR, \fBcv_wait_sig()\fR,
+\fBcv_timedwait_sig()\fR, \fBcv_reltimedwait()\fR, and
+\fBcv_reltimedwait_sig()\fR, should not be called from interrupt context, and
 cannot be called from a high-level interrupt context.
 .sp
 .LP
-If \fBcv_wait()\fR, \fBcv_timedwait()\fR, \fBcv_wait_sig()\fR, or
-\fBcv_timedwait_sig()\fR are used from interrupt context, lower-priority
+If \fBcv_wait()\fR, \fBcv_timedwait()\fR, \fBcv_wait_sig()\fR,
+\fBcv_timedwait_sig()\fR, \fBcv_reltimedwait()\fR, or
+\fBcv_reltimedwait_sig()\fR, are used from interrupt context, lower-priority
 interrupts will not be serviced during the wait. This means that if the thread
 that will eventually perform the wakeup becomes blocked on anything that
 requires the lower-priority interrupt, the system will hang.
@@ -264,16 +340,16 @@
 .in -2
 
 .SH NOTES
-.sp
 .LP
 It is possible for \fBcv_wait()\fR, \fBcv_wait_sig()\fR, \fBcv_timedwait()\fR,
-and \fBcv_timedwait_sig()\fR to return prematurely, that is, not due to a call
-to \fBcv_signal()\fR or \fBcv_broadcast()\fR. This occurs most commonly in the
-case of \fBcv_wait_sig()\fR and \fBcv_timedwait_sig()\fR when the thread is
-stopped and restarted by job control signals or by a debugger, but can happen
-in other cases as well, even for \fBcv_wait()\fR. Code that calls these
-functions must always recheck the reason for blocking and call again if the
-reason for blocking is still true.
+\fBcv_timedwait_sig()\fR, \fBcv_reltimedwait()\fR, and
+\fBcv_reltimedwait_sig()\fR to return prematurely, that is, not due to a call to
+\fBcv_signal()\fR or \fBcv_broadcast()\fR. This occurs most commonly in the case
+of \fBcv_wait_sig()\fR and \fBcv_timedwait_sig()\fR when the thread is stopped
+and restarted by job control signals or by a debugger, but can happen in other
+cases as well, even for \fBcv_wait()\fR. Code that calls these functions must
+always recheck the reason for blocking and call again if the reason for blocking
+is still true.
 .sp
 .LP
 If your driver needs to wait on behalf of processes that have real-time
@@ -284,13 +360,13 @@
 .LP
 Not all threads can receive signals from user level processes. In cases where
 such reception is impossible (such as during execution of \fBclose\fR(9E) due
-to \fBexit\fR(2)), \fBcv_wait_sig()\fR behaves as \fBcv_wait()\fR, and
-\fBcv_timedwait_sig()\fR behaves as \fBcv_timedwait()\fR. To avoid unkillable
+to \fBexit\fR(2)), \fBcv_wait_sig()\fR behaves as \fBcv_wait()\fR,
+\fBcv_timedwait_sig()\fR behaves as \fBcv_timedwait()\fR, and
+\fBcv_reltimedwait_sig()\fR behaves as \fBcv_reltimedwait()\fR. To avoid unkillable
 processes, users of these functions may need to protect against waiting
 indefinitely for events that might not occur. The \fBddi_can_receive_sig\fR(9F)
 function is provided to detect when signal reception is possible.
 .SH SEE ALSO
-.sp
 .LP
 \fBkill\fR(2), \fBddi_can_receive_sig\fR(9F), \fBddi_get_lbolt\fR(9F),
 \fBmutex\fR(9F), \fBmutex_init\fR(9F)
--- a/usr/src/pkg/manifests/SUNWcs.man1.inc	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/pkg/manifests/SUNWcs.man1.inc	Sun Jan 04 07:19:22 2015 -0800
@@ -108,6 +108,7 @@
 file path=usr/share/man/man1/kill.1
 file path=usr/share/man/man1/kmfcfg.1
 file path=usr/share/man/man1/ksh93.1
+file path=usr/share/man/man1/kvmstat.1
 file path=usr/share/man/man1/ld.so.1.1
 file path=usr/share/man/man1/less.1
 file path=usr/share/man/man1/lesskey.1
--- a/usr/src/pkg/manifests/system-kernel.man2.inc	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/pkg/manifests/system-kernel.man2.inc	Sun Jan 04 07:19:22 2015 -0800
@@ -180,6 +180,7 @@
 link path=usr/share/man/man2/facl.2 target=acl.2
 link path=usr/share/man/man2/fchdir.2 target=chdir.2
 link path=usr/share/man/man2/fchmod.2 target=chmod.2
+link path=usr/share/man/man2/fchmodat.2 target=chmod.2
 link path=usr/share/man/man2/fchown.2 target=chown.2
 link path=usr/share/man/man2/fchownat.2 target=chown.2
 link path=usr/share/man/man2/fchroot.2 target=chroot.2
@@ -213,6 +214,7 @@
 link path=usr/share/man/man2/openat.2 target=open.2
 link path=usr/share/man/man2/pathconf.2 target=fpathconf.2
 link path=usr/share/man/man2/pipe2.2 target=pipe.2
+link path=usr/share/man/man2/ppoll.2 target=poll.2
 link path=usr/share/man/man2/pread.2 target=read.2
 link path=usr/share/man/man2/pset_assign.2 target=pset_create.2
 link path=usr/share/man/man2/pset_destroy.2 target=pset_create.2
--- a/usr/src/pkg/manifests/system-library.man3c.inc	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/pkg/manifests/system-library.man3c.inc	Sun Jan 04 07:19:22 2015 -0800
@@ -56,6 +56,7 @@
 file path=usr/share/man/man3c/catopen.3c
 file path=usr/share/man/man3c/cfgetispeed.3c
 file path=usr/share/man/man3c/cfsetispeed.3c
+file path=usr/share/man/man3c/clearenv.3c
 file path=usr/share/man/man3c/clock.3c
 file path=usr/share/man/man3c/clock_nanosleep.3c
 file path=usr/share/man/man3c/clock_settime.3c
@@ -108,6 +109,7 @@
 file path=usr/share/man/man3c/exit.3c
 file path=usr/share/man/man3c/fattach.3c
 file path=usr/share/man/man3c/fclose.3c
+file path=usr/share/man/man3c/fcloseall.3c
 file path=usr/share/man/man3c/fdatasync.3c
 file path=usr/share/man/man3c/fdetach.3c
 file path=usr/share/man/man3c/fdopen.3c
@@ -155,12 +157,14 @@
 file path=usr/share/man/man3c/getlogin.3c
 file path=usr/share/man/man3c/getmntent.3c
 file path=usr/share/man/man3c/getnetgrent.3c
+file path=usr/share/man/man3c/get_nprocs.3c
 file path=usr/share/man/man3c/getopt.3c
 file path=usr/share/man/man3c/getpagesize.3c
 file path=usr/share/man/man3c/getpagesizes.3c
 file path=usr/share/man/man3c/getpass.3c
 file path=usr/share/man/man3c/getpeerucred.3c
 file path=usr/share/man/man3c/getpriority.3c
+file path=usr/share/man/man3c/getprogname.3c
 file path=usr/share/man/man3c/getpw.3c
 file path=usr/share/man/man3c/getpwnam.3c
 file path=usr/share/man/man3c/getrusage.3c
@@ -310,6 +314,7 @@
 file path=usr/share/man/man3c/pthread_key_delete.3c
 file path=usr/share/man/man3c/pthread_kill.3c
 file path=usr/share/man/man3c/pthread_mutex_getprioceiling.3c
+file path=usr/share/man/man3c/pthread_mutex_consistent.3c
 file path=usr/share/man/man3c/pthread_mutex_init.3c
 file path=usr/share/man/man3c/pthread_mutex_lock.3c
 file path=usr/share/man/man3c/pthread_mutex_consistent.3c
@@ -401,6 +406,7 @@
 file path=usr/share/man/man3c/sigstack.3c
 file path=usr/share/man/man3c/sigwaitinfo.3c
 file path=usr/share/man/man3c/sleep.3c
+file path=usr/share/man/man3c/smt_pause.3c
 file path=usr/share/man/man3c/ssignal.3c
 file path=usr/share/man/man3c/stack_getbounds.3c
 file path=usr/share/man/man3c/stack_inbounds.3c
@@ -666,6 +672,7 @@
 link path=usr/share/man/man3c/btowc_l.3c target=btowc.3c
 link path=usr/share/man/man3c/bzero.3c target=bstring.3c
 link path=usr/share/man/man3c/calloc.3c target=malloc.3c
+link path=usr/share/man/man3c/canonicalize_file_name.3c target=realpath.3c
 link path=usr/share/man/man3c/catclose.3c target=catopen.3c
 link path=usr/share/man/man3c/cfgetospeed.3c target=cfgetispeed.3c
 link path=usr/share/man/man3c/cfsetospeed.3c target=cfsetispeed.3c
@@ -735,6 +742,8 @@
 link path=usr/share/man/man3c/fdopendir.3c target=opendir.3c
 link path=usr/share/man/man3c/fdwalk.3c target=closefrom.3c
 link path=usr/share/man/man3c/feof.3c target=ferror.3c
+link path=usr/share/man/man3c/ffsl.3c target=ffs.3c
+link path=usr/share/man/man3c/ffsll.3c target=ffs.3c
 link path=usr/share/man/man3c/fgetgrent.3c target=getgrnam.3c
 link path=usr/share/man/man3c/fgetgrent_r.3c target=getgrnam.3c
 link path=usr/share/man/man3c/fgetpwent.3c target=getpwnam.3c
@@ -747,6 +756,9 @@
 link path=usr/share/man/man3c/file_to_decimal.3c target=string_to_decimal.3c
 link path=usr/share/man/man3c/fileno.3c target=ferror.3c
 link path=usr/share/man/man3c/finite.3c target=isnand.3c
+link path=usr/share/man/man3c/fls.3c target=ffs.3c
+link path=usr/share/man/man3c/flsl.3c target=ffs.3c
+link path=usr/share/man/man3c/flsll.3c target=ffs.3c
 link path=usr/share/man/man3c/fpclass.3c target=isnand.3c
 link path=usr/share/man/man3c/fpgetmask.3c target=fpgetround.3c
 link path=usr/share/man/man3c/fpgetsticky.3c target=fpgetround.3c
@@ -784,6 +796,7 @@
 link path=usr/share/man/man3c/getlogin_r.3c target=getlogin.3c
 link path=usr/share/man/man3c/getmntany.3c target=getmntent.3c
 link path=usr/share/man/man3c/getnetgrent_r.3c target=getnetgrent.3c
+link path=usr/share/man/man3c/get_nprocs_conf.3c target=get_nprocs.3c
 link path=usr/share/man/man3c/getpassphrase.3c target=getpass.3c
 link path=usr/share/man/man3c/getpwent.3c target=getpwnam.3c
 link path=usr/share/man/man3c/getpwent_r.3c target=getpwnam.3c
@@ -915,9 +928,11 @@
 link path=usr/share/man/man3c/memchr.3c target=memory.3c
 link path=usr/share/man/man3c/memcmp.3c target=memory.3c
 link path=usr/share/man/man3c/memcpy.3c target=memory.3c
+link path=usr/share/man/man3c/memmem.3c target=memory.3c
 link path=usr/share/man/man3c/memmove.3c target=memory.3c
 link path=usr/share/man/man3c/memset.3c target=memory.3c
 link path=usr/share/man/man3c/minor.3c target=makedev.3c
+link path=usr/share/man/man3c/mkfifoat.3c target=mkfifo.3c
 link path=usr/share/man/man3c/mkdtemp.3c target=mkstemp.3c
 link path=usr/share/man/man3c/mkfifoat.3c target=mkfifo.3c
 link path=usr/share/man/man3c/mkostemp.3c target=mkstemp.3c
@@ -1159,6 +1174,7 @@
 link path=usr/share/man/man3c/setlogmask.3c target=syslog.3c
 link path=usr/share/man/man3c/setnetgrent.3c target=getnetgrent.3c
 link path=usr/share/man/man3c/setpriority.3c target=getpriority.3c
+link path=usr/share/man/man3c/setprogname.3c target=getprogname.3c
 link path=usr/share/man/man3c/setpwent.3c target=getpwnam.3c
 link path=usr/share/man/man3c/setspent.3c target=getspnam.3c
 link path=usr/share/man/man3c/setstate.3c target=random.3c
@@ -1194,15 +1210,21 @@
 link path=usr/share/man/man3c/stderr.3c target=stdio.3c
 link path=usr/share/man/man3c/stdin.3c target=stdio.3c
 link path=usr/share/man/man3c/stdout.3c target=stdio.3c
+link path=usr/share/man/man3c/stpcpy.3c target=string.3c
+link path=usr/share/man/man3c/stpncpy.3c target=string.3c
 link path=usr/share/man/man3c/strcasecmp.3c target=string.3c
 link path=usr/share/man/man3c/strcasecmp_l.3c target=string.3c
+link path=usr/share/man/man3c/strcasestr.3c target=string.3c
+link path=usr/share/man/man3c/strcasestr_l.3c target=string.3c
 link path=usr/share/man/man3c/strcat.3c target=string.3c
 link path=usr/share/man/man3c/strchr.3c target=string.3c
+link path=usr/share/man/man3c/strchrnul.3c target=string.3c
 link path=usr/share/man/man3c/strcmp.3c target=string.3c
 link path=usr/share/man/man3c/strcoll_l.3c target=strcoll.3c
 link path=usr/share/man/man3c/strcpy.3c target=string.3c
 link path=usr/share/man/man3c/strcspn.3c target=string.3c
 link path=usr/share/man/man3c/strdup.3c target=string.3c
+link path=usr/share/man/man3c/strdupa.3c target=string.3c
 link path=usr/share/man/man3c/strerror_r.3c target=strerror.3c
 link path=usr/share/man/man3c/strfmon_l.3c target=strfmon.3c
 link path=usr/share/man/man3c/strftime_l.3c target=strftime.3c
@@ -1214,7 +1236,10 @@
 link path=usr/share/man/man3c/strncat.3c target=string.3c
 link path=usr/share/man/man3c/strncmp.3c target=string.3c
 link path=usr/share/man/man3c/strncpy.3c target=string.3c
+link path=usr/share/man/man3c/strndup.3c target=string.3c
+link path=usr/share/man/man3c/strndupa.3c target=string.3c
 link path=usr/share/man/man3c/strnlen.3c target=string.3c
+link path=usr/share/man/man3c/strnstr.3c target=string.3c
 link path=usr/share/man/man3c/strpbrk.3c target=string.3c
 link path=usr/share/man/man3c/strptime_l.3c target=strptime.3c
 link path=usr/share/man/man3c/strrchr.3c target=string.3c
--- a/usr/src/uts/common/fs/hsfs/hsfs_vnops.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/fs/hsfs/hsfs_vnops.c	Sun Jan 04 07:19:22 2015 -0800
@@ -1585,8 +1585,7 @@
 
 	/* does not support write */
 	if (rw == S_WRITE) {
-		panic("write attempt on READ ONLY HSFS");
-		/*NOTREACHED*/
+		return (EROFS);
 	}
 
 	if (vp->v_flag & VNOMAP) {
@@ -1798,6 +1797,9 @@
 	if (vp->v_flag & VNOMAP)
 		return (ENOSYS);
 
+	if ((prot & PROT_WRITE) && (flags & MAP_SHARED))
+		return (ENOSYS);
+
 	if (off > HS_MAXFILEOFF || off < 0 ||
 	    (off + len) < 0 || (off + len) > HS_MAXFILEOFF)
 		return (ENXIO);
--- a/usr/src/uts/common/fs/nfs/nfs_auth.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_auth.c	Sun Jan 04 07:19:22 2015 -0800
@@ -783,7 +783,7 @@
 	struct netbuf		*claddr;
 	struct auth_cache	**head;
 	struct auth_cache	*p;
-	struct auth_cache	*prev = NULL;
+	struct auth_cache	*prev;
 	int			access;
 	time_t			refresh;
 
@@ -818,7 +818,9 @@
 
 	rw_enter(&exi->exi_cache_lock, RW_READER);
 	head = &exi->exi_cache[hash(&addr)];
-	for (p = *head; p; p = p->auth_next) {
+retry:
+	prev = NULL;
+	for (p = *head; p != NULL; p = p->auth_next) {
 		if (EQADDR(&addr, &p->auth_addr) && flavor == p->auth_flavor &&
 		    crgetuid(cr) == p->auth_clnt_uid &&
 		    crgetgid(cr) == p->auth_clnt_gid)
@@ -831,44 +833,65 @@
 		 * In a case the client's supplemental groups changed we need
 		 * to discard the auth_cache entry and re-retrieve it.
 		 */
-		mutex_enter(&p->auth_lock);
 		if (p->auth_clnt_ngids != crgetngroups(cr) ||
 		    bcmp(p->auth_clnt_gids, crgetgroups(cr),
 		    p->auth_clnt_ngids * sizeof (gid_t))) {
-			auth_state_t prev_state = p->auth_state;
-
-			p->auth_state = NFS_AUTH_INVALID;
-			mutex_exit(&p->auth_lock);
+			struct auth_cache *next;
 
-			if (prev_state == NFS_AUTH_FRESH) {
+			/*
+			 * To remove the auth_cache entry from exi we need to
+			 * hold the exi_cache_lock for write.  If we do not
+			 * have it yet, we will try to upgrade, or re-lock as a
+			 * last resort.  In a case of re-lock we will retry the
+			 * search for the auth_cache entry because it might
+			 * changed in the meantime.
+			 */
+			ASSERT(RW_LOCK_HELD(&exi->exi_cache_lock));
+			if (rw_read_locked(&exi->exi_cache_lock) != 0) {
 				if (rw_tryupgrade(&exi->exi_cache_lock) == 0) {
-					struct auth_cache *tmp;
-
 					rw_exit(&exi->exi_cache_lock);
 					rw_enter(&exi->exi_cache_lock,
 					    RW_WRITER);
 
-					prev = NULL;
-					for (tmp = *head; tmp != NULL;
-					    tmp = tmp->auth_next) {
-						if (p == tmp)
-							break;
-						prev = p;
-					}
+					goto retry;
 				}
+			}
 
-				if (prev == NULL)
-					exi->exi_cache[hash(&addr)] =
-					    p->auth_next;
-				else
-					prev->auth_next = p->auth_next;
+			/*
+			 * Now, remove the entry from exi and free it, or place
+			 * it at the dead list.
+			 */
+			next = p->auth_next;
+			mutex_enter(&p->auth_lock);
+			if (p->auth_state != NFS_AUTH_FRESH) {
+				p->auth_state = NFS_AUTH_INVALID;
+				mutex_exit(&p->auth_lock);
 
+				mutex_enter(&refreshq_lock);
+				p->auth_next = refreshq_dead_entries;
+				refreshq_dead_entries = p;
+				mutex_exit(&refreshq_lock);
+			} else {
+				mutex_exit(&p->auth_lock);
 				nfsauth_free_node(p);
 			}
 
+			/*
+			 * Finally, disconnect the entry from exi
+			 */
+			if (prev == NULL)
+				*head = next;
+			else
+				prev->auth_next = next;
+
 			goto retrieve;
 		}
-		mutex_exit(&p->auth_lock);
+
+		/*
+		 * If we hold the lock for write, downgrade
+		 */
+		if (rw_read_locked(&exi->exi_cache_lock) == 0)
+			rw_downgrade(&exi->exi_cache_lock);
 
 		nfsauth_cache_hit++;
 
@@ -1084,6 +1107,27 @@
 	int authnone_entry = -1;
 
 	/*
+	 * By default root is mapped to anonymous user.
+	 * This might get overriden later in nfsauth_cache_get().
+	 */
+	if (crgetuid(cr) == 0) {
+		if (uid != NULL)
+			*uid = exi->exi_export.ex_anon;
+		if (gid != NULL)
+			*gid = exi->exi_export.ex_anon;
+	} else {
+		if (uid != NULL)
+			*uid = crgetuid(cr);
+		if (gid != NULL)
+			*gid = crgetgid(cr);
+	}
+
+	if (ngids != NULL)
+		*ngids = 0;
+	if (gids != NULL)
+		*gids = NULL;
+
+	/*
 	 *  Get the nfs flavor number from xprt.
 	 */
 	flavor = (int)(uintptr_t)req->rq_xprt->xp_cookie;
@@ -1119,27 +1163,6 @@
 	}
 
 	/*
-	 * By default root is mapped to anonymous user.
-	 * This might get overriden later in nfsauth_cache_get().
-	 */
-	if (crgetuid(cr) == 0) {
-		if (uid != NULL)
-			*uid = exi->exi_export.ex_anon;
-		if (gid != NULL)
-			*gid = exi->exi_export.ex_anon;
-	} else {
-		if (uid != NULL)
-			*uid = crgetuid(cr);
-		if (gid != NULL)
-			*gid = crgetgid(cr);
-	}
-
-	if (ngids != NULL)
-		*ngids = 0;
-	if (gids != NULL)
-		*gids = NULL;
-
-	/*
 	 * If the flavor is in the ex_secinfo list, but not an explicitly
 	 * shared flavor by the user, it is a result of the nfsv4 server
 	 * namespace setup. We will grant an RO permission similar for
--- a/usr/src/uts/common/fs/vfs.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/fs/vfs.c	Sun Jan 04 07:19:22 2015 -0800
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
 
 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
@@ -1129,6 +1130,7 @@
 	struct pathname	pn, rpn;
 	vsk_anchor_t	*vskap;
 	char fstname[FSTYPSZ];
+	zone_t		*zone;
 
 	/*
 	 * The v_flag value for the mount point vp is permanently set
@@ -1590,9 +1592,24 @@
 	}
 
 	/*
-	 * Serialize with zone creations.
+	 * Serialize with zone state transitions.
+	 * See vfs_list_add; zone mounted into is:
+	 * 	zone_find_by_path(refstr_value(vfsp->vfs_mntpt))
+	 * not the zone doing the mount (curproc->p_zone), but if we're already
+	 * inside a NGZ, then we know what zone we are.
 	 */
-	mount_in_progress();
+	if (INGLOBALZONE(curproc)) {
+		zone = zone_find_by_path(mountpt);
+		ASSERT(zone != NULL);
+	} else {
+		zone = curproc->p_zone;
+		/*
+		 * zone_find_by_path does a hold, so do one here too so that
+		 * we can do a zone_rele after mount_completed.
+		 */
+		zone_hold(zone);
+	}
+	mount_in_progress(zone);
 	/*
 	 * Instantiate (or reinstantiate) the file system.  If appropriate,
 	 * splice it into the file system name space.
@@ -1761,7 +1778,8 @@
 
 		vfs_unlock(vfsp);
 	}
-	mount_completed();
+	mount_completed(zone);
+	zone_rele(zone);
 	if (splice)
 		vn_vfsunlock(vp);
 
--- a/usr/src/uts/common/fs/zfs/arc.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/arc.c	Sun Jan 04 07:19:22 2015 -0800
@@ -111,7 +111,7 @@
  * Note that the majority of the performance stats are manipulated
  * with atomic operations.
  *
- * The L2ARC uses the l2arc_buflist_mtx global mutex for the following:
+ * The L2ARC uses the l2ad_mtx on each vdev for the following:
  *
  *	- L2ARC buflist creation
  *	- L2ARC buflist eviction
@@ -149,13 +149,7 @@
 static kcondvar_t	arc_reclaim_thr_cv;	/* used to signal reclaim thr */
 static uint8_t		arc_thread_exit;
 
-#define	ARC_REDUCE_DNLC_PERCENT	3
-uint_t arc_reduce_dnlc_percent = ARC_REDUCE_DNLC_PERCENT;
-
-typedef enum arc_reclaim_strategy {
-	ARC_RECLAIM_AGGR,		/* Aggressive reclaim strategy */
-	ARC_RECLAIM_CONS		/* Conservative reclaim strategy */
-} arc_reclaim_strategy_t;
+uint_t arc_reduce_dnlc_percent = 3;
 
 /*
  * The number of iterations through arc_evict_*() before we
@@ -170,7 +164,19 @@
 static int		arc_p_min_shift = 4;
 
 /* log2(fraction of arc to reclaim) */
-static int		arc_shrink_shift = 5;
+static int		arc_shrink_shift = 7;
+
+/*
+ * log2(fraction of ARC which must be free to allow growing).
+ * I.e. If there is less than arc_c >> arc_no_grow_shift free memory,
+ * when reading a new block into the ARC, we will evict an equal-sized block
+ * from the ARC.
+ *
+ * This must be less than arc_shrink_shift, so that when we shrink the ARC,
+ * we will still not allow it to grow.
+ */
+int			arc_no_grow_shift = 5;
+
 
 /*
  * minimum lifespan of a prefetch block in clock ticks
@@ -293,9 +299,137 @@
 	kstat_named_t arcstat_c_min;
 	kstat_named_t arcstat_c_max;
 	kstat_named_t arcstat_size;
+	/*
+	 * Number of bytes consumed by internal ARC structures necessary
+	 * for tracking purposes; these structures are not actually
+	 * backed by ARC buffers. This includes arc_buf_hdr_t structures
+	 * (allocated via arc_buf_hdr_t_full and arc_buf_hdr_t_l2only
+	 * caches), and arc_buf_t structures (allocated via arc_buf_t
+	 * cache).
+	 */
 	kstat_named_t arcstat_hdr_size;
+	/*
+	 * Number of bytes consumed by ARC buffers of type equal to
+	 * ARC_BUFC_DATA. This is generally consumed by buffers backing
+	 * on disk user data (e.g. plain file contents).
+	 */
 	kstat_named_t arcstat_data_size;
+	/*
+	 * Number of bytes consumed by ARC buffers of type equal to
+	 * ARC_BUFC_METADATA. This is generally consumed by buffers
+	 * backing on disk data that is used for internal ZFS
+	 * structures (e.g. ZAP, dnode, indirect blocks, etc).
+	 */
+	kstat_named_t arcstat_metadata_size;
+	/*
+	 * Number of bytes consumed by various buffers and structures
+	 * not actually backed with ARC buffers. This includes bonus
+	 * buffers (allocated directly via zio_buf_* functions),
+	 * dmu_buf_impl_t structures (allocated via dmu_buf_impl_t
+	 * cache), and dnode_t structures (allocated via dnode_t cache).
+	 */
 	kstat_named_t arcstat_other_size;
+	/*
+	 * Total number of bytes consumed by ARC buffers residing in the
+	 * arc_anon state. This includes *all* buffers in the arc_anon
+	 * state; e.g. data, metadata, evictable, and unevictable buffers
+	 * are all included in this value.
+	 */
+	kstat_named_t arcstat_anon_size;
+	/*
+	 * Number of bytes consumed by ARC buffers that meet the
+	 * following criteria: backing buffers of type ARC_BUFC_DATA,
+	 * residing in the arc_anon state, and are eligible for eviction
+	 * (e.g. have no outstanding holds on the buffer).
+	 */
+	kstat_named_t arcstat_anon_evictable_data;
+	/*
+	 * Number of bytes consumed by ARC buffers that meet the
+	 * following criteria: backing buffers of type ARC_BUFC_METADATA,
+	 * residing in the arc_anon state, and are eligible for eviction
+	 * (e.g. have no outstanding holds on the buffer).
+	 */
+	kstat_named_t arcstat_anon_evictable_metadata;
+	/*
+	 * Total number of bytes consumed by ARC buffers residing in the
+	 * arc_mru state. This includes *all* buffers in the arc_mru
+	 * state; e.g. data, metadata, evictable, and unevictable buffers
+	 * are all included in this value.
+	 */
+	kstat_named_t arcstat_mru_size;
+	/*
+	 * Number of bytes consumed by ARC buffers that meet the
+	 * following criteria: backing buffers of type ARC_BUFC_DATA,
+	 * residing in the arc_mru state, and are eligible for eviction
+	 * (e.g. have no outstanding holds on the buffer).
+	 */
+	kstat_named_t arcstat_mru_evictable_data;
+	/*
+	 * Number of bytes consumed by ARC buffers that meet the
+	 * following criteria: backing buffers of type ARC_BUFC_METADATA,
+	 * residing in the arc_mru state, and are eligible for eviction
+	 * (e.g. have no outstanding holds on the buffer).
+	 */
+	kstat_named_t arcstat_mru_evictable_metadata;
+	/*
+	 * Total number of bytes that *would have been* consumed by ARC
+	 * buffers in the arc_mru_ghost state. The key thing to note
+	 * here, is the fact that this size doesn't actually indicate
+	 * RAM consumption. The ghost lists only consist of headers and
+	 * don't actually have ARC buffers linked off of these headers.
+	 * Thus, *if* the headers had associated ARC buffers, these
+	 * buffers *would have* consumed this number of bytes.
+	 */
+	kstat_named_t arcstat_mru_ghost_size;
+	/*
+	 * Number of bytes that *would have been* consumed by ARC
+	 * buffers that are eligible for eviction, of type
+	 * ARC_BUFC_DATA, and linked off the arc_mru_ghost state.
+	 */
+	kstat_named_t arcstat_mru_ghost_evictable_data;
+	/*
+	 * Number of bytes that *would have been* consumed by ARC
+	 * buffers that are eligible for eviction, of type
+	 * ARC_BUFC_METADATA, and linked off the arc_mru_ghost state.
+	 */
+	kstat_named_t arcstat_mru_ghost_evictable_metadata;
+	/*
+	 * Total number of bytes consumed by ARC buffers residing in the
+	 * arc_mfu state. This includes *all* buffers in the arc_mfu
+	 * state; e.g. data, metadata, evictable, and unevictable buffers
+	 * are all included in this value.
+	 */
+	kstat_named_t arcstat_mfu_size;
+	/*
+	 * Number of bytes consumed by ARC buffers that are eligible for
+	 * eviction, of type ARC_BUFC_DATA, and reside in the arc_mfu
+	 * state.
+	 */
+	kstat_named_t arcstat_mfu_evictable_data;
+	/*
+	 * Number of bytes consumed by ARC buffers that are eligible for
+	 * eviction, of type ARC_BUFC_METADATA, and reside in the
+	 * arc_mfu state.
+	 */
+	kstat_named_t arcstat_mfu_evictable_metadata;
+	/*
+	 * Total number of bytes that *would have been* consumed by ARC
+	 * buffers in the arc_mfu_ghost state. See the comment above
+	 * arcstat_mru_ghost_size for more details.
+	 */
+	kstat_named_t arcstat_mfu_ghost_size;
+	/*
+	 * Number of bytes that *would have been* consumed by ARC
+	 * buffers that are eligible for eviction, of type
+	 * ARC_BUFC_DATA, and linked off the arc_mfu_ghost state.
+	 */
+	kstat_named_t arcstat_mfu_ghost_evictable_data;
+	/*
+	 * Number of bytes that *would have been* consumed by ARC
+	 * buffers that are eligible for eviction, of type
+	 * ARC_BUFC_METADATA, and linked off the arc_mru_ghost state.
+	 */
+	kstat_named_t arcstat_mfu_ghost_evictable_metadata;
 	kstat_named_t arcstat_l2_hits;
 	kstat_named_t arcstat_l2_misses;
 	kstat_named_t arcstat_l2_feeds;
@@ -308,6 +442,7 @@
 	kstat_named_t arcstat_l2_writes_hdr_miss;
 	kstat_named_t arcstat_l2_evict_lock_retry;
 	kstat_named_t arcstat_l2_evict_reading;
+	kstat_named_t arcstat_l2_evict_l1cached;
 	kstat_named_t arcstat_l2_free_on_write;
 	kstat_named_t arcstat_l2_abort_lowmem;
 	kstat_named_t arcstat_l2_cksum_bad;
@@ -362,7 +497,23 @@
 	{ "size",			KSTAT_DATA_UINT64 },
 	{ "hdr_size",			KSTAT_DATA_UINT64 },
 	{ "data_size",			KSTAT_DATA_UINT64 },
+	{ "metadata_size",		KSTAT_DATA_UINT64 },
 	{ "other_size",			KSTAT_DATA_UINT64 },
+	{ "anon_size",			KSTAT_DATA_UINT64 },
+	{ "anon_evictable_data",	KSTAT_DATA_UINT64 },
+	{ "anon_evictable_metadata",	KSTAT_DATA_UINT64 },
+	{ "mru_size",			KSTAT_DATA_UINT64 },
+	{ "mru_evictable_data",		KSTAT_DATA_UINT64 },
+	{ "mru_evictable_metadata",	KSTAT_DATA_UINT64 },
+	{ "mru_ghost_size",		KSTAT_DATA_UINT64 },
+	{ "mru_ghost_evictable_data",	KSTAT_DATA_UINT64 },
+	{ "mru_ghost_evictable_metadata", KSTAT_DATA_UINT64 },
+	{ "mfu_size",			KSTAT_DATA_UINT64 },
+	{ "mfu_evictable_data",		KSTAT_DATA_UINT64 },
+	{ "mfu_evictable_metadata",	KSTAT_DATA_UINT64 },
+	{ "mfu_ghost_size",		KSTAT_DATA_UINT64 },
+	{ "mfu_ghost_evictable_data",	KSTAT_DATA_UINT64 },
+	{ "mfu_ghost_evictable_metadata", KSTAT_DATA_UINT64 },
 	{ "l2_hits",			KSTAT_DATA_UINT64 },
 	{ "l2_misses",			KSTAT_DATA_UINT64 },
 	{ "l2_feeds",			KSTAT_DATA_UINT64 },
@@ -375,6 +526,7 @@
 	{ "l2_writes_hdr_miss",		KSTAT_DATA_UINT64 },
 	{ "l2_evict_lock_retry",	KSTAT_DATA_UINT64 },
 	{ "l2_evict_reading",		KSTAT_DATA_UINT64 },
+	{ "l2_evict_l1cached",		KSTAT_DATA_UINT64 },
 	{ "l2_free_on_write",		KSTAT_DATA_UINT64 },
 	{ "l2_abort_lowmem",		KSTAT_DATA_UINT64 },
 	{ "l2_cksum_bad",		KSTAT_DATA_UINT64 },
@@ -466,8 +618,6 @@
 static uint64_t		arc_tempreserve;
 static uint64_t		arc_loaned_bytes;
 
-typedef struct l2arc_buf_hdr l2arc_buf_hdr_t;
-
 typedef struct arc_callback arc_callback_t;
 
 struct arc_callback {
@@ -488,29 +638,53 @@
 	arc_buf_t	*awcb_buf;
 };
 
-struct arc_buf_hdr {
-	/* protected by hash lock */
-	dva_t			b_dva;
-	uint64_t		b_birth;
-	uint64_t		b_cksum0;
-
+/*
+ * ARC buffers are separated into multiple structs as a memory saving measure:
+ *   - Common fields struct, always defined, and embedded within it:
+ *       - L2-only fields, always allocated but undefined when not in L2ARC
+ *       - L1-only fields, only allocated when in L1ARC
+ *
+ *           Buffer in L1                     Buffer only in L2
+ *    +------------------------+          +------------------------+
+ *    | arc_buf_hdr_t          |          | arc_buf_hdr_t          |
+ *    |                        |          |                        |
+ *    |                        |          |                        |
+ *    |                        |          |                        |
+ *    +------------------------+          +------------------------+
+ *    | l2arc_buf_hdr_t        |          | l2arc_buf_hdr_t        |
+ *    | (undefined if L1-only) |          |                        |
+ *    +------------------------+          +------------------------+
+ *    | l1arc_buf_hdr_t        |
+ *    |                        |
+ *    |                        |
+ *    |                        |
+ *    |                        |
+ *    +------------------------+
+ *
+ * Because it's possible for the L2ARC to become extremely large, we can wind
+ * up eating a lot of memory in L2ARC buffer headers, so the size of a header
+ * is minimized by only allocating the fields necessary for an L1-cached buffer
+ * when a header is actually in the L1 cache. The sub-headers (l1arc_buf_hdr and
+ * l2arc_buf_hdr) are embedded rather than allocated separately to save a couple
+ * words in pointers. arc_hdr_realloc() is used to switch a header between
+ * these two allocation states.
+ */
+typedef struct l1arc_buf_hdr {
 	kmutex_t		b_freeze_lock;
-	zio_cksum_t		*b_freeze_cksum;
+#ifdef ZFS_DEBUG
+	/*
+	 * used for debugging wtih kmem_flags - by allocating and freeing
+	 * b_thawed when the buffer is thawed, we get a record of the stack
+	 * trace that thawed it.
+	 */
 	void			*b_thawed;
-
-	arc_buf_hdr_t		*b_hash_next;
+#endif
+
 	arc_buf_t		*b_buf;
-	arc_flags_t		b_flags;
 	uint32_t		b_datacnt;
-
-	arc_callback_t		*b_acb;
+	/* for waiting on writes to complete */
 	kcondvar_t		b_cv;
 
-	/* immutable */
-	arc_buf_contents_t	b_type;
-	uint64_t		b_size;
-	uint64_t		b_spa;
-
 	/* protected by arc state mutex */
 	arc_state_t		*b_state;
 	list_node_t		b_arc_node;
@@ -521,8 +695,46 @@
 	/* self protecting */
 	refcount_t		b_refcnt;
 
-	l2arc_buf_hdr_t		*b_l2hdr;
+	arc_callback_t		*b_acb;
+	/* temporary buffer holder for in-flight compressed data */
+	void			*b_tmp_cdata;
+} l1arc_buf_hdr_t;
+
+typedef struct l2arc_dev l2arc_dev_t;
+
+typedef struct l2arc_buf_hdr {
+	/* protected by arc_buf_hdr mutex */
+	l2arc_dev_t		*b_dev;		/* L2ARC device */
+	uint64_t		b_daddr;	/* disk address, offset byte */
+	/* real alloc'd buffer size depending on b_compress applied */
+	int32_t			b_asize;
+
 	list_node_t		b_l2node;
+} l2arc_buf_hdr_t;
+
+struct arc_buf_hdr {
+	/* protected by hash lock */
+	dva_t			b_dva;
+	uint64_t		b_birth;
+	/*
+	 * Even though this checksum is only set/verified when a buffer is in
+	 * the L1 cache, it needs to be in the set of common fields because it
+	 * must be preserved from the time before a buffer is written out to
+	 * L2ARC until after it is read back in.
+	 */
+	zio_cksum_t		*b_freeze_cksum;
+
+	arc_buf_hdr_t		*b_hash_next;
+	arc_flags_t		b_flags;
+
+	/* immutable */
+	int32_t			b_size;
+	uint64_t		b_spa;
+
+	/* L2ARC fields. Undefined when not in L2ARC. */
+	l2arc_buf_hdr_t		b_l2hdr;
+	/* L1ARC fields. Undefined when in l2arc_only state */
+	l1arc_buf_hdr_t		b_l1hdr;
 };
 
 static arc_buf_t *arc_eviction_list;
@@ -539,22 +751,38 @@
 #define	HDR_PREFETCH(hdr)	((hdr)->b_flags & ARC_FLAG_PREFETCH)
 #define	HDR_FREED_IN_READ(hdr)	((hdr)->b_flags & ARC_FLAG_FREED_IN_READ)
 #define	HDR_BUF_AVAILABLE(hdr)	((hdr)->b_flags & ARC_FLAG_BUF_AVAILABLE)
-#define	HDR_FREE_IN_PROGRESS(hdr)	\
-	((hdr)->b_flags & ARC_FLAG_FREE_IN_PROGRESS)
+
 #define	HDR_L2CACHE(hdr)	((hdr)->b_flags & ARC_FLAG_L2CACHE)
+#define	HDR_L2COMPRESS(hdr)	((hdr)->b_flags & ARC_FLAG_L2COMPRESS)
 #define	HDR_L2_READING(hdr)	\
-	((hdr)->b_flags & ARC_FLAG_IO_IN_PROGRESS &&	\
-	    (hdr)->b_l2hdr != NULL)
+	    (((hdr)->b_flags & ARC_FLAG_IO_IN_PROGRESS) &&	\
+	    ((hdr)->b_flags & ARC_FLAG_HAS_L2HDR))
 #define	HDR_L2_WRITING(hdr)	((hdr)->b_flags & ARC_FLAG_L2_WRITING)
 #define	HDR_L2_EVICTED(hdr)	((hdr)->b_flags & ARC_FLAG_L2_EVICTED)
 #define	HDR_L2_WRITE_HEAD(hdr)	((hdr)->b_flags & ARC_FLAG_L2_WRITE_HEAD)
 
+#define	HDR_ISTYPE_METADATA(hdr)	\
+	    ((hdr)->b_flags & ARC_FLAG_BUFC_METADATA)
+#define	HDR_ISTYPE_DATA(hdr)	(!HDR_ISTYPE_METADATA(hdr))
+
+#define	HDR_HAS_L1HDR(hdr)	((hdr)->b_flags & ARC_FLAG_HAS_L1HDR)
+#define	HDR_HAS_L2HDR(hdr)	((hdr)->b_flags & ARC_FLAG_HAS_L2HDR)
+
+/* For storing compression mode in b_flags */
+#define	HDR_COMPRESS_OFFSET	24
+#define	HDR_COMPRESS_NBITS	7
+
+#define	HDR_GET_COMPRESS(hdr)	((enum zio_compress)BF32_GET(hdr->b_flags, \
+	    HDR_COMPRESS_OFFSET, HDR_COMPRESS_NBITS))
+#define	HDR_SET_COMPRESS(hdr, cmp) BF32_SET(hdr->b_flags, \
+	    HDR_COMPRESS_OFFSET, HDR_COMPRESS_NBITS, (cmp))
+
 /*
  * Other sizes
  */
 
-#define	HDR_SIZE ((int64_t)sizeof (arc_buf_hdr_t))
-#define	L2HDR_SIZE ((int64_t)sizeof (l2arc_buf_hdr_t))
+#define	HDR_FULL_SIZE ((int64_t)sizeof (arc_buf_hdr_t))
+#define	HDR_L2ONLY_SIZE ((int64_t)offsetof(arc_buf_hdr_t, b_l1hdr))
 
 /*
  * Hash table routines
@@ -618,7 +846,7 @@
 /*
  * L2ARC Internals
  */
-typedef struct l2arc_dev {
+struct l2arc_dev {
 	vdev_t			*l2ad_vdev;	/* vdev */
 	spa_t			*l2ad_spa;	/* spa */
 	uint64_t		l2ad_hand;	/* next write location */
@@ -627,15 +855,15 @@
 	uint64_t		l2ad_evict;	/* last addr eviction reached */
 	boolean_t		l2ad_first;	/* first sweep through */
 	boolean_t		l2ad_writing;	/* currently writing */
-	list_t			*l2ad_buflist;	/* buffer list */
+	kmutex_t		l2ad_mtx;	/* lock for buffer list */
+	list_t			l2ad_buflist;	/* buffer list */
 	list_node_t		l2ad_node;	/* device list node */
-} l2arc_dev_t;
+};
 
 static list_t L2ARC_dev_list;			/* device list */
 static list_t *l2arc_dev_list;			/* device list pointer */
 static kmutex_t l2arc_dev_mtx;			/* device list mutex */
 static l2arc_dev_t *l2arc_dev_last;		/* last device used */
-static kmutex_t l2arc_buflist_mtx;		/* mutex for all buflists */
 static list_t L2ARC_free_on_write;		/* free after write buf list */
 static list_t *l2arc_free_on_write;		/* free after write list ptr */
 static kmutex_t l2arc_free_on_write_mtx;	/* mutex for list */
@@ -655,18 +883,6 @@
 	arc_buf_hdr_t	*l2wcb_head;		/* head of write buflist */
 } l2arc_write_callback_t;
 
-struct l2arc_buf_hdr {
-	/* protected by arc_buf_hdr  mutex */
-	l2arc_dev_t		*b_dev;		/* L2ARC device */
-	uint64_t		b_daddr;	/* disk address, offset byte */
-	/* compression applied to buffer data */
-	enum zio_compress	b_compress;
-	/* real alloc'd buffer size depending on b_compress applied */
-	int			b_asize;
-	/* temporary buffer holder for in-flight compressed data */
-	void			*b_tmp_cdata;
-};
-
 typedef struct l2arc_data_free {
 	/* protected by l2arc_free_on_write_mtx */
 	void		*l2df_data;
@@ -685,12 +901,13 @@
 static void arc_evict_ghost(arc_state_t *, uint64_t, int64_t);
 static void arc_buf_watch(arc_buf_t *);
 
+static arc_buf_contents_t arc_buf_type(arc_buf_hdr_t *);
+static uint32_t arc_bufc_to_flags(arc_buf_contents_t);
+
 static boolean_t l2arc_write_eligible(uint64_t, arc_buf_hdr_t *);
 static void l2arc_read_done(zio_t *);
-static void l2arc_hdr_stat_add(void);
-static void l2arc_hdr_stat_remove(void);
-
-static boolean_t l2arc_compress_buf(l2arc_buf_hdr_t *);
+
+static boolean_t l2arc_compress_buf(arc_buf_hdr_t *);
 static void l2arc_decompress_zio(zio_t *, arc_buf_hdr_t *, enum zio_compress);
 static void l2arc_release_cdata_buf(arc_buf_hdr_t *);
 
@@ -713,8 +930,7 @@
 
 #define	BUF_EMPTY(buf)						\
 	((buf)->b_dva.dva_word[0] == 0 &&			\
-	(buf)->b_dva.dva_word[1] == 0 &&			\
-	(buf)->b_cksum0 == 0)
+	(buf)->b_dva.dva_word[1] == 0)
 
 #define	BUF_EQUAL(spa, dva, birth, buf)				\
 	((buf)->b_dva.dva_word[0] == (dva)->dva_word[0]) &&	\
@@ -727,7 +943,6 @@
 	hdr->b_dva.dva_word[0] = 0;
 	hdr->b_dva.dva_word[1] = 0;
 	hdr->b_birth = 0;
-	hdr->b_cksum0 = 0;
 }
 
 static arc_buf_hdr_t *
@@ -757,6 +972,7 @@
  * equal to elem in the hash table, then the already existing element
  * will be returned and the new element will not be inserted.
  * Otherwise returns NULL.
+ * If lockp == NULL, the caller is assumed to already hold the hash lock.
  */
 static arc_buf_hdr_t *
 buf_hash_insert(arc_buf_hdr_t *hdr, kmutex_t **lockp)
@@ -769,8 +985,14 @@
 	ASSERT(!DVA_IS_EMPTY(&hdr->b_dva));
 	ASSERT(hdr->b_birth != 0);
 	ASSERT(!HDR_IN_HASH_TABLE(hdr));
-	*lockp = hash_lock;
-	mutex_enter(hash_lock);
+
+	if (lockp != NULL) {
+		*lockp = hash_lock;
+		mutex_enter(hash_lock);
+	} else {
+		ASSERT(MUTEX_HELD(hash_lock));
+	}
+
 	for (fhdr = buf_hash_table.ht_table[idx], i = 0; fhdr != NULL;
 	    fhdr = fhdr->b_hash_next, i++) {
 		if (BUF_EQUAL(hdr->b_spa, &hdr->b_dva, hdr->b_birth, fhdr))
@@ -825,7 +1047,8 @@
 /*
  * Global data structures and functions for the buf kmem cache.
  */
-static kmem_cache_t *hdr_cache;
+static kmem_cache_t *hdr_full_cache;
+static kmem_cache_t *hdr_l2only_cache;
 static kmem_cache_t *buf_cache;
 
 static void
@@ -837,7 +1060,8 @@
 	    (buf_hash_table.ht_mask + 1) * sizeof (void *));
 	for (i = 0; i < BUF_LOCKS; i++)
 		mutex_destroy(&buf_hash_table.ht_locks[i].ht_lock);
-	kmem_cache_destroy(hdr_cache);
+	kmem_cache_destroy(hdr_full_cache);
+	kmem_cache_destroy(hdr_l2only_cache);
 	kmem_cache_destroy(buf_cache);
 }
 
@@ -847,15 +1071,27 @@
  */
 /* ARGSUSED */
 static int
-hdr_cons(void *vbuf, void *unused, int kmflag)
+hdr_full_cons(void *vbuf, void *unused, int kmflag)
 {
 	arc_buf_hdr_t *hdr = vbuf;
 
-	bzero(hdr, sizeof (arc_buf_hdr_t));
-	refcount_create(&hdr->b_refcnt);
-	cv_init(&hdr->b_cv, NULL, CV_DEFAULT, NULL);
-	mutex_init(&hdr->b_freeze_lock, NULL, MUTEX_DEFAULT, NULL);
-	arc_space_consume(sizeof (arc_buf_hdr_t), ARC_SPACE_HDRS);
+	bzero(hdr, HDR_FULL_SIZE);
+	cv_init(&hdr->b_l1hdr.b_cv, NULL, CV_DEFAULT, NULL);
+	refcount_create(&hdr->b_l1hdr.b_refcnt);
+	mutex_init(&hdr->b_l1hdr.b_freeze_lock, NULL, MUTEX_DEFAULT, NULL);
+	arc_space_consume(HDR_FULL_SIZE, ARC_SPACE_HDRS);
+
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+hdr_l2only_cons(void *vbuf, void *unused, int kmflag)
+{
+	arc_buf_hdr_t *hdr = vbuf;
+
+	bzero(hdr, HDR_L2ONLY_SIZE);
+	arc_space_consume(HDR_L2ONLY_SIZE, ARC_SPACE_L2HDRS);
 
 	return (0);
 }
@@ -879,15 +1115,25 @@
  */
 /* ARGSUSED */
 static void
-hdr_dest(void *vbuf, void *unused)
+hdr_full_dest(void *vbuf, void *unused)
 {
 	arc_buf_hdr_t *hdr = vbuf;
 
 	ASSERT(BUF_EMPTY(hdr));
-	refcount_destroy(&hdr->b_refcnt);
-	cv_destroy(&hdr->b_cv);
-	mutex_destroy(&hdr->b_freeze_lock);
-	arc_space_return(sizeof (arc_buf_hdr_t), ARC_SPACE_HDRS);
+	cv_destroy(&hdr->b_l1hdr.b_cv);
+	refcount_destroy(&hdr->b_l1hdr.b_refcnt);
+	mutex_destroy(&hdr->b_l1hdr.b_freeze_lock);
+	arc_space_return(HDR_FULL_SIZE, ARC_SPACE_HDRS);
+}
+
+/* ARGSUSED */
+static void
+hdr_l2only_dest(void *vbuf, void *unused)
+{
+	arc_buf_hdr_t *hdr = vbuf;
+
+	ASSERT(BUF_EMPTY(hdr));
+	arc_space_return(HDR_L2ONLY_SIZE, ARC_SPACE_L2HDRS);
 }
 
 /* ARGSUSED */
@@ -941,8 +1187,11 @@
 		goto retry;
 	}
 
-	hdr_cache = kmem_cache_create("arc_buf_hdr_t", sizeof (arc_buf_hdr_t),
-	    0, hdr_cons, hdr_dest, hdr_recl, NULL, NULL, 0);
+	hdr_full_cache = kmem_cache_create("arc_buf_hdr_t_full", HDR_FULL_SIZE,
+	    0, hdr_full_cons, hdr_full_dest, hdr_recl, NULL, NULL, 0);
+	hdr_l2only_cache = kmem_cache_create("arc_buf_hdr_t_l2only",
+	    HDR_L2ONLY_SIZE, 0, hdr_l2only_cons, hdr_l2only_dest, hdr_recl,
+	    NULL, NULL, 0);
 	buf_cache = kmem_cache_create("arc_buf_t", sizeof (arc_buf_t),
 	    0, buf_cons, buf_dest, NULL, NULL, NULL, 0);
 
@@ -956,6 +1205,81 @@
 	}
 }
 
+/*
+ * Transition between the two allocation states for the arc_buf_hdr struct.
+ * The arc_buf_hdr struct can be allocated with (hdr_full_cache) or without
+ * (hdr_l2only_cache) the fields necessary for the L1 cache - the smaller
+ * version is used when a cache buffer is only in the L2ARC in order to reduce
+ * memory usage.
+ */
+static arc_buf_hdr_t *
+arc_hdr_realloc(arc_buf_hdr_t *hdr, kmem_cache_t *old, kmem_cache_t *new)
+{
+	ASSERT(HDR_HAS_L2HDR(hdr));
+
+	arc_buf_hdr_t *nhdr;
+	l2arc_dev_t *dev = hdr->b_l2hdr.b_dev;
+
+	ASSERT((old == hdr_full_cache && new == hdr_l2only_cache) ||
+	    (old == hdr_l2only_cache && new == hdr_full_cache));
+
+	nhdr = kmem_cache_alloc(new, KM_PUSHPAGE);
+
+	ASSERT(MUTEX_HELD(HDR_LOCK(hdr)));
+	buf_hash_remove(hdr);
+
+	bcopy(hdr, nhdr, HDR_L2ONLY_SIZE);
+	if (new == hdr_full_cache) {
+		nhdr->b_flags |= ARC_FLAG_HAS_L1HDR;
+		/*
+		 * arc_access and arc_change_state need to be aware that a
+		 * header has just come out of L2ARC, so we set its state to
+		 * l2c_only even though it's about to change.
+		 */
+		nhdr->b_l1hdr.b_state = arc_l2c_only;
+	} else {
+		ASSERT(hdr->b_l1hdr.b_buf == NULL);
+		ASSERT0(hdr->b_l1hdr.b_datacnt);
+		ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node));
+		/*
+		 * We might be removing the L1hdr of a buffer which was just
+		 * written out to L2ARC. If such a buffer is compressed then we
+		 * need to free its b_tmp_cdata before destroying the header.
+		 */
+		if (hdr->b_l1hdr.b_tmp_cdata != NULL &&
+		    HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_OFF)
+			l2arc_release_cdata_buf(hdr);
+		nhdr->b_flags &= ~ARC_FLAG_HAS_L1HDR;
+	}
+	/*
+	 * The header has been reallocated so we need to re-insert it into any
+	 * lists it was on.
+	 */
+	(void) buf_hash_insert(nhdr, NULL);
+
+	ASSERT(list_link_active(&hdr->b_l2hdr.b_l2node));
+
+	mutex_enter(&dev->l2ad_mtx);
+
+	/*
+	 * We must place the realloc'ed header back into the list at
+	 * the same spot. Otherwise, if it's placed earlier in the list,
+	 * l2arc_write_buffers() could find it during the function's
+	 * write phase, and try to write it out to the l2arc.
+	 */
+	list_insert_after(&dev->l2ad_buflist, hdr, nhdr);
+	list_remove(&dev->l2ad_buflist, hdr);
+
+	mutex_exit(&dev->l2ad_mtx);
+
+	buf_discard_identity(hdr);
+	hdr->b_freeze_cksum = NULL;
+	kmem_cache_free(old, hdr);
+
+	return (nhdr);
+}
+
+
 #define	ARC_MINTIME	(hz>>4) /* 62 ms */
 
 static void
@@ -966,16 +1290,15 @@
 	if (!(zfs_flags & ZFS_DEBUG_MODIFY))
 		return;
 
-	mutex_enter(&buf->b_hdr->b_freeze_lock);
-	if (buf->b_hdr->b_freeze_cksum == NULL ||
-	    (buf->b_hdr->b_flags & ARC_FLAG_IO_ERROR)) {
-		mutex_exit(&buf->b_hdr->b_freeze_lock);
+	mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock);
+	if (buf->b_hdr->b_freeze_cksum == NULL || HDR_IO_ERROR(buf->b_hdr)) {
+		mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 		return;
 	}
 	fletcher_2_native(buf->b_data, buf->b_hdr->b_size, &zc);
 	if (!ZIO_CHECKSUM_EQUAL(*buf->b_hdr->b_freeze_cksum, zc))
 		panic("buffer modified while frozen!");
-	mutex_exit(&buf->b_hdr->b_freeze_lock);
+	mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 }
 
 static int
@@ -984,10 +1307,10 @@
 	zio_cksum_t zc;
 	int equal;
 
-	mutex_enter(&buf->b_hdr->b_freeze_lock);
+	mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 	fletcher_2_native(buf->b_data, buf->b_hdr->b_size, &zc);
 	equal = ZIO_CHECKSUM_EQUAL(*buf->b_hdr->b_freeze_cksum, zc);
-	mutex_exit(&buf->b_hdr->b_freeze_lock);
+	mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 
 	return (equal);
 }
@@ -998,15 +1321,15 @@
 	if (!force && !(zfs_flags & ZFS_DEBUG_MODIFY))
 		return;
 
-	mutex_enter(&buf->b_hdr->b_freeze_lock);
+	mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 	if (buf->b_hdr->b_freeze_cksum != NULL) {
-		mutex_exit(&buf->b_hdr->b_freeze_lock);
+		mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 		return;
 	}
 	buf->b_hdr->b_freeze_cksum = kmem_alloc(sizeof (zio_cksum_t), KM_SLEEP);
 	fletcher_2_native(buf->b_data, buf->b_hdr->b_size,
 	    buf->b_hdr->b_freeze_cksum);
-	mutex_exit(&buf->b_hdr->b_freeze_lock);
+	mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 	arc_buf_watch(buf);
 }
 
@@ -1053,30 +1376,58 @@
 #endif
 }
 
+static arc_buf_contents_t
+arc_buf_type(arc_buf_hdr_t *hdr)
+{
+	if (HDR_ISTYPE_METADATA(hdr)) {
+		return (ARC_BUFC_METADATA);
+	} else {
+		return (ARC_BUFC_DATA);
+	}
+}
+
+static uint32_t
+arc_bufc_to_flags(arc_buf_contents_t type)
+{
+	switch (type) {
+	case ARC_BUFC_DATA:
+		/* metadata field is 0 if buffer contains normal data */
+		return (0);
+	case ARC_BUFC_METADATA:
+		return (ARC_FLAG_BUFC_METADATA);
+	default:
+		break;
+	}
+	panic("undefined ARC buffer type!");
+	return ((uint32_t)-1);
+}
+
 void
 arc_buf_thaw(arc_buf_t *buf)
 {
 	if (zfs_flags & ZFS_DEBUG_MODIFY) {
-		if (buf->b_hdr->b_state != arc_anon)
+		if (buf->b_hdr->b_l1hdr.b_state != arc_anon)
 			panic("modifying non-anon buffer!");
-		if (buf->b_hdr->b_flags & ARC_FLAG_IO_IN_PROGRESS)
+		if (HDR_IO_IN_PROGRESS(buf->b_hdr))
 			panic("modifying buffer while i/o in progress!");
 		arc_cksum_verify(buf);
 	}
 
-	mutex_enter(&buf->b_hdr->b_freeze_lock);
+	mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 	if (buf->b_hdr->b_freeze_cksum != NULL) {
 		kmem_free(buf->b_hdr->b_freeze_cksum, sizeof (zio_cksum_t));
 		buf->b_hdr->b_freeze_cksum = NULL;
 	}
 
+#ifdef ZFS_DEBUG
 	if (zfs_flags & ZFS_DEBUG_MODIFY) {
-		if (buf->b_hdr->b_thawed)
-			kmem_free(buf->b_hdr->b_thawed, 1);
-		buf->b_hdr->b_thawed = kmem_alloc(1, KM_SLEEP);
+		if (buf->b_hdr->b_l1hdr.b_thawed != NULL)
+			kmem_free(buf->b_hdr->b_l1hdr.b_thawed, 1);
+		buf->b_hdr->b_l1hdr.b_thawed = kmem_alloc(1, KM_SLEEP);
 	}
-
-	mutex_exit(&buf->b_hdr->b_freeze_lock);
+#endif
+
+	mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock);
 
 	arc_buf_unwatch(buf);
 }
@@ -1093,7 +1444,7 @@
 	mutex_enter(hash_lock);
 
 	ASSERT(buf->b_hdr->b_freeze_cksum != NULL ||
-	    buf->b_hdr->b_state == arc_anon);
+	    buf->b_hdr->b_l1hdr.b_state == arc_anon);
 	arc_cksum_compute(buf, B_FALSE);
 	mutex_exit(hash_lock);
 
@@ -1102,30 +1453,34 @@
 static void
 add_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, void *tag)
 {
+	ASSERT(HDR_HAS_L1HDR(hdr));
 	ASSERT(MUTEX_HELD(hash_lock));
-
-	if ((refcount_add(&hdr->b_refcnt, tag) == 1) &&
-	    (hdr->b_state != arc_anon)) {
-		uint64_t delta = hdr->b_size * hdr->b_datacnt;
-		list_t *list = &hdr->b_state->arcs_list[hdr->b_type];
-		uint64_t *size = &hdr->b_state->arcs_lsize[hdr->b_type];
-
-		ASSERT(!MUTEX_HELD(&hdr->b_state->arcs_mtx));
-		mutex_enter(&hdr->b_state->arcs_mtx);
-		ASSERT(list_link_active(&hdr->b_arc_node));
-		list_remove(list, hdr);
-		if (GHOST_STATE(hdr->b_state)) {
-			ASSERT0(hdr->b_datacnt);
-			ASSERT3P(hdr->b_buf, ==, NULL);
-			delta = hdr->b_size;
+	arc_state_t *state = hdr->b_l1hdr.b_state;
+
+	if ((refcount_add(&hdr->b_l1hdr.b_refcnt, tag) == 1) &&
+	    (state != arc_anon)) {
+		/* We don't use the L2-only state list. */
+		if (state != arc_l2c_only) {
+			uint64_t delta = hdr->b_size * hdr->b_l1hdr.b_datacnt;
+			list_t *list = &state->arcs_list[arc_buf_type(hdr)];
+			uint64_t *size = &state->arcs_lsize[arc_buf_type(hdr)];
+
+			ASSERT(!MUTEX_HELD(&state->arcs_mtx));
+			mutex_enter(&state->arcs_mtx);
+			ASSERT(list_link_active(&hdr->b_l1hdr.b_arc_node));
+			list_remove(list, hdr);
+			if (GHOST_STATE(state)) {
+				ASSERT0(hdr->b_l1hdr.b_datacnt);
+				ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
+				delta = hdr->b_size;
+			}
+			ASSERT(delta > 0);
+			ASSERT3U(*size, >=, delta);
+			atomic_add_64(size, -delta);
+			mutex_exit(&state->arcs_mtx);
 		}
-		ASSERT(delta > 0);
-		ASSERT3U(*size, >=, delta);
-		atomic_add_64(size, -delta);
-		mutex_exit(&hdr->b_state->arcs_mtx);
 		/* remove the prefetch flag if we get a reference */
-		if (hdr->b_flags & ARC_FLAG_PREFETCH)
-			hdr->b_flags &= ~ARC_FLAG_PREFETCH;
+		hdr->b_flags &= ~ARC_FLAG_PREFETCH;
 	}
 }
 
@@ -1133,21 +1488,27 @@
 remove_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, void *tag)
 {
 	int cnt;
-	arc_state_t *state = hdr->b_state;
-
+	arc_state_t *state = hdr->b_l1hdr.b_state;
+
+	ASSERT(HDR_HAS_L1HDR(hdr));
 	ASSERT(state == arc_anon || MUTEX_HELD(hash_lock));
 	ASSERT(!GHOST_STATE(state));
 
-	if (((cnt = refcount_remove(&hdr->b_refcnt, tag)) == 0) &&
+	/*
+	 * arc_l2c_only counts as a ghost state so we don't need to explicitly
+	 * check to prevent usage of the arc_l2c_only list.
+	 */
+	if (((cnt = refcount_remove(&hdr->b_l1hdr.b_refcnt, tag)) == 0) &&
 	    (state != arc_anon)) {
-		uint64_t *size = &state->arcs_lsize[hdr->b_type];
+		uint64_t *size = &state->arcs_lsize[arc_buf_type(hdr)];
 
 		ASSERT(!MUTEX_HELD(&state->arcs_mtx));
 		mutex_enter(&state->arcs_mtx);
-		ASSERT(!list_link_active(&hdr->b_arc_node));
-		list_insert_head(&state->arcs_list[hdr->b_type], hdr);
-		ASSERT(hdr->b_datacnt > 0);
-		atomic_add_64(size, hdr->b_size * hdr->b_datacnt);
+		ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node));
+		list_insert_head(&state->arcs_list[arc_buf_type(hdr)], hdr);
+		ASSERT(hdr->b_l1hdr.b_datacnt > 0);
+		atomic_add_64(size, hdr->b_size *
+		    hdr->b_l1hdr.b_datacnt);
 		mutex_exit(&state->arcs_mtx);
 	}
 	return (cnt);
@@ -1161,40 +1522,60 @@
 arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
     kmutex_t *hash_lock)
 {
-	arc_state_t *old_state = hdr->b_state;
-	int64_t refcnt = refcount_count(&hdr->b_refcnt);
+	arc_state_t *old_state;
+	int64_t refcnt;
+	uint32_t datacnt;
 	uint64_t from_delta, to_delta;
+	arc_buf_contents_t buftype = arc_buf_type(hdr);
+
+	/*
+	 * We almost always have an L1 hdr here, since we call arc_hdr_realloc()
+	 * in arc_read() when bringing a buffer out of the L2ARC.  However, the
+	 * L1 hdr doesn't always exist when we change state to arc_anon before
+	 * destroying a header, in which case reallocating to add the L1 hdr is
+	 * pointless.
+	 */
+	if (HDR_HAS_L1HDR(hdr)) {
+		old_state = hdr->b_l1hdr.b_state;
+		refcnt = refcount_count(&hdr->b_l1hdr.b_refcnt);
+		datacnt = hdr->b_l1hdr.b_datacnt;
+	} else {
+		old_state = arc_l2c_only;
+		refcnt = 0;
+		datacnt = 0;
+	}
 
 	ASSERT(MUTEX_HELD(hash_lock));
 	ASSERT3P(new_state, !=, old_state);
-	ASSERT(refcnt == 0 || hdr->b_datacnt > 0);
-	ASSERT(hdr->b_datacnt == 0 || !GHOST_STATE(new_state));
-	ASSERT(hdr->b_datacnt <= 1 || old_state != arc_anon);
-
-	from_delta = to_delta = hdr->b_datacnt * hdr->b_size;
+	ASSERT(refcnt == 0 || datacnt > 0);
+	ASSERT(!GHOST_STATE(new_state) || datacnt == 0);
+	ASSERT(old_state != arc_anon || datacnt <= 1);
+
+	from_delta = to_delta = datacnt * hdr->b_size;
 
 	/*
 	 * If this buffer is evictable, transfer it from the
 	 * old state list to the new state list.
 	 */
 	if (refcnt == 0) {
-		if (old_state != arc_anon) {
+		if (old_state != arc_anon && old_state != arc_l2c_only) {
 			int use_mutex = !MUTEX_HELD(&old_state->arcs_mtx);
-			uint64_t *size = &old_state->arcs_lsize[hdr->b_type];
+			uint64_t *size = &old_state->arcs_lsize[buftype];
 
 			if (use_mutex)
 				mutex_enter(&old_state->arcs_mtx);
 
-			ASSERT(list_link_active(&hdr->b_arc_node));
-			list_remove(&old_state->arcs_list[hdr->b_type], hdr);
+			ASSERT(HDR_HAS_L1HDR(hdr));
+			ASSERT(list_link_active(&hdr->b_l1hdr.b_arc_node));
+			list_remove(&old_state->arcs_list[buftype], hdr);
 
 			/*
 			 * If prefetching out of the ghost cache,
 			 * we will have a non-zero datacnt.
 			 */
-			if (GHOST_STATE(old_state) && hdr->b_datacnt == 0) {
+			if (GHOST_STATE(old_state) && datacnt == 0) {
 				/* ghost elements have a ghost size */
-				ASSERT(hdr->b_buf == NULL);
+				ASSERT(hdr->b_l1hdr.b_buf == NULL);
 				from_delta = hdr->b_size;
 			}
 			ASSERT3U(*size, >=, from_delta);
@@ -1203,20 +1584,26 @@
 			if (use_mutex)
 				mutex_exit(&old_state->arcs_mtx);
 		}
-		if (new_state != arc_anon) {
+		if (new_state != arc_anon && new_state != arc_l2c_only) {
 			int use_mutex = !MUTEX_HELD(&new_state->arcs_mtx);
-			uint64_t *size = &new_state->arcs_lsize[hdr->b_type];
-
+			uint64_t *size = &new_state->arcs_lsize[buftype];
+
+			/*
+			 * An L1 header always exists here, since if we're
+			 * moving to some L1-cached state (i.e. not l2c_only or
+			 * anonymous), we realloc the header to add an L1hdr
+			 * beforehand.
+			 */
+			ASSERT(HDR_HAS_L1HDR(hdr));
 			if (use_mutex)
 				mutex_enter(&new_state->arcs_mtx);
 
-			list_insert_head(&new_state->arcs_list[hdr->b_type],
-			    hdr);
+			list_insert_head(&new_state->arcs_list[buftype], hdr);
 
 			/* ghost elements have a ghost size */
 			if (GHOST_STATE(new_state)) {
-				ASSERT(hdr->b_datacnt == 0);
-				ASSERT(hdr->b_buf == NULL);
+				ASSERT0(datacnt);
+				ASSERT(hdr->b_l1hdr.b_buf == NULL);
 				to_delta = hdr->b_size;
 			}
 			atomic_add_64(size, to_delta);
@@ -1230,20 +1617,22 @@
 	if (new_state == arc_anon && HDR_IN_HASH_TABLE(hdr))
 		buf_hash_remove(hdr);
 
-	/* adjust state sizes */
-	if (to_delta)
+	/* adjust state sizes (ignore arc_l2c_only) */
+	if (to_delta && new_state != arc_l2c_only)
 		atomic_add_64(&new_state->arcs_size, to_delta);
-	if (from_delta) {
+	if (from_delta && old_state != arc_l2c_only) {
 		ASSERT3U(old_state->arcs_size, >=, from_delta);
 		atomic_add_64(&old_state->arcs_size, -from_delta);
 	}
-	hdr->b_state = new_state;
-
-	/* adjust l2arc hdr stats */
-	if (new_state == arc_l2c_only)
-		l2arc_hdr_stat_add();
-	else if (old_state == arc_l2c_only)
-		l2arc_hdr_stat_remove();
+	if (HDR_HAS_L1HDR(hdr))
+		hdr->b_l1hdr.b_state = new_state;
+
+	/*
+	 * L2 headers should never be on the L2 state list since they don't
+	 * have L1 headers allocated.
+	 */
+	ASSERT(list_is_empty(&arc_l2c_only->arcs_list[ARC_BUFC_DATA]) &&
+	    list_is_empty(&arc_l2c_only->arcs_list[ARC_BUFC_METADATA]));
 }
 
 void
@@ -1255,6 +1644,9 @@
 	case ARC_SPACE_DATA:
 		ARCSTAT_INCR(arcstat_data_size, space);
 		break;
+	case ARC_SPACE_META:
+		ARCSTAT_INCR(arcstat_metadata_size, space);
+		break;
 	case ARC_SPACE_OTHER:
 		ARCSTAT_INCR(arcstat_other_size, space);
 		break;
@@ -1266,7 +1658,9 @@
 		break;
 	}
 
-	ARCSTAT_INCR(arcstat_meta_used, space);
+	if (type != ARC_SPACE_DATA)
+		ARCSTAT_INCR(arcstat_meta_used, space);
+
 	atomic_add_64(&arc_size, space);
 }
 
@@ -1279,6 +1673,9 @@
 	case ARC_SPACE_DATA:
 		ARCSTAT_INCR(arcstat_data_size, -space);
 		break;
+	case ARC_SPACE_META:
+		ARCSTAT_INCR(arcstat_metadata_size, -space);
+		break;
 	case ARC_SPACE_OTHER:
 		ARCSTAT_INCR(arcstat_other_size, -space);
 		break;
@@ -1290,40 +1687,48 @@
 		break;
 	}
 
-	ASSERT(arc_meta_used >= space);
-	if (arc_meta_max < arc_meta_used)
-		arc_meta_max = arc_meta_used;
-	ARCSTAT_INCR(arcstat_meta_used, -space);
+	if (type != ARC_SPACE_DATA) {
+		ASSERT(arc_meta_used >= space);
+		if (arc_meta_max < arc_meta_used)
+			arc_meta_max = arc_meta_used;
+		ARCSTAT_INCR(arcstat_meta_used, -space);
+	}
+
 	ASSERT(arc_size >= space);
 	atomic_add_64(&arc_size, -space);
 }
 
 arc_buf_t *
-arc_buf_alloc(spa_t *spa, int size, void *tag, arc_buf_contents_t type)
+arc_buf_alloc(spa_t *spa, int32_t size, void *tag, arc_buf_contents_t type)
 {
 	arc_buf_hdr_t *hdr;
 	arc_buf_t *buf;
 
 	ASSERT3U(size, >, 0);
-	hdr = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE);
+	hdr = kmem_cache_alloc(hdr_full_cache, KM_PUSHPAGE);
 	ASSERT(BUF_EMPTY(hdr));
+	ASSERT3P(hdr->b_freeze_cksum, ==, NULL);
 	hdr->b_size = size;
-	hdr->b_type = type;
 	hdr->b_spa = spa_load_guid(spa);
-	hdr->b_state = arc_anon;
-	hdr->b_arc_access = 0;
+
 	buf = kmem_cache_alloc(buf_cache, KM_PUSHPAGE);
 	buf->b_hdr = hdr;
 	buf->b_data = NULL;
 	buf->b_efunc = NULL;
 	buf->b_private = NULL;
 	buf->b_next = NULL;
-	hdr->b_buf = buf;
+
+	hdr->b_flags = arc_bufc_to_flags(type);
+	hdr->b_flags |= ARC_FLAG_HAS_L1HDR;
+
+	hdr->b_l1hdr.b_buf = buf;
+	hdr->b_l1hdr.b_state = arc_anon;
+	hdr->b_l1hdr.b_arc_access = 0;
+	hdr->b_l1hdr.b_datacnt = 1;
+
 	arc_get_data_buf(buf);
-	hdr->b_datacnt = 1;
-	hdr->b_flags = 0;
-	ASSERT(refcount_is_zero(&hdr->b_refcnt));
-	(void) refcount_add(&hdr->b_refcnt, tag);
+	ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+	(void) refcount_add(&hdr->b_l1hdr.b_refcnt, tag);
 
 	return (buf);
 }
@@ -1356,8 +1761,9 @@
 	arc_buf_hdr_t *hdr = buf->b_hdr;
 
 	ASSERT(buf->b_data != NULL);
-	(void) refcount_add(&hdr->b_refcnt, tag);
-	(void) refcount_remove(&hdr->b_refcnt, arc_onloan_tag);
+	ASSERT(HDR_HAS_L1HDR(hdr));
+	(void) refcount_add(&hdr->b_l1hdr.b_refcnt, tag);
+	(void) refcount_remove(&hdr->b_l1hdr.b_refcnt, arc_onloan_tag);
 
 	atomic_add_64(&arc_loaned_bytes, -hdr->b_size);
 }
@@ -1366,12 +1772,12 @@
 void
 arc_loan_inuse_buf(arc_buf_t *buf, void *tag)
 {
-	arc_buf_hdr_t *hdr;
+	arc_buf_hdr_t *hdr = buf->b_hdr;
 
 	ASSERT(buf->b_data != NULL);
-	hdr = buf->b_hdr;
-	(void) refcount_add(&hdr->b_refcnt, arc_onloan_tag);
-	(void) refcount_remove(&hdr->b_refcnt, tag);
+	ASSERT(HDR_HAS_L1HDR(hdr));
+	(void) refcount_add(&hdr->b_l1hdr.b_refcnt, arc_onloan_tag);
+	(void) refcount_remove(&hdr->b_l1hdr.b_refcnt, tag);
 	buf->b_efunc = NULL;
 	buf->b_private = NULL;
 
@@ -1385,15 +1791,16 @@
 	arc_buf_hdr_t *hdr = from->b_hdr;
 	uint64_t size = hdr->b_size;
 
-	ASSERT(hdr->b_state != arc_anon);
+	ASSERT(HDR_HAS_L1HDR(hdr));
+	ASSERT(hdr->b_l1hdr.b_state != arc_anon);
 
 	buf = kmem_cache_alloc(buf_cache, KM_PUSHPAGE);
 	buf->b_hdr = hdr;
 	buf->b_data = NULL;
 	buf->b_efunc = NULL;
 	buf->b_private = NULL;
-	buf->b_next = hdr->b_buf;
-	hdr->b_buf = buf;
+	buf->b_next = hdr->b_l1hdr.b_buf;
+	hdr->b_l1hdr.b_buf = buf;
 	arc_get_data_buf(buf);
 	bcopy(from->b_data, buf->b_data, size);
 
@@ -1403,11 +1810,11 @@
 	 * then track the size and number of duplicates.  These stats will be
 	 * updated as duplicate buffers are created and destroyed.
 	 */
-	if (hdr->b_type == ARC_BUFC_DATA) {
+	if (HDR_ISTYPE_DATA(hdr)) {
 		ARCSTAT_BUMP(arcstat_duplicate_buffers);
 		ARCSTAT_INCR(arcstat_duplicate_buffers_size, size);
 	}
-	hdr->b_datacnt += 1;
+	hdr->b_l1hdr.b_datacnt += 1;
 	return (buf);
 }
 
@@ -1430,17 +1837,20 @@
 	hash_lock = HDR_LOCK(buf->b_hdr);
 	mutex_enter(hash_lock);
 	hdr = buf->b_hdr;
+	ASSERT(HDR_HAS_L1HDR(hdr));
 	ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
 	mutex_exit(&buf->b_evict_lock);
 
-	ASSERT(hdr->b_state == arc_mru || hdr->b_state == arc_mfu);
+	ASSERT(hdr->b_l1hdr.b_state == arc_mru ||
+	    hdr->b_l1hdr.b_state == arc_mfu);
+
 	add_reference(hdr, hash_lock, tag);
 	DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr);
 	arc_access(hdr, hash_lock);
 	mutex_exit(hash_lock);
 	ARCSTAT_BUMP(arcstat_hits);
-	ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH),
-	    demand, prefetch, hdr->b_type != ARC_BUFC_METADATA,
+	ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr),
+	    demand, prefetch, !HDR_ISTYPE_METADATA(hdr),
 	    data, metadata, hits);
 }
 
@@ -1478,10 +1888,10 @@
 	arc_buf_t **bufp;
 
 	/* free up data associated with the buf */
-	if (buf->b_data) {
-		arc_state_t *state = buf->b_hdr->b_state;
+	if (buf->b_data != NULL) {
+		arc_state_t *state = buf->b_hdr->b_l1hdr.b_state;
 		uint64_t size = buf->b_hdr->b_size;
-		arc_buf_contents_t type = buf->b_hdr->b_type;
+		arc_buf_contents_t type = arc_buf_type(buf->b_hdr);
 
 		arc_cksum_verify(buf);
 		arc_buf_unwatch(buf);
@@ -1489,19 +1899,19 @@
 		if (!recycle) {
 			if (type == ARC_BUFC_METADATA) {
 				arc_buf_data_free(buf, zio_buf_free);
-				arc_space_return(size, ARC_SPACE_DATA);
+				arc_space_return(size, ARC_SPACE_META);
 			} else {
 				ASSERT(type == ARC_BUFC_DATA);
 				arc_buf_data_free(buf, zio_data_buf_free);
-				ARCSTAT_INCR(arcstat_data_size, -size);
-				atomic_add_64(&arc_size, -size);
+				arc_space_return(size, ARC_SPACE_DATA);
 			}
 		}
-		if (list_link_active(&buf->b_hdr->b_arc_node)) {
+		if (list_link_active(&buf->b_hdr->b_l1hdr.b_arc_node)) {
 			uint64_t *cnt = &state->arcs_lsize[type];
 
-			ASSERT(refcount_is_zero(&buf->b_hdr->b_refcnt));
-			ASSERT(state != arc_anon);
+			ASSERT(refcount_is_zero(
+			    &buf->b_hdr->b_l1hdr.b_refcnt));
+			ASSERT(state != arc_anon && state != arc_l2c_only);
 
 			ASSERT3U(*cnt, >=, size);
 			atomic_add_64(cnt, -size);
@@ -1514,13 +1924,13 @@
 		 * If we're destroying a duplicate buffer make sure
 		 * that the appropriate statistics are updated.
 		 */
-		if (buf->b_hdr->b_datacnt > 1 &&
-		    buf->b_hdr->b_type == ARC_BUFC_DATA) {
+		if (buf->b_hdr->b_l1hdr.b_datacnt > 1 &&
+		    HDR_ISTYPE_DATA(buf->b_hdr)) {
 			ARCSTAT_BUMPDOWN(arcstat_duplicate_buffers);
 			ARCSTAT_INCR(arcstat_duplicate_buffers_size, -size);
 		}
-		ASSERT(buf->b_hdr->b_datacnt > 0);
-		buf->b_hdr->b_datacnt -= 1;
+		ASSERT(buf->b_hdr->b_l1hdr.b_datacnt > 0);
+		buf->b_hdr->b_l1hdr.b_datacnt -= 1;
 	}
 
 	/* only remove the buf if requested */
@@ -1528,7 +1938,8 @@
 		return;
 
 	/* remove the buf from the hdr list */
-	for (bufp = &buf->b_hdr->b_buf; *bufp != buf; bufp = &(*bufp)->b_next)
+	for (bufp = &buf->b_hdr->b_l1hdr.b_buf; *bufp != buf;
+	    bufp = &(*bufp)->b_next)
 		continue;
 	*bufp = buf->b_next;
 	buf->b_next = NULL;
@@ -1543,86 +1954,87 @@
 static void
 arc_hdr_destroy(arc_buf_hdr_t *hdr)
 {
-	ASSERT(refcount_is_zero(&hdr->b_refcnt));
-	ASSERT3P(hdr->b_state, ==, arc_anon);
+	if (HDR_HAS_L1HDR(hdr)) {
+		ASSERT(hdr->b_l1hdr.b_buf == NULL ||
+		    hdr->b_l1hdr.b_datacnt > 0);
+		ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+		ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon);
+	}
 	ASSERT(!HDR_IO_IN_PROGRESS(hdr));
-	l2arc_buf_hdr_t *l2hdr = hdr->b_l2hdr;
-
-	if (l2hdr != NULL) {
-		boolean_t buflist_held = MUTEX_HELD(&l2arc_buflist_mtx);
-		/*
-		 * To prevent arc_free() and l2arc_evict() from
-		 * attempting to free the same buffer at the same time,
-		 * a FREE_IN_PROGRESS flag is given to arc_free() to
-		 * give it priority.  l2arc_evict() can't destroy this
-		 * header while we are waiting on l2arc_buflist_mtx.
-		 *
-		 * The hdr may be removed from l2ad_buflist before we
-		 * grab l2arc_buflist_mtx, so b_l2hdr is rechecked.
-		 */
+	ASSERT(!HDR_IN_HASH_TABLE(hdr));
+
+	if (HDR_HAS_L2HDR(hdr)) {
+		l2arc_buf_hdr_t *l2hdr = &hdr->b_l2hdr;
+		boolean_t buflist_held = MUTEX_HELD(&l2hdr->b_dev->l2ad_mtx);
+
 		if (!buflist_held) {
-			mutex_enter(&l2arc_buflist_mtx);
-			l2hdr = hdr->b_l2hdr;
+			mutex_enter(&l2hdr->b_dev->l2ad_mtx);
+			l2hdr = &hdr->b_l2hdr;
 		}
 
-		if (l2hdr != NULL) {
-			list_remove(l2hdr->b_dev->l2ad_buflist, hdr);
-			ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
-			ARCSTAT_INCR(arcstat_l2_asize, -l2hdr->b_asize);
-			vdev_space_update(l2hdr->b_dev->l2ad_vdev,
-			    -l2hdr->b_asize, 0, 0);
-			kmem_free(l2hdr, sizeof (l2arc_buf_hdr_t));
-			if (hdr->b_state == arc_l2c_only)
-				l2arc_hdr_stat_remove();
-			hdr->b_l2hdr = NULL;
-		}
+		list_remove(&l2hdr->b_dev->l2ad_buflist, hdr);
+
+		ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
+		ARCSTAT_INCR(arcstat_l2_asize, -l2hdr->b_asize);
 
 		if (!buflist_held)
-			mutex_exit(&l2arc_buflist_mtx);
-	}
-
-	if (!BUF_EMPTY(hdr)) {
-		ASSERT(!HDR_IN_HASH_TABLE(hdr));
-		buf_discard_identity(hdr);
+			mutex_exit(&l2hdr->b_dev->l2ad_mtx);
+
+		hdr->b_flags &= ~ARC_FLAG_HAS_L2HDR;
 	}
-	while (hdr->b_buf) {
-		arc_buf_t *buf = hdr->b_buf;
-
-		if (buf->b_efunc) {
-			mutex_enter(&arc_eviction_mtx);
-			mutex_enter(&buf->b_evict_lock);
-			ASSERT(buf->b_hdr != NULL);
-			arc_buf_destroy(hdr->b_buf, FALSE, FALSE);
-			hdr->b_buf = buf->b_next;
-			buf->b_hdr = &arc_eviction_hdr;
-			buf->b_next = arc_eviction_list;
-			arc_eviction_list = buf;
-			mutex_exit(&buf->b_evict_lock);
-			mutex_exit(&arc_eviction_mtx);
-		} else {
-			arc_buf_destroy(hdr->b_buf, FALSE, TRUE);
-		}
-	}
+
+	if (!BUF_EMPTY(hdr))
+		buf_discard_identity(hdr);
+
 	if (hdr->b_freeze_cksum != NULL) {
 		kmem_free(hdr->b_freeze_cksum, sizeof (zio_cksum_t));
 		hdr->b_freeze_cksum = NULL;
 	}
-	if (hdr->b_thawed) {
-		kmem_free(hdr->b_thawed, 1);
-		hdr->b_thawed = NULL;
+
+	if (HDR_HAS_L1HDR(hdr)) {
+		while (hdr->b_l1hdr.b_buf) {
+			arc_buf_t *buf = hdr->b_l1hdr.b_buf;
+
+			if (buf->b_efunc != NULL) {
+				mutex_enter(&arc_eviction_mtx);
+				mutex_enter(&buf->b_evict_lock);
+				ASSERT(buf->b_hdr != NULL);
+				arc_buf_destroy(hdr->b_l1hdr.b_buf, FALSE,
+				    FALSE);
+				hdr->b_l1hdr.b_buf = buf->b_next;
+				buf->b_hdr = &arc_eviction_hdr;
+				buf->b_next = arc_eviction_list;
+				arc_eviction_list = buf;
+				mutex_exit(&buf->b_evict_lock);
+				mutex_exit(&arc_eviction_mtx);
+			} else {
+				arc_buf_destroy(hdr->b_l1hdr.b_buf, FALSE,
+				    TRUE);
+			}
+		}
+#ifdef ZFS_DEBUG
+		if (hdr->b_l1hdr.b_thawed != NULL) {
+			kmem_free(hdr->b_l1hdr.b_thawed, 1);
+			hdr->b_l1hdr.b_thawed = NULL;
+		}
+#endif
 	}
 
-	ASSERT(!list_link_active(&hdr->b_arc_node));
 	ASSERT3P(hdr->b_hash_next, ==, NULL);
-	ASSERT3P(hdr->b_acb, ==, NULL);
-	kmem_cache_free(hdr_cache, hdr);
+	if (HDR_HAS_L1HDR(hdr)) {
+		ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node));
+		ASSERT3P(hdr->b_l1hdr.b_acb, ==, NULL);
+		kmem_cache_free(hdr_full_cache, hdr);
+	} else {
+		kmem_cache_free(hdr_l2only_cache, hdr);
+	}
 }
 
 void
 arc_buf_free(arc_buf_t *buf, void *tag)
 {
 	arc_buf_hdr_t *hdr = buf->b_hdr;
-	int hashed = hdr->b_state != arc_anon;
+	int hashed = hdr->b_l1hdr.b_state != arc_anon;
 
 	ASSERT(buf->b_efunc == NULL);
 	ASSERT(buf->b_data != NULL);
@@ -1635,10 +2047,10 @@
 		ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
 
 		(void) remove_reference(hdr, hash_lock, tag);
-		if (hdr->b_datacnt > 1) {
+		if (hdr->b_l1hdr.b_datacnt > 1) {
 			arc_buf_destroy(buf, FALSE, TRUE);
 		} else {
-			ASSERT(buf == hdr->b_buf);
+			ASSERT(buf == hdr->b_l1hdr.b_buf);
 			ASSERT(buf->b_efunc == NULL);
 			hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE;
 		}
@@ -1652,7 +2064,7 @@
 		 */
 		mutex_enter(&arc_eviction_mtx);
 		(void) remove_reference(hdr, NULL, tag);
-		ASSERT(refcount_is_zero(&hdr->b_refcnt));
+		ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 		destroy_hdr = !HDR_IO_IN_PROGRESS(hdr);
 		mutex_exit(&arc_eviction_mtx);
 		if (destroy_hdr)
@@ -1672,34 +2084,35 @@
 	kmutex_t *hash_lock = HDR_LOCK(hdr);
 	boolean_t no_callback = (buf->b_efunc == NULL);
 
-	if (hdr->b_state == arc_anon) {
-		ASSERT(hdr->b_datacnt == 1);
+	if (hdr->b_l1hdr.b_state == arc_anon) {
+		ASSERT(hdr->b_l1hdr.b_datacnt == 1);
 		arc_buf_free(buf, tag);
 		return (no_callback);
 	}
 
 	mutex_enter(hash_lock);
 	hdr = buf->b_hdr;
+	ASSERT(hdr->b_l1hdr.b_datacnt > 0);
 	ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
-	ASSERT(hdr->b_state != arc_anon);
+	ASSERT(hdr->b_l1hdr.b_state != arc_anon);
 	ASSERT(buf->b_data != NULL);
 
 	(void) remove_reference(hdr, hash_lock, tag);
-	if (hdr->b_datacnt > 1) {
+	if (hdr->b_l1hdr.b_datacnt > 1) {
 		if (no_callback)
 			arc_buf_destroy(buf, FALSE, TRUE);
 	} else if (no_callback) {
-		ASSERT(hdr->b_buf == buf && buf->b_next == NULL);
+		ASSERT(hdr->b_l1hdr.b_buf == buf && buf->b_next == NULL);
 		ASSERT(buf->b_efunc == NULL);
 		hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE;
 	}
-	ASSERT(no_callback || hdr->b_datacnt > 1 ||
-	    refcount_is_zero(&hdr->b_refcnt));
+	ASSERT(no_callback || hdr->b_l1hdr.b_datacnt > 1 ||
+	    refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 	mutex_exit(hash_lock);
 	return (no_callback);
 }
 
-int
+int32_t
 arc_buf_size(arc_buf_t *buf)
 {
 	return (buf->b_hdr->b_size);
@@ -1740,7 +2153,7 @@
 		return (B_TRUE);
 	}
 
-	if (hdr->b_datacnt > 1 && hdr->b_type == ARC_BUFC_DATA)
+	if (hdr->b_l1hdr.b_datacnt > 1 && HDR_ISTYPE_DATA(hdr))
 		evict_needed = B_TRUE;
 
 	mutex_exit(&buf->b_evict_lock);
@@ -1777,8 +2190,20 @@
 
 	evicted_state = (state == arc_mru) ? arc_mru_ghost : arc_mfu_ghost;
 
+	/*
+	 * The ghost list lock must be acquired first in order to prevent
+	 * a 3 party deadlock:
+	 *
+	 *  - arc_evict_ghost acquires arc_*_ghost->arcs_mtx, followed by
+	 *    l2ad_mtx in arc_hdr_realloc
+	 *  - l2arc_write_buffers acquires l2ad_mtx, followed by arc_*->arcs_mtx
+	 *  - arc_evict acquires arc_*_ghost->arcs_mtx, followed by
+	 *    arc_*_ghost->arcs_mtx and forms a deadlock cycle.
+	 *
+	 * This situation is avoided by acquiring the ghost list lock first.
+	 */
+	mutex_enter(&evicted_state->arcs_mtx);
 	mutex_enter(&state->arcs_mtx);
-	mutex_enter(&evicted_state->arcs_mtx);
 
 	/*
 	 * Decide which "type" (data vs metadata) to recycle from.
@@ -1794,6 +2219,7 @@
 		arc_buf_hdr_t *metadata_hdr =
 		    list_tail(&state->arcs_list[ARC_BUFC_METADATA]);
 		arc_buf_contents_t realtype;
+
 		if (data_hdr == NULL) {
 			realtype = ARC_BUFC_METADATA;
 		} else if (metadata_hdr == NULL) {
@@ -1802,13 +2228,13 @@
 			realtype = ARC_BUFC_METADATA;
 		} else if (arc_meta_used <= arc_meta_min) {
 			realtype = ARC_BUFC_DATA;
+		} else if (HDR_HAS_L1HDR(data_hdr) &&
+		    HDR_HAS_L1HDR(metadata_hdr) &&
+		    data_hdr->b_l1hdr.b_arc_access <
+		    metadata_hdr->b_l1hdr.b_arc_access) {
+			realtype = ARC_BUFC_DATA;
 		} else {
-			if (data_hdr->b_arc_access <
-			    metadata_hdr->b_arc_access) {
-				realtype = ARC_BUFC_DATA;
-			} else {
-				realtype = ARC_BUFC_METADATA;
-			}
+			realtype = ARC_BUFC_METADATA;
 		}
 		if (realtype != type) {
 			/*
@@ -1829,8 +2255,8 @@
 		/* prefetch buffers have a minimum lifespan */
 		if (HDR_IO_IN_PROGRESS(hdr) ||
 		    (spa && hdr->b_spa != spa) ||
-		    (hdr->b_flags & (ARC_FLAG_PREFETCH | ARC_FLAG_INDIRECT) &&
-		    ddi_get_lbolt() - hdr->b_arc_access <
+		    ((hdr->b_flags & (ARC_FLAG_PREFETCH | ARC_FLAG_INDIRECT)) &&
+		    ddi_get_lbolt() - hdr->b_l1hdr.b_arc_access <
 		    arc_min_prefetch_lifespan)) {
 			skipped++;
 			continue;
@@ -1855,11 +2281,11 @@
 		 */
 		if (!recycle && count++ > arc_evict_iterations) {
 			list_insert_after(list, hdr, &marker);
+			mutex_exit(&state->arcs_mtx);
 			mutex_exit(&evicted_state->arcs_mtx);
-			mutex_exit(&state->arcs_mtx);
 			kpreempt(KPREEMPT_SYNC);
+			mutex_enter(&evicted_state->arcs_mtx);
 			mutex_enter(&state->arcs_mtx);
-			mutex_enter(&evicted_state->arcs_mtx);
 			hdr_prev = list_prev(list, &marker);
 			list_remove(list, &marker);
 			count = 0;
@@ -1869,28 +2295,29 @@
 		hash_lock = HDR_LOCK(hdr);
 		have_lock = MUTEX_HELD(hash_lock);
 		if (have_lock || mutex_tryenter(hash_lock)) {
-			ASSERT0(refcount_count(&hdr->b_refcnt));
-			ASSERT(hdr->b_datacnt > 0);
-			while (hdr->b_buf) {
-				arc_buf_t *buf = hdr->b_buf;
+			ASSERT0(refcount_count(&hdr->b_l1hdr.b_refcnt));
+			ASSERT3U(hdr->b_l1hdr.b_datacnt, >, 0);
+			while (hdr->b_l1hdr.b_buf) {
+				arc_buf_t *buf = hdr->b_l1hdr.b_buf;
 				if (!mutex_tryenter(&buf->b_evict_lock)) {
 					missed += 1;
 					break;
 				}
-				if (buf->b_data) {
+				if (buf->b_data != NULL) {
 					bytes_evicted += hdr->b_size;
-					if (recycle && hdr->b_type == type &&
+					if (recycle &&
+					    arc_buf_type(hdr) == type &&
 					    hdr->b_size == bytes &&
 					    !HDR_L2_WRITING(hdr)) {
 						stolen = buf->b_data;
 						recycle = FALSE;
 					}
 				}
-				if (buf->b_efunc) {
+				if (buf->b_efunc != NULL) {
 					mutex_enter(&arc_eviction_mtx);
 					arc_buf_destroy(buf,
 					    buf->b_data == stolen, FALSE);
-					hdr->b_buf = buf->b_next;
+					hdr->b_l1hdr.b_buf = buf->b_next;
 					buf->b_hdr = &arc_eviction_hdr;
 					buf->b_next = arc_eviction_list;
 					arc_eviction_list = buf;
@@ -1903,7 +2330,7 @@
 				}
 			}
 
-			if (hdr->b_l2hdr) {
+			if (HDR_HAS_L2HDR(hdr)) {
 				ARCSTAT_INCR(arcstat_evict_l2_cached,
 				    hdr->b_size);
 			} else {
@@ -1917,7 +2344,7 @@
 				}
 			}
 
-			if (hdr->b_datacnt == 0) {
+			if (hdr->b_l1hdr.b_datacnt == 0) {
 				arc_change_state(evicted_state, hdr, hash_lock);
 				ASSERT(HDR_IN_HASH_TABLE(hdr));
 				hdr->b_flags |= ARC_FLAG_IN_HASH_TABLE;
@@ -1933,8 +2360,8 @@
 		}
 	}
 
+	mutex_exit(&state->arcs_mtx);
 	mutex_exit(&evicted_state->arcs_mtx);
-	mutex_exit(&state->arcs_mtx);
 
 	if (bytes_evicted < bytes)
 		dprintf("only evicted %lld bytes from %x",
@@ -1976,7 +2403,7 @@
 	mutex_enter(&state->arcs_mtx);
 	for (hdr = list_tail(list); hdr; hdr = hdr_prev) {
 		hdr_prev = list_prev(list, hdr);
-		if (hdr->b_type > ARC_BUFC_NUMTYPES)
+		if (arc_buf_type(hdr) >= ARC_BUFC_NUMTYPES)
 			panic("invalid hdr=%p", (void *)hdr);
 		if (spa && hdr->b_spa != spa)
 			continue;
@@ -2008,16 +2435,23 @@
 		}
 		if (mutex_tryenter(hash_lock)) {
 			ASSERT(!HDR_IO_IN_PROGRESS(hdr));
-			ASSERT(hdr->b_buf == NULL);
+			ASSERT(!HDR_HAS_L1HDR(hdr) ||
+			    hdr->b_l1hdr.b_buf == NULL);
 			ARCSTAT_BUMP(arcstat_deleted);
 			bytes_deleted += hdr->b_size;
 
-			if (hdr->b_l2hdr != NULL) {
+			if (HDR_HAS_L2HDR(hdr)) {
 				/*
 				 * This buffer is cached on the 2nd Level ARC;
 				 * don't destroy the header.
 				 */
 				arc_change_state(arc_l2c_only, hdr, hash_lock);
+				/*
+				 * dropping from L1+L2 cached to L2-only,
+				 * realloc to remove the L1 header.
+				 */
+				hdr = arc_hdr_realloc(hdr, hdr_full_cache,
+				    hdr_l2only_cache);
 				mutex_exit(hash_lock);
 			} else {
 				arc_change_state(arc_anon, hdr, hash_lock);
@@ -2160,27 +2594,27 @@
 {
 	uint64_t guid = 0;
 
-	if (spa)
+	if (spa != NULL)
 		guid = spa_load_guid(spa);
 
 	while (list_head(&arc_mru->arcs_list[ARC_BUFC_DATA])) {
 		(void) arc_evict(arc_mru, guid, -1, FALSE, ARC_BUFC_DATA);
-		if (spa)
+		if (spa != NULL)
 			break;
 	}
 	while (list_head(&arc_mru->arcs_list[ARC_BUFC_METADATA])) {
 		(void) arc_evict(arc_mru, guid, -1, FALSE, ARC_BUFC_METADATA);
-		if (spa)
+		if (spa != NULL)
 			break;
 	}
 	while (list_head(&arc_mfu->arcs_list[ARC_BUFC_DATA])) {
 		(void) arc_evict(arc_mfu, guid, -1, FALSE, ARC_BUFC_DATA);
-		if (spa)
+		if (spa != NULL)
 			break;
 	}
 	while (list_head(&arc_mfu->arcs_list[ARC_BUFC_METADATA])) {
 		(void) arc_evict(arc_mfu, guid, -1, FALSE, ARC_BUFC_METADATA);
-		if (spa)
+		if (spa != NULL)
 			break;
 	}
 
@@ -2194,16 +2628,10 @@
 }
 
 void
-arc_shrink(void)
+arc_shrink(int64_t to_free)
 {
 	if (arc_c > arc_c_min) {
-		uint64_t to_free;
-
-#ifdef _KERNEL
-		to_free = MAX(arc_c >> arc_shrink_shift, ptob(needfree));
-#else
-		to_free = arc_c >> arc_shrink_shift;
-#endif
+
 		if (arc_c > arc_c_min + to_free)
 			atomic_add_64(&arc_c, -to_free);
 		else
@@ -2222,25 +2650,49 @@
 		arc_adjust();
 }
 
+typedef enum free_memory_reason_t {
+	FMR_UNKNOWN,
+	FMR_NEEDFREE,
+	FMR_LOTSFREE,
+	FMR_SWAPFS_MINFREE,
+	FMR_PAGES_PP_MAXIMUM,
+	FMR_HEAP_ARENA,
+	FMR_ZIO_ARENA,
+} free_memory_reason_t;
+
+int64_t last_free_memory;
+free_memory_reason_t last_free_reason;
+
 /*
- * Determine if the system is under memory pressure and is asking
- * to reclaim memory. A return value of 1 indicates that the system
- * is under memory pressure and that the arc should adjust accordingly.
+ * Additional reserve of pages for pp_reserve.
  */
-static int
-arc_reclaim_needed(void)
+int64_t arc_pages_pp_reserve = 64;
+
+/*
+ * Additional reserve of pages for swapfs.
+ */
+int64_t arc_swapfs_reserve = 64;
+
+/*
+ * Return the amount of memory that can be consumed before reclaim will be
+ * needed.  Positive if there is sufficient free memory, negative indicates
+ * the amount of memory that needs to be freed up.
+ */
+static int64_t
+arc_available_memory(void)
 {
-	uint64_t extra;
+	int64_t lowest = INT64_MAX;
+	int64_t n;
+	free_memory_reason_t r = FMR_UNKNOWN;
 
 #ifdef _KERNEL
-
-	if (needfree)
-		return (1);
-
-	/*
-	 * take 'desfree' extra pages, so we reclaim sooner, rather than later
-	 */
-	extra = desfree;
+	if (needfree > 0) {
+		n = PAGESIZE * (-needfree);
+		if (n < lowest) {
+			lowest = n;
+			r = FMR_NEEDFREE;
+		}
+	}
 
 	/*
 	 * check that we're out of range of the pageout scanner.  It starts to
@@ -2249,8 +2701,11 @@
 	 * number of needed free pages.  We add extra pages here to make sure
 	 * the scanner doesn't start up while we're freeing memory.
 	 */
-	if (freemem < lotsfree + needfree + extra)
-		return (1);
+	n = PAGESIZE * (freemem - lotsfree - needfree - desfree);
+	if (n < lowest) {
+		lowest = n;
+		r = FMR_LOTSFREE;
+	}
 
 	/*
 	 * check to make sure that swapfs has enough space so that anon
@@ -2259,8 +2714,13 @@
 	 * swap pages.  We also add a bit of extra here just to prevent
 	 * circumstances from getting really dire.
 	 */
-	if (availrmem < swapfs_minfree + swapfs_reserve + extra)
-		return (1);
+	n = PAGESIZE * (availrmem - swapfs_minfree - swapfs_reserve -
+	    desfree - arc_swapfs_reserve);
+	if (n < lowest) {
+		lowest = n;
+		r = FMR_SWAPFS_MINFREE;
+	}
+
 
 	/*
 	 * Check that we have enough availrmem that memory locking (e.g., via
@@ -2269,8 +2729,12 @@
 	 * drops below pages_pp_maximum, page locking mechanisms such as
 	 * page_pp_lock() will fail.)
 	 */
-	if (availrmem <= pages_pp_maximum)
-		return (1);
+	n = PAGESIZE * (availrmem - pages_pp_maximum -
+	    arc_pages_pp_reserve);
+	if (n < lowest) {
+		lowest = n;
+		r = FMR_PAGES_PP_MAXIMUM;
+	}
 
 #if defined(__i386)
 	/*
@@ -2284,9 +2748,12 @@
 	 * heap is allocated.  (Or, in the calculation, if less than 1/4th is
 	 * free)
 	 */
-	if (vmem_size(heap_arena, VMEM_FREE) <
-	    (vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC) >> 2))
-		return (1);
+	n = vmem_size(heap_arena, VMEM_FREE) -
+	    (vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC) >> 2);
+	if (n < lowest) {
+		lowest = n;
+		r = FMR_HEAP_ARENA;
+	}
 #endif
 
 	/*
@@ -2298,19 +2765,40 @@
 	 * to aggressively evict memory from the arc in order to avoid
 	 * memory fragmentation issues.
 	 */
-	if (zio_arena != NULL &&
-	    vmem_size(zio_arena, VMEM_FREE) <
-	    (vmem_size(zio_arena, VMEM_ALLOC) >> 4))
-		return (1);
+	if (zio_arena != NULL) {
+		n = vmem_size(zio_arena, VMEM_FREE) -
+		    (vmem_size(zio_arena, VMEM_ALLOC) >> 4);
+		if (n < lowest) {
+			lowest = n;
+			r = FMR_ZIO_ARENA;
+		}
+	}
 #else
+	/* Every 100 calls, free a small amount */
 	if (spa_get_random(100) == 0)
-		return (1);
+		lowest = -1024;
 #endif
-	return (0);
+
+	last_free_memory = lowest;
+	last_free_reason = r;
+
+	return (lowest);
+}
+
+
+/*
+ * Determine if the system is under memory pressure and is asking
+ * to reclaim memory. A return value of TRUE indicates that the system
+ * is under memory pressure and that the arc should adjust accordingly.
+ */
+static boolean_t
+arc_reclaim_needed(void)
+{
+	return (arc_available_memory() < 0);
 }
 
 static void
-arc_kmem_reap_now(arc_reclaim_strategy_t strat)
+arc_kmem_reap_now(void)
 {
 	size_t			i;
 	kmem_cache_t		*prev_cache = NULL;
@@ -2335,13 +2823,6 @@
 #endif
 #endif
 
-	/*
-	 * An aggressive reclamation will shrink the cache size as well as
-	 * reap free buffers from the arc kmem caches.
-	 */
-	if (strat == ARC_RECLAIM_AGGR)
-		arc_shrink();
-
 	for (i = 0; i < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT; i++) {
 		if (zio_buf_cache[i] != prev_cache) {
 			prev_cache = zio_buf_cache[i];
@@ -2353,50 +2834,61 @@
 		}
 	}
 	kmem_cache_reap_now(buf_cache);
-	kmem_cache_reap_now(hdr_cache);
+	kmem_cache_reap_now(hdr_full_cache);
+	kmem_cache_reap_now(hdr_l2only_cache);
 	kmem_cache_reap_now(range_seg_cache);
 
-	/*
-	 * Ask the vmem areana to reclaim unused memory from its
-	 * quantum caches.
-	 */
-	if (zio_arena != NULL && strat == ARC_RECLAIM_AGGR)
+	if (zio_arena != NULL) {
+		/*
+		 * Ask the vmem arena to reclaim unused memory from its
+		 * quantum caches.
+		 */
 		vmem_qcache_reap(zio_arena);
+	}
 }
 
 static void
 arc_reclaim_thread(void)
 {
 	clock_t			growtime = 0;
-	arc_reclaim_strategy_t	last_reclaim = ARC_RECLAIM_CONS;
 	callb_cpr_t		cpr;
 
 	CALLB_CPR_INIT(&cpr, &arc_reclaim_thr_lock, callb_generic_cpr, FTAG);
 
 	mutex_enter(&arc_reclaim_thr_lock);
 	while (arc_thread_exit == 0) {
-		if (arc_reclaim_needed()) {
-
-			if (arc_no_grow) {
-				if (last_reclaim == ARC_RECLAIM_CONS) {
-					last_reclaim = ARC_RECLAIM_AGGR;
-				} else {
-					last_reclaim = ARC_RECLAIM_CONS;
-				}
-			} else {
-				arc_no_grow = TRUE;
-				last_reclaim = ARC_RECLAIM_AGGR;
-				membar_producer();
+		int64_t free_memory = arc_available_memory();
+		if (free_memory < 0) {
+
+			arc_no_grow = B_TRUE;
+			arc_warm = B_TRUE;
+
+			/*
+			 * Wait at least zfs_grow_retry (default 60) seconds
+			 * before considering growing.
+			 */
+			growtime = ddi_get_lbolt() + (arc_grow_retry * hz);
+
+			arc_kmem_reap_now();
+
+			/*
+			 * If we are still low on memory, shrink the ARC
+			 * so that we have arc_shrink_min free space.
+			 */
+			free_memory = arc_available_memory();
+
+			int64_t to_free =
+			    (arc_c >> arc_shrink_shift) - free_memory;
+			if (to_free > 0) {
+#ifdef _KERNEL
+				to_free = MAX(to_free, ptob(needfree));
+#endif
+				arc_shrink(to_free);
 			}
-
-			/* reset the growth delay for every reclaim */
-			growtime = ddi_get_lbolt() + (arc_grow_retry * hz);
-
-			arc_kmem_reap_now(last_reclaim);
-			arc_warm = B_TRUE;
-
-		} else if (arc_no_grow && ddi_get_lbolt() >= growtime) {
-			arc_no_grow = FALSE;
+		} else if (free_memory < arc_c >> arc_no_grow_shift) {
+			arc_no_grow = B_TRUE;
+		} else if (ddi_get_lbolt() >= growtime) {
+			arc_no_grow = B_FALSE;
 		}
 
 		arc_adjust();
@@ -2404,6 +2896,20 @@
 		if (arc_eviction_list != NULL)
 			arc_do_user_evicts();
 
+		/*
+		 * This is necessary in order for the mdb ::arc dcmd to
+		 * show up to date information. Since the ::arc command
+		 * does not call the kstat's update function, without
+		 * this call, the command may show stale stats for the
+		 * anon, mru, mru_ghost, mfu, and mfu_ghost lists. Even
+		 * with this change, the data might be up to 1 second
+		 * out of date; but that should suffice. The arc_state_t
+		 * structures can be queried directly if more accurate
+		 * information is needed.
+		 */
+		if (arc_ksp != NULL)
+			arc_ksp->ks_update(arc_ksp, KSTAT_READ);
+
 		/* block until needed, or one second, whichever is shorter */
 		CALLB_CPR_SAFE_BEGIN(&cpr);
 		(void) cv_timedwait(&arc_reclaim_thr_cv,
@@ -2527,9 +3033,9 @@
 static void
 arc_get_data_buf(arc_buf_t *buf)
 {
-	arc_state_t		*state = buf->b_hdr->b_state;
+	arc_state_t		*state = buf->b_hdr->b_l1hdr.b_state;
 	uint64_t		size = buf->b_hdr->b_size;
-	arc_buf_contents_t	type = buf->b_hdr->b_type;
+	arc_buf_contents_t	type = arc_buf_type(buf->b_hdr);
 
 	arc_adapt(size, state);
 
@@ -2540,12 +3046,11 @@
 	if (!arc_evict_needed(type)) {
 		if (type == ARC_BUFC_METADATA) {
 			buf->b_data = zio_buf_alloc(size);
-			arc_space_consume(size, ARC_SPACE_DATA);
+			arc_space_consume(size, ARC_SPACE_META);
 		} else {
 			ASSERT(type == ARC_BUFC_DATA);
 			buf->b_data = zio_data_buf_alloc(size);
-			ARCSTAT_INCR(arcstat_data_size, size);
-			atomic_add_64(&arc_size, size);
+			arc_space_consume(size, ARC_SPACE_DATA);
 		}
 		goto out;
 	}
@@ -2555,8 +3060,7 @@
 	 * will end up on the mru list; so steal space from there.
 	 */
 	if (state == arc_mfu_ghost)
-		state = buf->b_hdr->b_flags & ARC_FLAG_PREFETCH ?
-		    arc_mru : arc_mfu;
+		state = HDR_PREFETCH(buf->b_hdr) ? arc_mru : arc_mfu;
 	else if (state == arc_mru_ghost)
 		state = arc_mru;
 
@@ -2573,12 +3077,11 @@
 	if ((buf->b_data = arc_evict(state, NULL, size, TRUE, type)) == NULL) {
 		if (type == ARC_BUFC_METADATA) {
 			buf->b_data = zio_buf_alloc(size);
-			arc_space_consume(size, ARC_SPACE_DATA);
+			arc_space_consume(size, ARC_SPACE_META);
 		} else {
 			ASSERT(type == ARC_BUFC_DATA);
 			buf->b_data = zio_data_buf_alloc(size);
-			ARCSTAT_INCR(arcstat_data_size, size);
-			atomic_add_64(&arc_size, size);
+			arc_space_consume(size, ARC_SPACE_DATA);
 		}
 		ARCSTAT_BUMP(arcstat_recycle_miss);
 	}
@@ -2588,19 +3091,20 @@
 	 * Update the state size.  Note that ghost states have a
 	 * "ghost size" and so don't need to be updated.
 	 */
-	if (!GHOST_STATE(buf->b_hdr->b_state)) {
+	if (!GHOST_STATE(buf->b_hdr->b_l1hdr.b_state)) {
 		arc_buf_hdr_t *hdr = buf->b_hdr;
 
-		atomic_add_64(&hdr->b_state->arcs_size, size);
-		if (list_link_active(&hdr->b_arc_node)) {
-			ASSERT(refcount_is_zero(&hdr->b_refcnt));
-			atomic_add_64(&hdr->b_state->arcs_lsize[type], size);
+		atomic_add_64(&hdr->b_l1hdr.b_state->arcs_size, size);
+		if (list_link_active(&hdr->b_l1hdr.b_arc_node)) {
+			ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+			atomic_add_64(&hdr->b_l1hdr.b_state->arcs_lsize[type],
+			    size);
 		}
 		/*
 		 * If we are growing the cache, and we are adding anonymous
 		 * data, and we have outgrown arc_p, update arc_p
 		 */
-		if (arc_size < arc_c && hdr->b_state == arc_anon &&
+		if (arc_size < arc_c && hdr->b_l1hdr.b_state == arc_anon &&
 		    arc_anon->arcs_size + arc_mru->arcs_size > arc_p)
 			arc_p = MIN(arc_c, arc_p + size);
 	}
@@ -2616,20 +3120,21 @@
 	clock_t now;
 
 	ASSERT(MUTEX_HELD(hash_lock));
-
-	if (hdr->b_state == arc_anon) {
+	ASSERT(HDR_HAS_L1HDR(hdr));
+
+	if (hdr->b_l1hdr.b_state == arc_anon) {
 		/*
 		 * This buffer is not in the cache, and does not
 		 * appear in our "ghost" list.  Add the new buffer
 		 * to the MRU state.
 		 */
 
-		ASSERT(hdr->b_arc_access == 0);
-		hdr->b_arc_access = ddi_get_lbolt();
+		ASSERT0(hdr->b_l1hdr.b_arc_access);
+		hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
 		DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr);
 		arc_change_state(arc_mru, hdr, hash_lock);
 
-	} else if (hdr->b_state == arc_mru) {
+	} else if (hdr->b_l1hdr.b_state == arc_mru) {
 		now = ddi_get_lbolt();
 
 		/*
@@ -2640,14 +3145,15 @@
 		 * - move the buffer to the head of the list if this is
 		 *   another prefetch (to make it less likely to be evicted).
 		 */
-		if ((hdr->b_flags & ARC_FLAG_PREFETCH) != 0) {
-			if (refcount_count(&hdr->b_refcnt) == 0) {
-				ASSERT(list_link_active(&hdr->b_arc_node));
+		if (HDR_PREFETCH(hdr)) {
+			if (refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
+				ASSERT(list_link_active(
+				    &hdr->b_l1hdr.b_arc_node));
 			} else {
 				hdr->b_flags &= ~ARC_FLAG_PREFETCH;
 				ARCSTAT_BUMP(arcstat_mru_hits);
 			}
-			hdr->b_arc_access = now;
+			hdr->b_l1hdr.b_arc_access = now;
 			return;
 		}
 
@@ -2656,18 +3162,18 @@
 		 * but it is still in the cache. Move it to the MFU
 		 * state.
 		 */
-		if (now > hdr->b_arc_access + ARC_MINTIME) {
+		if (now > hdr->b_l1hdr.b_arc_access + ARC_MINTIME) {
 			/*
 			 * More than 125ms have passed since we
 			 * instantiated this buffer.  Move it to the
 			 * most frequently used state.
 			 */
-			hdr->b_arc_access = now;
+			hdr->b_l1hdr.b_arc_access = now;
 			DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
 			arc_change_state(arc_mfu, hdr, hash_lock);
 		}
 		ARCSTAT_BUMP(arcstat_mru_hits);
-	} else if (hdr->b_state == arc_mru_ghost) {
+	} else if (hdr->b_l1hdr.b_state == arc_mru_ghost) {
 		arc_state_t	*new_state;
 		/*
 		 * This buffer has been "accessed" recently, but
@@ -2675,9 +3181,9 @@
 		 * MFU state.
 		 */
 
-		if (hdr->b_flags & ARC_FLAG_PREFETCH) {
+		if (HDR_PREFETCH(hdr)) {
 			new_state = arc_mru;
-			if (refcount_count(&hdr->b_refcnt) > 0)
+			if (refcount_count(&hdr->b_l1hdr.b_refcnt) > 0)
 				hdr->b_flags &= ~ARC_FLAG_PREFETCH;
 			DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr);
 		} else {
@@ -2685,11 +3191,11 @@
 			DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
 		}
 
-		hdr->b_arc_access = ddi_get_lbolt();
+		hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
 		arc_change_state(new_state, hdr, hash_lock);
 
 		ARCSTAT_BUMP(arcstat_mru_ghost_hits);
-	} else if (hdr->b_state == arc_mfu) {
+	} else if (hdr->b_l1hdr.b_state == arc_mfu) {
 		/*
 		 * This buffer has been accessed more than once and is
 		 * still in the cache.  Keep it in the MFU state.
@@ -2699,13 +3205,13 @@
 		 * If it was a prefetch, we will explicitly move it to
 		 * the head of the list now.
 		 */
-		if ((hdr->b_flags & ARC_FLAG_PREFETCH) != 0) {
-			ASSERT(refcount_count(&hdr->b_refcnt) == 0);
-			ASSERT(list_link_active(&hdr->b_arc_node));
+		if ((HDR_PREFETCH(hdr)) != 0) {
+			ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+			ASSERT(list_link_active(&hdr->b_l1hdr.b_arc_node));
 		}
 		ARCSTAT_BUMP(arcstat_mfu_hits);
-		hdr->b_arc_access = ddi_get_lbolt();
-	} else if (hdr->b_state == arc_mfu_ghost) {
+		hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
+	} else if (hdr->b_l1hdr.b_state == arc_mfu_ghost) {
 		arc_state_t	*new_state = arc_mfu;
 		/*
 		 * This buffer has been accessed more than once but has
@@ -2713,26 +3219,26 @@
 		 * MFU state.
 		 */
 
-		if (hdr->b_flags & ARC_FLAG_PREFETCH) {
+		if (HDR_PREFETCH(hdr)) {
 			/*
 			 * This is a prefetch access...
 			 * move this block back to the MRU state.
 			 */
-			ASSERT0(refcount_count(&hdr->b_refcnt));
+			ASSERT0(refcount_count(&hdr->b_l1hdr.b_refcnt));
 			new_state = arc_mru;
 		}
 
-		hdr->b_arc_access = ddi_get_lbolt();
+		hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
 		DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
 		arc_change_state(new_state, hdr, hash_lock);
 
 		ARCSTAT_BUMP(arcstat_mfu_ghost_hits);
-	} else if (hdr->b_state == arc_l2c_only) {
+	} else if (hdr->b_l1hdr.b_state == arc_l2c_only) {
 		/*
 		 * This buffer is on the 2nd Level ARC.
 		 */
 
-		hdr->b_arc_access = ddi_get_lbolt();
+		hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
 		DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
 		arc_change_state(arc_mfu, hdr, hash_lock);
 	} else {
@@ -2803,11 +3309,11 @@
 	}
 
 	hdr->b_flags &= ~ARC_FLAG_L2_EVICTED;
-	if (l2arc_noprefetch && (hdr->b_flags & ARC_FLAG_PREFETCH))
+	if (l2arc_noprefetch && HDR_PREFETCH(hdr))
 		hdr->b_flags &= ~ARC_FLAG_L2CACHE;
 
 	/* byteswap if necessary */
-	callback_list = hdr->b_acb;
+	callback_list = hdr->b_l1hdr.b_acb;
 	ASSERT(callback_list != NULL);
 	if (BP_SHOULD_BYTESWAP(zio->io_bp) && zio->io_error == 0) {
 		dmu_object_byteswap_t bswap =
@@ -2821,7 +3327,8 @@
 	arc_cksum_compute(buf, B_FALSE);
 	arc_buf_watch(buf);
 
-	if (hash_lock && zio->io_error == 0 && hdr->b_state == arc_anon) {
+	if (hash_lock && zio->io_error == 0 &&
+	    hdr->b_l1hdr.b_state == arc_anon) {
 		/*
 		 * Only call arc_access on anonymous buffers.  This is because
 		 * if we've issued an I/O for an evicted buffer, we've already
@@ -2843,24 +3350,25 @@
 			abuf = NULL;
 		}
 	}
-	hdr->b_acb = NULL;
+	hdr->b_l1hdr.b_acb = NULL;
 	hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS;
 	ASSERT(!HDR_BUF_AVAILABLE(hdr));
 	if (abuf == buf) {
 		ASSERT(buf->b_efunc == NULL);
-		ASSERT(hdr->b_datacnt == 1);
+		ASSERT(hdr->b_l1hdr.b_datacnt == 1);
 		hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE;
 	}
 
-	ASSERT(refcount_is_zero(&hdr->b_refcnt) || callback_list != NULL);
+	ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt) ||
+	    callback_list != NULL);
 
 	if (zio->io_error != 0) {
 		hdr->b_flags |= ARC_FLAG_IO_ERROR;
-		if (hdr->b_state != arc_anon)
+		if (hdr->b_l1hdr.b_state != arc_anon)
 			arc_change_state(arc_anon, hdr, hash_lock);
 		if (HDR_IN_HASH_TABLE(hdr))
 			buf_hash_remove(hdr);
-		freeable = refcount_is_zero(&hdr->b_refcnt);
+		freeable = refcount_is_zero(&hdr->b_l1hdr.b_refcnt);
 	}
 
 	/*
@@ -2868,9 +3376,9 @@
 	 * that the hdr (and hence the cv) might be freed before we get to
 	 * the cv_broadcast().
 	 */
-	cv_broadcast(&hdr->b_cv);
-
-	if (hash_lock) {
+	cv_broadcast(&hdr->b_l1hdr.b_cv);
+
+	if (hash_lock != NULL) {
 		mutex_exit(hash_lock);
 	} else {
 		/*
@@ -2879,8 +3387,8 @@
 		 * moved to the anonymous state (so that it won't show up
 		 * in the cache).
 		 */
-		ASSERT3P(hdr->b_state, ==, arc_anon);
-		freeable = refcount_is_zero(&hdr->b_refcnt);
+		ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon);
+		freeable = refcount_is_zero(&hdr->b_l1hdr.b_refcnt);
 	}
 
 	/* execute each callback and free its structure */
@@ -2942,14 +3450,14 @@
 		hdr = buf_hash_find(guid, bp, &hash_lock);
 	}
 
-	if (hdr != NULL && hdr->b_datacnt > 0) {
+	if (hdr != NULL && HDR_HAS_L1HDR(hdr) && hdr->b_l1hdr.b_datacnt > 0) {
 
 		*arc_flags |= ARC_FLAG_CACHED;
 
 		if (HDR_IO_IN_PROGRESS(hdr)) {
 
 			if (*arc_flags & ARC_FLAG_WAIT) {
-				cv_wait(&hdr->b_cv, hash_lock);
+				cv_wait(&hdr->b_l1hdr.b_cv, hash_lock);
 				mutex_exit(hash_lock);
 				goto top;
 			}
@@ -2967,8 +3475,8 @@
 					    spa, NULL, NULL, NULL, zio_flags);
 
 				ASSERT(acb->acb_done != NULL);
-				acb->acb_next = hdr->b_acb;
-				hdr->b_acb = acb;
+				acb->acb_next = hdr->b_l1hdr.b_acb;
+				hdr->b_l1hdr.b_acb = acb;
 				add_reference(hdr, hash_lock, private);
 				mutex_exit(hash_lock);
 				return (0);
@@ -2977,7 +3485,8 @@
 			return (0);
 		}
 
-		ASSERT(hdr->b_state == arc_mru || hdr->b_state == arc_mfu);
+		ASSERT(hdr->b_l1hdr.b_state == arc_mru ||
+		    hdr->b_l1hdr.b_state == arc_mfu);
 
 		if (done) {
 			add_reference(hdr, hash_lock, private);
@@ -2986,7 +3495,7 @@
 			 * copy of the data so that we will be guaranteed
 			 * that arc_release() will always succeed.
 			 */
-			buf = hdr->b_buf;
+			buf = hdr->b_l1hdr.b_buf;
 			ASSERT(buf);
 			ASSERT(buf->b_data);
 			if (HDR_BUF_AVAILABLE(hdr)) {
@@ -2997,7 +3506,7 @@
 			}
 
 		} else if (*arc_flags & ARC_FLAG_PREFETCH &&
-		    refcount_count(&hdr->b_refcnt) == 0) {
+		    refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
 			hdr->b_flags |= ARC_FLAG_PREFETCH;
 		}
 		DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr);
@@ -3008,8 +3517,8 @@
 			hdr->b_flags |= ARC_FLAG_L2COMPRESS;
 		mutex_exit(hash_lock);
 		ARCSTAT_BUMP(arcstat_hits);
-		ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH),
-		    demand, prefetch, hdr->b_type != ARC_BUFC_METADATA,
+		ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr),
+		    demand, prefetch, !HDR_ISTYPE_METADATA(hdr),
 		    data, metadata, hits);
 
 		if (done)
@@ -3021,7 +3530,7 @@
 		uint64_t addr = 0;
 		boolean_t devw = B_FALSE;
 		enum zio_compress b_compress = ZIO_COMPRESS_OFF;
-		uint64_t b_asize = 0;
+		int32_t b_asize = 0;
 
 		if (hdr == NULL) {
 			/* this block is not in the cache */
@@ -3032,7 +3541,6 @@
 			if (!BP_IS_EMBEDDED(bp)) {
 				hdr->b_dva = *BP_IDENTITY(bp);
 				hdr->b_birth = BP_PHYSICAL_BIRTH(bp);
-				hdr->b_cksum0 = bp->blk_cksum.zc_word[0];
 				exists = buf_hash_insert(hdr, &hash_lock);
 			}
 			if (exists != NULL) {
@@ -3056,11 +3564,20 @@
 			if (BP_GET_LEVEL(bp) > 0)
 				hdr->b_flags |= ARC_FLAG_INDIRECT;
 		} else {
-			/* this block is in the ghost cache */
-			ASSERT(GHOST_STATE(hdr->b_state));
+			/*
+			 * This block is in the ghost cache. If it was L2-only
+			 * (and thus didn't have an L1 hdr), we realloc the
+			 * header to add an L1 hdr.
+			 */
+			if (!HDR_HAS_L1HDR(hdr)) {
+				hdr = arc_hdr_realloc(hdr, hdr_l2only_cache,
+				    hdr_full_cache);
+			}
+
+			ASSERT(GHOST_STATE(hdr->b_l1hdr.b_state));
 			ASSERT(!HDR_IO_IN_PROGRESS(hdr));
-			ASSERT0(refcount_count(&hdr->b_refcnt));
-			ASSERT(hdr->b_buf == NULL);
+			ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+			ASSERT(hdr->b_l1hdr.b_buf == NULL);
 
 			/* if this is a prefetch, we don't have a reference */
 			if (*arc_flags & ARC_FLAG_PREFETCH)
@@ -3077,29 +3594,29 @@
 			buf->b_efunc = NULL;
 			buf->b_private = NULL;
 			buf->b_next = NULL;
-			hdr->b_buf = buf;
-			ASSERT(hdr->b_datacnt == 0);
-			hdr->b_datacnt = 1;
+			hdr->b_l1hdr.b_buf = buf;
+			ASSERT0(hdr->b_l1hdr.b_datacnt);
+			hdr->b_l1hdr.b_datacnt = 1;
 			arc_get_data_buf(buf);
 			arc_access(hdr, hash_lock);
 		}
 
-		ASSERT(!GHOST_STATE(hdr->b_state));
+		ASSERT(!GHOST_STATE(hdr->b_l1hdr.b_state));
 
 		acb = kmem_zalloc(sizeof (arc_callback_t), KM_SLEEP);
 		acb->acb_done = done;
 		acb->acb_private = private;
 
-		ASSERT(hdr->b_acb == NULL);
-		hdr->b_acb = acb;
+		ASSERT(hdr->b_l1hdr.b_acb == NULL);
+		hdr->b_l1hdr.b_acb = acb;
 		hdr->b_flags |= ARC_FLAG_IO_IN_PROGRESS;
 
-		if (hdr->b_l2hdr != NULL &&
-		    (vd = hdr->b_l2hdr->b_dev->l2ad_vdev) != NULL) {
-			devw = hdr->b_l2hdr->b_dev->l2ad_writing;
-			addr = hdr->b_l2hdr->b_daddr;
-			b_compress = hdr->b_l2hdr->b_compress;
-			b_asize = hdr->b_l2hdr->b_asize;
+		if (HDR_HAS_L2HDR(hdr) &&
+		    (vd = hdr->b_l2hdr.b_dev->l2ad_vdev) != NULL) {
+			devw = hdr->b_l2hdr.b_dev->l2ad_writing;
+			addr = hdr->b_l2hdr.b_daddr;
+			b_compress = HDR_GET_COMPRESS(hdr);
+			b_asize = hdr->b_l2hdr.b_asize;
 			/*
 			 * Lock out device removal.
 			 */
@@ -3119,8 +3636,8 @@
 		DTRACE_PROBE4(arc__miss, arc_buf_hdr_t *, hdr, blkptr_t *, bp,
 		    uint64_t, size, zbookmark_phys_t *, zb);
 		ARCSTAT_BUMP(arcstat_misses);
-		ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH),
-		    demand, prefetch, hdr->b_type != ARC_BUFC_METADATA,
+		ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr),
+		    demand, prefetch, !HDR_ISTYPE_METADATA(hdr),
 		    data, metadata, misses);
 
 		if (vd != NULL && l2arc_ndev != 0 && !(l2arc_norw && devw)) {
@@ -3133,7 +3650,7 @@
 			 *    also have invalidated the vdev.
 			 * 5. This isn't prefetch and l2arc_noprefetch is set.
 			 */
-			if (hdr->b_l2hdr != NULL &&
+			if (HDR_HAS_L2HDR(hdr) &&
 			    !HDR_L2_WRITING(hdr) && !HDR_L2_EVICTED(hdr) &&
 			    !(l2arc_noprefetch && HDR_PREFETCH(hdr))) {
 				l2arc_read_callback_t *cb;
@@ -3225,8 +3742,9 @@
 arc_set_callback(arc_buf_t *buf, arc_evict_func_t *func, void *private)
 {
 	ASSERT(buf->b_hdr != NULL);
-	ASSERT(buf->b_hdr->b_state != arc_anon);
-	ASSERT(!refcount_is_zero(&buf->b_hdr->b_refcnt) || func == NULL);
+	ASSERT(buf->b_hdr->b_l1hdr.b_state != arc_anon);
+	ASSERT(!refcount_is_zero(&buf->b_hdr->b_l1hdr.b_refcnt) ||
+	    func == NULL);
 	ASSERT(buf->b_efunc == NULL);
 	ASSERT(!HDR_BUF_AVAILABLE(buf->b_hdr));
 
@@ -3250,7 +3768,7 @@
 	if (hdr == NULL)
 		return;
 	if (HDR_BUF_AVAILABLE(hdr)) {
-		arc_buf_t *buf = hdr->b_buf;
+		arc_buf_t *buf = hdr->b_l1hdr.b_buf;
 		add_reference(hdr, hash_lock, FTAG);
 		hdr->b_flags &= ~ARC_FLAG_BUF_AVAILABLE;
 		mutex_exit(hash_lock);
@@ -3308,17 +3826,19 @@
 	hdr = buf->b_hdr;
 	ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
 
-	ASSERT3U(refcount_count(&hdr->b_refcnt), <, hdr->b_datacnt);
-	ASSERT(hdr->b_state == arc_mru || hdr->b_state == arc_mfu);
+	ASSERT3U(refcount_count(&hdr->b_l1hdr.b_refcnt), <,
+	    hdr->b_l1hdr.b_datacnt);
+	ASSERT(hdr->b_l1hdr.b_state == arc_mru ||
+	    hdr->b_l1hdr.b_state == arc_mfu);
 
 	buf->b_efunc = NULL;
 	buf->b_private = NULL;
 
-	if (hdr->b_datacnt > 1) {
+	if (hdr->b_l1hdr.b_datacnt > 1) {
 		mutex_exit(&buf->b_evict_lock);
 		arc_buf_destroy(buf, FALSE, TRUE);
 	} else {
-		ASSERT(buf == hdr->b_buf);
+		ASSERT(buf == hdr->b_l1hdr.b_buf);
 		hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE;
 		mutex_exit(&buf->b_evict_lock);
 	}
@@ -3337,10 +3857,7 @@
 void
 arc_release(arc_buf_t *buf, void *tag)
 {
-	arc_buf_hdr_t *hdr;
-	kmutex_t *hash_lock = NULL;
-	l2arc_buf_hdr_t *l2hdr;
-	uint64_t buf_size;
+	arc_buf_hdr_t *hdr = buf->b_hdr;
 
 	/*
 	 * It would be nice to assert that if it's DMU metadata (level >
@@ -3349,56 +3866,87 @@
 	 */
 
 	mutex_enter(&buf->b_evict_lock);
-	hdr = buf->b_hdr;
+
+	/*
+	 * We don't grab the hash lock prior to this check, because if
+	 * the buffer's header is in the arc_anon state, it won't be
+	 * linked into the hash table.
+	 */
+	if (hdr->b_l1hdr.b_state == arc_anon) {
+		mutex_exit(&buf->b_evict_lock);
+		ASSERT(!HDR_IO_IN_PROGRESS(hdr));
+		ASSERT(!HDR_IN_HASH_TABLE(hdr));
+		ASSERT(!HDR_HAS_L2HDR(hdr));
+		ASSERT(BUF_EMPTY(hdr));
+
+		ASSERT3U(hdr->b_l1hdr.b_datacnt, ==, 1);
+		ASSERT3S(refcount_count(&hdr->b_l1hdr.b_refcnt), ==, 1);
+		ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node));
+
+		ASSERT3P(buf->b_efunc, ==, NULL);
+		ASSERT3P(buf->b_private, ==, NULL);
+
+		hdr->b_l1hdr.b_arc_access = 0;
+		arc_buf_thaw(buf);
+
+		return;
+	}
+
+	kmutex_t *hash_lock = HDR_LOCK(hdr);
+	mutex_enter(hash_lock);
+
+	/*
+	 * This assignment is only valid as long as the hash_lock is
+	 * held, we must be careful not to reference state or the
+	 * b_state field after dropping the lock.
+	 */
+	arc_state_t *state = hdr->b_l1hdr.b_state;
+	ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
+	ASSERT3P(state, !=, arc_anon);
 
 	/* this buffer is not on any list */
-	ASSERT(refcount_count(&hdr->b_refcnt) > 0);
-
-	if (hdr->b_state == arc_anon) {
-		/* this buffer is already released */
-		ASSERT(buf->b_efunc == NULL);
-	} else {
-		hash_lock = HDR_LOCK(hdr);
-		mutex_enter(hash_lock);
-		hdr = buf->b_hdr;
-		ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
+	ASSERT(refcount_count(&hdr->b_l1hdr.b_refcnt) > 0);
+
+	if (HDR_HAS_L2HDR(hdr)) {
+		ARCSTAT_INCR(arcstat_l2_asize, -hdr->b_l2hdr.b_asize);
+		ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
+
+		mutex_enter(&hdr->b_l2hdr.b_dev->l2ad_mtx);
+		list_remove(&hdr->b_l2hdr.b_dev->l2ad_buflist, hdr);
+		mutex_exit(&hdr->b_l2hdr.b_dev->l2ad_mtx);
+
+		hdr->b_flags &= ~ARC_FLAG_HAS_L2HDR;
 	}
 
-	l2hdr = hdr->b_l2hdr;
-	if (l2hdr) {
-		mutex_enter(&l2arc_buflist_mtx);
-		hdr->b_l2hdr = NULL;
-		list_remove(l2hdr->b_dev->l2ad_buflist, hdr);
-	}
-	buf_size = hdr->b_size;
-
 	/*
 	 * Do we have more than one buf?
 	 */
-	if (hdr->b_datacnt > 1) {
+	if (hdr->b_l1hdr.b_datacnt > 1) {
 		arc_buf_hdr_t *nhdr;
 		arc_buf_t **bufp;
 		uint64_t blksz = hdr->b_size;
 		uint64_t spa = hdr->b_spa;
-		arc_buf_contents_t type = hdr->b_type;
+		arc_buf_contents_t type = arc_buf_type(hdr);
 		uint32_t flags = hdr->b_flags;
 
-		ASSERT(hdr->b_buf != buf || buf->b_next != NULL);
+		ASSERT(hdr->b_l1hdr.b_buf != buf || buf->b_next != NULL);
 		/*
 		 * Pull the data off of this hdr and attach it to
 		 * a new anonymous hdr.
 		 */
 		(void) remove_reference(hdr, hash_lock, tag);
-		bufp = &hdr->b_buf;
+		bufp = &hdr->b_l1hdr.b_buf;
 		while (*bufp != buf)
 			bufp = &(*bufp)->b_next;
 		*bufp = buf->b_next;
 		buf->b_next = NULL;
 
-		ASSERT3U(hdr->b_state->arcs_size, >=, hdr->b_size);
-		atomic_add_64(&hdr->b_state->arcs_size, -hdr->b_size);
-		if (refcount_is_zero(&hdr->b_refcnt)) {
-			uint64_t *size = &hdr->b_state->arcs_lsize[hdr->b_type];
+		ASSERT3P(state, !=, arc_l2c_only);
+		ASSERT3U(state->arcs_size, >=, hdr->b_size);
+		atomic_add_64(&state->arcs_size, -hdr->b_size);
+		if (refcount_is_zero(&hdr->b_l1hdr.b_refcnt)) {
+			ASSERT3P(state, !=, arc_l2c_only);
+			uint64_t *size = &state->arcs_lsize[type];
 			ASSERT3U(*size, >=, hdr->b_size);
 			atomic_add_64(size, -hdr->b_size);
 		}
@@ -3407,57 +3955,50 @@
 		 * We're releasing a duplicate user data buffer, update
 		 * our statistics accordingly.
 		 */
-		if (hdr->b_type == ARC_BUFC_DATA) {
+		if (HDR_ISTYPE_DATA(hdr)) {
 			ARCSTAT_BUMPDOWN(arcstat_duplicate_buffers);
 			ARCSTAT_INCR(arcstat_duplicate_buffers_size,
 			    -hdr->b_size);
 		}
-		hdr->b_datacnt -= 1;
+		hdr->b_l1hdr.b_datacnt -= 1;
 		arc_cksum_verify(buf);
 		arc_buf_unwatch(buf);
 
 		mutex_exit(hash_lock);
 
-		nhdr = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE);
+		nhdr = kmem_cache_alloc(hdr_full_cache, KM_PUSHPAGE);
 		nhdr->b_size = blksz;
 		nhdr->b_spa = spa;
-		nhdr->b_type = type;
-		nhdr->b_buf = buf;
-		nhdr->b_state = arc_anon;
-		nhdr->b_arc_access = 0;
+
 		nhdr->b_flags = flags & ARC_FLAG_L2_WRITING;
-		nhdr->b_l2hdr = NULL;
-		nhdr->b_datacnt = 1;
+		nhdr->b_flags |= arc_bufc_to_flags(type);
+		nhdr->b_flags |= ARC_FLAG_HAS_L1HDR;
+
+		nhdr->b_l1hdr.b_buf = buf;
+		nhdr->b_l1hdr.b_datacnt = 1;
+		nhdr->b_l1hdr.b_state = arc_anon;
+		nhdr->b_l1hdr.b_arc_access = 0;
 		nhdr->b_freeze_cksum = NULL;
-		(void) refcount_add(&nhdr->b_refcnt, tag);
+
+		(void) refcount_add(&nhdr->b_l1hdr.b_refcnt, tag);
 		buf->b_hdr = nhdr;
 		mutex_exit(&buf->b_evict_lock);
 		atomic_add_64(&arc_anon->arcs_size, blksz);
 	} else {
 		mutex_exit(&buf->b_evict_lock);
-		ASSERT(refcount_count(&hdr->b_refcnt) == 1);
-		ASSERT(!list_link_active(&hdr->b_arc_node));
+		ASSERT(refcount_count(&hdr->b_l1hdr.b_refcnt) == 1);
+		/* protected by hash lock */
+		ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node));
 		ASSERT(!HDR_IO_IN_PROGRESS(hdr));
-		if (hdr->b_state != arc_anon)
-			arc_change_state(arc_anon, hdr, hash_lock);
-		hdr->b_arc_access = 0;
-		if (hash_lock)
-			mutex_exit(hash_lock);
+		arc_change_state(arc_anon, hdr, hash_lock);
+		hdr->b_l1hdr.b_arc_access = 0;
+		mutex_exit(hash_lock);
 
 		buf_discard_identity(hdr);
 		arc_buf_thaw(buf);
 	}
 	buf->b_efunc = NULL;
 	buf->b_private = NULL;
-
-	if (l2hdr) {
-		ARCSTAT_INCR(arcstat_l2_asize, -l2hdr->b_asize);
-		vdev_space_update(l2hdr->b_dev->l2ad_vdev,
-		    -l2hdr->b_asize, 0, 0);
-		kmem_free(l2hdr, sizeof (l2arc_buf_hdr_t));
-		ARCSTAT_INCR(arcstat_l2_size, -buf_size);
-		mutex_exit(&l2arc_buflist_mtx);
-	}
 }
 
 int
@@ -3466,7 +4007,8 @@
 	int released;
 
 	mutex_enter(&buf->b_evict_lock);
-	released = (buf->b_data != NULL && buf->b_hdr->b_state == arc_anon);
+	released = (buf->b_data != NULL &&
+	    buf->b_hdr->b_l1hdr.b_state == arc_anon);
 	mutex_exit(&buf->b_evict_lock);
 	return (released);
 }
@@ -3478,7 +4020,7 @@
 	int referenced;
 
 	mutex_enter(&buf->b_evict_lock);
-	referenced = (refcount_count(&buf->b_hdr->b_refcnt));
+	referenced = (refcount_count(&buf->b_hdr->b_l1hdr.b_refcnt));
 	mutex_exit(&buf->b_evict_lock);
 	return (referenced);
 }
@@ -3491,7 +4033,9 @@
 	arc_buf_t *buf = callback->awcb_buf;
 	arc_buf_hdr_t *hdr = buf->b_hdr;
 
-	ASSERT(!refcount_is_zero(&buf->b_hdr->b_refcnt));
+	ASSERT(HDR_HAS_L1HDR(hdr));
+	ASSERT(!refcount_is_zero(&buf->b_hdr->b_l1hdr.b_refcnt));
+	ASSERT(hdr->b_l1hdr.b_datacnt > 0);
 	callback->awcb_ready(zio, buf, callback->awcb_private);
 
 	/*
@@ -3501,12 +4045,12 @@
 	 * accounting for any re-write attempt.
 	 */
 	if (HDR_IO_IN_PROGRESS(hdr)) {
-		mutex_enter(&hdr->b_freeze_lock);
+		mutex_enter(&hdr->b_l1hdr.b_freeze_lock);
 		if (hdr->b_freeze_cksum != NULL) {
 			kmem_free(hdr->b_freeze_cksum, sizeof (zio_cksum_t));
 			hdr->b_freeze_cksum = NULL;
 		}
-		mutex_exit(&hdr->b_freeze_lock);
+		mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
 	}
 	arc_cksum_compute(buf, B_FALSE);
 	hdr->b_flags |= ARC_FLAG_IO_IN_PROGRESS;
@@ -3531,7 +4075,7 @@
 	arc_buf_t *buf = callback->awcb_buf;
 	arc_buf_hdr_t *hdr = buf->b_hdr;
 
-	ASSERT(hdr->b_acb == NULL);
+	ASSERT(hdr->b_l1hdr.b_acb == NULL);
 
 	if (zio->io_error == 0) {
 		if (BP_IS_HOLE(zio->io_bp) || BP_IS_EMBEDDED(zio->io_bp)) {
@@ -3539,7 +4083,6 @@
 		} else {
 			hdr->b_dva = *BP_IDENTITY(zio->io_bp);
 			hdr->b_birth = BP_PHYSICAL_BIRTH(zio->io_bp);
-			hdr->b_cksum0 = zio->io_bp->blk_cksum.zc_word[0];
 		}
 	} else {
 		ASSERT(BUF_EMPTY(hdr));
@@ -3560,7 +4103,7 @@
 		arc_cksum_verify(buf);
 
 		exists = buf_hash_insert(hdr, &hash_lock);
-		if (exists) {
+		if (exists != NULL) {
 			/*
 			 * This can only happen if we overwrite for
 			 * sync-to-convergence, because we remove
@@ -3570,7 +4113,8 @@
 				if (!BP_EQUAL(&zio->io_bp_orig, zio->io_bp))
 					panic("bad overwrite, hdr=%p exists=%p",
 					    (void *)hdr, (void *)exists);
-				ASSERT(refcount_is_zero(&exists->b_refcnt));
+				ASSERT(refcount_is_zero(
+				    &exists->b_l1hdr.b_refcnt));
 				arc_change_state(arc_anon, exists, hash_lock);
 				mutex_exit(hash_lock);
 				arc_hdr_destroy(exists);
@@ -3584,22 +4128,22 @@
 					    (void *)hdr, (void *)exists);
 			} else {
 				/* Dedup */
-				ASSERT(hdr->b_datacnt == 1);
-				ASSERT(hdr->b_state == arc_anon);
+				ASSERT(hdr->b_l1hdr.b_datacnt == 1);
+				ASSERT(hdr->b_l1hdr.b_state == arc_anon);
 				ASSERT(BP_GET_DEDUP(zio->io_bp));
 				ASSERT(BP_GET_LEVEL(zio->io_bp) == 0);
 			}
 		}
 		hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS;
 		/* if it's not anon, we are doing a scrub */
-		if (!exists && hdr->b_state == arc_anon)
+		if (exists == NULL && hdr->b_l1hdr.b_state == arc_anon)
 			arc_access(hdr, hash_lock);
 		mutex_exit(hash_lock);
 	} else {
 		hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS;
 	}
 
-	ASSERT(!refcount_is_zero(&hdr->b_refcnt));
+	ASSERT(!refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 	callback->awcb_done(zio, buf, callback->awcb_private);
 
 	kmem_free(callback, sizeof (arc_write_callback_t));
@@ -3619,8 +4163,9 @@
 	ASSERT(ready != NULL);
 	ASSERT(done != NULL);
 	ASSERT(!HDR_IO_ERROR(hdr));
-	ASSERT((hdr->b_flags & ARC_FLAG_IO_IN_PROGRESS) == 0);
-	ASSERT(hdr->b_acb == NULL);
+	ASSERT(!HDR_IO_IN_PROGRESS(hdr));
+	ASSERT(hdr->b_l1hdr.b_acb == NULL);
+	ASSERT(hdr->b_l1hdr.b_datacnt > 0);
 	if (l2arc)
 		hdr->b_flags |= ARC_FLAG_L2CACHE;
 	if (l2arc_compress)
@@ -3736,9 +4281,60 @@
 	return (0);
 }
 
+static void
+arc_kstat_update_state(arc_state_t *state, kstat_named_t *size,
+    kstat_named_t *evict_data, kstat_named_t *evict_metadata)
+{
+	size->value.ui64 = state->arcs_size;
+	evict_data->value.ui64 = state->arcs_lsize[ARC_BUFC_DATA];
+	evict_metadata->value.ui64 = state->arcs_lsize[ARC_BUFC_METADATA];
+}
+
+static int
+arc_kstat_update(kstat_t *ksp, int rw)
+{
+	arc_stats_t *as = ksp->ks_data;
+
+	if (rw == KSTAT_WRITE) {
+		return (EACCES);
+	} else {
+		arc_kstat_update_state(arc_anon,
+		    &as->arcstat_anon_size,
+		    &as->arcstat_anon_evictable_data,
+		    &as->arcstat_anon_evictable_metadata);
+		arc_kstat_update_state(arc_mru,
+		    &as->arcstat_mru_size,
+		    &as->arcstat_mru_evictable_data,
+		    &as->arcstat_mru_evictable_metadata);
+		arc_kstat_update_state(arc_mru_ghost,
+		    &as->arcstat_mru_ghost_size,
+		    &as->arcstat_mru_ghost_evictable_data,
+		    &as->arcstat_mru_ghost_evictable_metadata);
+		arc_kstat_update_state(arc_mfu,
+		    &as->arcstat_mfu_size,
+		    &as->arcstat_mfu_evictable_data,
+		    &as->arcstat_mfu_evictable_metadata);
+		arc_kstat_update_state(arc_mfu_ghost,
+		    &as->arcstat_mfu_ghost_size,
+		    &as->arcstat_mfu_ghost_evictable_data,
+		    &as->arcstat_mfu_ghost_evictable_metadata);
+	}
+
+	return (0);
+}
+
 void
 arc_init(void)
 {
+	/*
+	 * allmem is "all memory that we could possibly use".
+	 */
+#ifdef _KERNEL
+	uint64_t allmem = ptob(physmem - swapfs_minfree);
+#else
+	uint64_t allmem = (physmem * PAGESIZE) / 2;
+#endif
+
 	mutex_init(&arc_reclaim_thr_lock, NULL, MUTEX_DEFAULT, NULL);
 	cv_init(&arc_reclaim_thr_cv, NULL, CV_DEFAULT, NULL);
 
@@ -3746,7 +4342,7 @@
 	arc_min_prefetch_lifespan = 1 * hz;
 
 	/* Start out with 1/8 of all memory */
-	arc_c = physmem * PAGESIZE / 8;
+	arc_c = allmem / 8;
 
 #ifdef _KERNEL
 	/*
@@ -3758,21 +4354,21 @@
 #endif
 
 	/* set min cache to 1/32 of all memory, or 64MB, whichever is more */
-	arc_c_min = MAX(arc_c / 4, 64<<20);
+	arc_c_min = MAX(allmem / 32, 64 << 20);
 	/* set max to 3/4 of all memory, or all but 1GB, whichever is more */
-	if (arc_c * 8 >= 1<<30)
-		arc_c_max = (arc_c * 8) - (1<<30);
+	if (allmem >= 1 << 30)
+		arc_c_max = allmem - (1 << 30);
 	else
 		arc_c_max = arc_c_min;
-	arc_c_max = MAX(arc_c * 6, arc_c_max);
+	arc_c_max = MAX(allmem * 3 / 4, arc_c_max);
 
 	/*
 	 * Allow the tunables to override our calculations if they are
 	 * reasonable (ie. over 64MB)
 	 */
-	if (zfs_arc_max > 64<<20 && zfs_arc_max < physmem * PAGESIZE)
+	if (zfs_arc_max > 64 << 20 && zfs_arc_max < allmem)
 		arc_c_max = zfs_arc_max;
-	if (zfs_arc_min > 64<<20 && zfs_arc_min <= arc_c_max)
+	if (zfs_arc_min > 64 << 20 && zfs_arc_min <= arc_c_max)
 		arc_c_min = zfs_arc_min;
 
 	arc_c = arc_c_max;
@@ -3800,6 +4396,12 @@
 	if (zfs_arc_shrink_shift > 0)
 		arc_shrink_shift = zfs_arc_shrink_shift;
 
+	/*
+	 * Ensure that arc_no_grow_shift is less than arc_shrink_shift.
+	 */
+	if (arc_no_grow_shift >= arc_shrink_shift)
+		arc_no_grow_shift = arc_shrink_shift - 1;
+
 	if (zfs_arc_p_min_shift > 0)
 		arc_p_min_shift = zfs_arc_p_min_shift;
 
@@ -3825,25 +4427,35 @@
 	mutex_init(&arc_l2c_only->arcs_mtx, NULL, MUTEX_DEFAULT, NULL);
 
 	list_create(&arc_mru->arcs_list[ARC_BUFC_METADATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_mru->arcs_list[ARC_BUFC_DATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_mru_ghost->arcs_list[ARC_BUFC_METADATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_mru_ghost->arcs_list[ARC_BUFC_DATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_mfu->arcs_list[ARC_BUFC_METADATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_mfu->arcs_list[ARC_BUFC_DATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_mfu_ghost->arcs_list[ARC_BUFC_METADATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_mfu_ghost->arcs_list[ARC_BUFC_DATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_l2c_only->arcs_list[ARC_BUFC_METADATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 	list_create(&arc_l2c_only->arcs_list[ARC_BUFC_DATA],
-	    sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node));
+	    sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node));
 
 	buf_init();
 
@@ -3857,6 +4469,7 @@
 
 	if (arc_ksp != NULL) {
 		arc_ksp->ks_data = &arc_stats;
+		arc_ksp->ks_update = arc_kstat_update;
 		kstat_install(arc_ksp);
 	}
 
@@ -3922,7 +4535,7 @@
 
 	buf_fini();
 
-	ASSERT(arc_loaned_bytes == 0);
+	ASSERT0(arc_loaned_bytes);
 }
 
 /*
@@ -4080,7 +4693,7 @@
 	 * 3. has an I/O in progress (it may be an incomplete read).
 	 * 4. is flagged not eligible (zfs property).
 	 */
-	if (hdr->b_spa != spa_guid || hdr->b_l2hdr != NULL ||
+	if (hdr->b_spa != spa_guid || HDR_HAS_L2HDR(hdr) ||
 	    HDR_IO_IN_PROGRESS(hdr) || !HDR_L2CACHE(hdr))
 		return (B_FALSE);
 
@@ -4133,20 +4746,6 @@
 	return (next);
 }
 
-static void
-l2arc_hdr_stat_add(void)
-{
-	ARCSTAT_INCR(arcstat_l2_hdr_size, HDR_SIZE + L2HDR_SIZE);
-	ARCSTAT_INCR(arcstat_hdr_size, -HDR_SIZE);
-}
-
-static void
-l2arc_hdr_stat_remove(void)
-{
-	ARCSTAT_INCR(arcstat_l2_hdr_size, -(HDR_SIZE + L2HDR_SIZE));
-	ARCSTAT_INCR(arcstat_hdr_size, HDR_SIZE);
-}
-
 /*
  * Cycle through L2ARC devices.  This is how L2ARC load balances.
  * If a device is returned, this also returns holding the spa config lock.
@@ -4243,7 +4842,6 @@
 	l2arc_dev_t *dev;
 	list_t *buflist;
 	arc_buf_hdr_t *head, *hdr, *hdr_prev;
-	l2arc_buf_hdr_t *abl2;
 	kmutex_t *hash_lock;
 	int64_t bytes_dropped = 0;
 
@@ -4253,7 +4851,7 @@
 	ASSERT(dev != NULL);
 	head = cb->l2wcb_head;
 	ASSERT(head != NULL);
-	buflist = dev->l2ad_buflist;
+	buflist = &dev->l2ad_buflist;
 	ASSERT(buflist != NULL);
 	DTRACE_PROBE2(l2arc__iodone, zio_t *, zio,
 	    l2arc_write_callback_t *, cb);
@@ -4261,41 +4859,43 @@
 	if (zio->io_error != 0)
 		ARCSTAT_BUMP(arcstat_l2_writes_error);
 
-	mutex_enter(&l2arc_buflist_mtx);
+	mutex_enter(&dev->l2ad_mtx);
 
 	/*
 	 * All writes completed, or an error was hit.
 	 */
 	for (hdr = list_prev(buflist, head); hdr; hdr = hdr_prev) {
 		hdr_prev = list_prev(buflist, hdr);
-		abl2 = hdr->b_l2hdr;
-
-		/*
-		 * Release the temporary compressed buffer as soon as possible.
-		 */
-		if (abl2->b_compress != ZIO_COMPRESS_OFF)
-			l2arc_release_cdata_buf(hdr);
 
 		hash_lock = HDR_LOCK(hdr);
 		if (!mutex_tryenter(hash_lock)) {
 			/*
 			 * This buffer misses out.  It may be in a stage
-			 * of eviction.  Its ARC_L2_WRITING flag will be
+			 * of eviction.  Its ARC_FLAG_L2_WRITING flag will be
 			 * left set, denying reads to this buffer.
 			 */
 			ARCSTAT_BUMP(arcstat_l2_writes_hdr_miss);
 			continue;
 		}
 
+		/*
+		 * It's possible that this buffer got evicted from the L1 cache
+		 * before we grabbed the vdev + hash locks, in which case
+		 * arc_hdr_realloc freed b_tmp_cdata for us if it was allocated.
+		 * Only free the buffer if we still have an L1 hdr.
+		 */
+		if (HDR_HAS_L1HDR(hdr) && hdr->b_l1hdr.b_tmp_cdata != NULL &&
+		    HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_OFF)
+			l2arc_release_cdata_buf(hdr);
+
 		if (zio->io_error != 0) {
 			/*
 			 * Error - drop L2ARC entry.
 			 */
 			list_remove(buflist, hdr);
-			ARCSTAT_INCR(arcstat_l2_asize, -abl2->b_asize);
-			bytes_dropped += abl2->b_asize;
-			hdr->b_l2hdr = NULL;
-			kmem_free(abl2, sizeof (l2arc_buf_hdr_t));
+			hdr->b_flags &= ~ARC_FLAG_HAS_L2HDR;
+
+			ARCSTAT_INCR(arcstat_l2_asize, -hdr->b_l2hdr.b_asize);
 			ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
 		}
 
@@ -4309,8 +4909,9 @@
 
 	atomic_inc_64(&l2arc_writes_done);
 	list_remove(buflist, head);
-	kmem_cache_free(hdr_cache, head);
-	mutex_exit(&l2arc_buflist_mtx);
+	ASSERT(!HDR_HAS_L1HDR(head));
+	kmem_cache_free(hdr_l2only_cache, head);
+	mutex_exit(&dev->l2ad_mtx);
 
 	vdev_space_update(dev->l2ad_vdev, -bytes_dropped, 0, 0);
 
@@ -4448,16 +5049,12 @@
 l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all)
 {
 	list_t *buflist;
-	l2arc_buf_hdr_t *abl2;
 	arc_buf_hdr_t *hdr, *hdr_prev;
 	kmutex_t *hash_lock;
 	uint64_t taddr;
 	int64_t bytes_evicted = 0;
 
-	buflist = dev->l2ad_buflist;
-
-	if (buflist == NULL)
-		return;
+	buflist = &dev->l2ad_buflist;
 
 	if (!all && dev->l2ad_first) {
 		/*
@@ -4480,7 +5077,7 @@
 	    uint64_t, taddr, boolean_t, all);
 
 top:
-	mutex_enter(&l2arc_buflist_mtx);
+	mutex_enter(&dev->l2ad_mtx);
 	for (hdr = list_tail(buflist); hdr; hdr = hdr_prev) {
 		hdr_prev = list_prev(buflist, hdr);
 
@@ -4490,7 +5087,7 @@
 			 * Missed the hash lock.  Retry.
 			 */
 			ARCSTAT_BUMP(arcstat_l2_evict_lock_retry);
-			mutex_exit(&l2arc_buflist_mtx);
+			mutex_exit(&dev->l2ad_mtx);
 			mutex_enter(hash_lock);
 			mutex_exit(hash_lock);
 			goto top;
@@ -4506,9 +5103,9 @@
 			continue;
 		}
 
-		if (!all && hdr->b_l2hdr != NULL &&
-		    (hdr->b_l2hdr->b_daddr > taddr ||
-		    hdr->b_l2hdr->b_daddr < dev->l2ad_hand)) {
+		if (!all && HDR_HAS_L2HDR(hdr) &&
+		    (hdr->b_l2hdr.b_daddr > taddr ||
+		    hdr->b_l2hdr.b_daddr < dev->l2ad_hand)) {
 			/*
 			 * We've evicted to the target address,
 			 * or the end of the device.
@@ -4517,15 +5114,8 @@
 			break;
 		}
 
-		if (HDR_FREE_IN_PROGRESS(hdr)) {
-			/*
-			 * Already on the path to destruction.
-			 */
-			mutex_exit(hash_lock);
-			continue;
-		}
-
-		if (hdr->b_state == arc_l2c_only) {
+		ASSERT(HDR_HAS_L2HDR(hdr));
+		if (!HDR_HAS_L1HDR(hdr)) {
 			ASSERT(!HDR_L2_READING(hdr));
 			/*
 			 * This doesn't exist in the ARC.  Destroy.
@@ -4535,6 +5125,8 @@
 			arc_change_state(arc_anon, hdr, hash_lock);
 			arc_hdr_destroy(hdr);
 		} else {
+			ASSERT(hdr->b_l1hdr.b_state != arc_l2c_only);
+			ARCSTAT_BUMP(arcstat_l2_evict_l1cached);
 			/*
 			 * Invalidate issued or about to be issued
 			 * reads, since we may be about to write
@@ -4545,28 +5137,18 @@
 				hdr->b_flags |= ARC_FLAG_L2_EVICTED;
 			}
 
-			/*
-			 * Tell ARC this no longer exists in L2ARC.
-			 */
-			if (hdr->b_l2hdr != NULL) {
-				abl2 = hdr->b_l2hdr;
-				ARCSTAT_INCR(arcstat_l2_asize, -abl2->b_asize);
-				bytes_evicted += abl2->b_asize;
-				hdr->b_l2hdr = NULL;
-				kmem_free(abl2, sizeof (l2arc_buf_hdr_t));
-				ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
-			}
+			/* Tell ARC this no longer exists in L2ARC. */
+			ARCSTAT_INCR(arcstat_l2_asize, -hdr->b_l2hdr.b_asize);
+			ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
+			hdr->b_flags &= ~ARC_FLAG_HAS_L2HDR;
 			list_remove(buflist, hdr);
 
-			/*
-			 * This may have been leftover after a
-			 * failed write.
-			 */
+			/* This may have been leftover after a failed write. */
 			hdr->b_flags &= ~ARC_FLAG_L2_WRITING;
 		}
 		mutex_exit(hash_lock);
 	}
-	mutex_exit(&l2arc_buflist_mtx);
+	mutex_exit(&dev->l2ad_mtx);
 
 	vdev_space_update(dev->l2ad_vdev, -bytes_evicted, 0, 0);
 	dev->l2ad_evict = taddr;
@@ -4607,8 +5189,9 @@
 	pio = NULL;
 	write_sz = write_asize = write_psize = 0;
 	full = B_FALSE;
-	head = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE);
+	head = kmem_cache_alloc(hdr_l2only_cache, KM_PUSHPAGE);
 	head->b_flags |= ARC_FLAG_L2_WRITE_HEAD;
+	head->b_flags |= ARC_FLAG_HAS_L2HDR;
 
 	/*
 	 * We will want to try to compress buffers that are at least 2x the
@@ -4619,7 +5202,7 @@
 	/*
 	 * Copy buffers for L2ARC writing.
 	 */
-	mutex_enter(&l2arc_buflist_mtx);
+	mutex_enter(&dev->l2ad_mtx);
 	for (int try = 0; try <= 3; try++) {
 		uint64_t passed_sz = 0;
 
@@ -4641,7 +5224,6 @@
 			headroom = (headroom * l2arc_headroom_boost) / 100;
 
 		for (; hdr; hdr = hdr_prev) {
-			l2arc_buf_hdr_t *l2hdr;
 			kmutex_t *hash_lock;
 			uint64_t buf_sz;
 
@@ -4684,7 +5266,7 @@
 				 * l2arc_write_done() can find where the
 				 * write buffers begin without searching.
 				 */
-				list_insert_head(dev->l2ad_buflist, head);
+				list_insert_head(&dev->l2ad_buflist, head);
 
 				cb = kmem_alloc(
 				    sizeof (l2arc_write_callback_t), KM_SLEEP);
@@ -4697,33 +5279,31 @@
 			/*
 			 * Create and add a new L2ARC header.
 			 */
-			l2hdr = kmem_zalloc(sizeof (l2arc_buf_hdr_t), KM_SLEEP);
-			l2hdr->b_dev = dev;
+			hdr->b_l2hdr.b_dev = dev;
 			hdr->b_flags |= ARC_FLAG_L2_WRITING;
-
 			/*
 			 * Temporarily stash the data buffer in b_tmp_cdata.
 			 * The subsequent write step will pick it up from
-			 * there. This is because can't access hdr->b_buf
+			 * there. This is because can't access b_l1hdr.b_buf
 			 * without holding the hash_lock, which we in turn
 			 * can't access without holding the ARC list locks
 			 * (which we want to avoid during compression/writing).
 			 */
-			l2hdr->b_compress = ZIO_COMPRESS_OFF;
-			l2hdr->b_asize = hdr->b_size;
-			l2hdr->b_tmp_cdata = hdr->b_buf->b_data;
+			HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_OFF);
+			hdr->b_l2hdr.b_asize = hdr->b_size;
+			hdr->b_l1hdr.b_tmp_cdata = hdr->b_l1hdr.b_buf->b_data;
 
 			buf_sz = hdr->b_size;
-			hdr->b_l2hdr = l2hdr;
-
-			list_insert_head(dev->l2ad_buflist, hdr);
+			hdr->b_flags |= ARC_FLAG_HAS_L2HDR;
+
+			list_insert_head(&dev->l2ad_buflist, hdr);
 
 			/*
 			 * Compute and store the buffer cksum before
 			 * writing.  On debug the cksum is verified first.
 			 */
-			arc_cksum_verify(hdr->b_buf);
-			arc_cksum_compute(hdr->b_buf, B_TRUE);
+			arc_cksum_verify(hdr->b_l1hdr.b_buf);
+			arc_cksum_compute(hdr->b_l1hdr.b_buf, B_TRUE);
 
 			mutex_exit(hash_lock);
 
@@ -4739,8 +5319,9 @@
 	/* No buffers selected for writing? */
 	if (pio == NULL) {
 		ASSERT0(write_sz);
-		mutex_exit(&l2arc_buflist_mtx);
-		kmem_cache_free(hdr_cache, head);
+		mutex_exit(&dev->l2ad_mtx);
+		ASSERT(!HDR_HAS_L1HDR(head));
+		kmem_cache_free(hdr_l2only_cache, head);
 		return (0);
 	}
 
@@ -4749,24 +5330,22 @@
 	 * and work backwards, retracing the course of the buffer selector
 	 * loop above.
 	 */
-	for (hdr = list_prev(dev->l2ad_buflist, head); hdr;
-	    hdr = list_prev(dev->l2ad_buflist, hdr)) {
-		l2arc_buf_hdr_t *l2hdr;
+	for (hdr = list_prev(&dev->l2ad_buflist, head); hdr;
+	    hdr = list_prev(&dev->l2ad_buflist, hdr)) {
 		uint64_t buf_sz;
 
 		/*
 		 * We shouldn't need to lock the buffer here, since we flagged
 		 * it as ARC_FLAG_L2_WRITING in the previous step, but we must
 		 * take care to only access its L2 cache parameters. In
-		 * particular, hdr->b_buf may be invalid by now due to
+		 * particular, hdr->l1hdr.b_buf may be invalid by now due to
 		 * ARC eviction.
 		 */
-		l2hdr = hdr->b_l2hdr;
-		l2hdr->b_daddr = dev->l2ad_hand;
-
-		if ((hdr->b_flags & ARC_FLAG_L2COMPRESS) &&
-		    l2hdr->b_asize >= buf_compress_minsz) {
-			if (l2arc_compress_buf(l2hdr)) {
+		hdr->b_l2hdr.b_daddr = dev->l2ad_hand;
+
+		if ((HDR_L2COMPRESS(hdr)) &&
+		    hdr->b_l2hdr.b_asize >= buf_compress_minsz) {
+			if (l2arc_compress_buf(hdr)) {
 				/*
 				 * If compression succeeded, enable headroom
 				 * boost on the next scan cycle.
@@ -4779,8 +5358,8 @@
 		 * Pick up the buffer data we had previously stashed away
 		 * (and now potentially also compressed).
 		 */
-		buf_data = l2hdr->b_tmp_cdata;
-		buf_sz = l2hdr->b_asize;
+		buf_data = hdr->b_l1hdr.b_tmp_cdata;
+		buf_sz = hdr->b_l2hdr.b_asize;
 
 		/* Compression may have squashed the buffer to zero length. */
 		if (buf_sz != 0) {
@@ -4805,7 +5384,7 @@
 		}
 	}
 
-	mutex_exit(&l2arc_buflist_mtx);
+	mutex_exit(&dev->l2ad_mtx);
 
 	ASSERT3U(write_asize, <=, target_sz);
 	ARCSTAT_BUMP(arcstat_l2_writes_sent);
@@ -4833,7 +5412,7 @@
 
 /*
  * Compresses an L2ARC buffer.
- * The data to be compressed must be prefilled in l2hdr->b_tmp_cdata and its
+ * The data to be compressed must be prefilled in l1hdr.b_tmp_cdata and its
  * size in l2hdr->b_asize. This routine tries to compress the data and
  * depending on the compression result there are three possible outcomes:
  * *) The buffer was incompressible. The original l2hdr contents were left
@@ -4851,17 +5430,21 @@
  * buffer was incompressible).
  */
 static boolean_t
-l2arc_compress_buf(l2arc_buf_hdr_t *l2hdr)
+l2arc_compress_buf(arc_buf_hdr_t *hdr)
 {
 	void *cdata;
 	size_t csize, len, rounded;
-
-	ASSERT(l2hdr->b_compress == ZIO_COMPRESS_OFF);
-	ASSERT(l2hdr->b_tmp_cdata != NULL);
+	ASSERT(HDR_HAS_L2HDR(hdr));
+	l2arc_buf_hdr_t *l2hdr = &hdr->b_l2hdr;
+
+	ASSERT(HDR_HAS_L1HDR(hdr));
+	ASSERT(HDR_GET_COMPRESS(hdr) == ZIO_COMPRESS_OFF);
+	ASSERT(hdr->b_l1hdr.b_tmp_cdata != NULL);
 
 	len = l2hdr->b_asize;
 	cdata = zio_data_buf_alloc(len);
-	csize = zio_compress_data(ZIO_COMPRESS_LZ4, l2hdr->b_tmp_cdata,
+	ASSERT3P(cdata, !=, NULL);
+	csize = zio_compress_data(ZIO_COMPRESS_LZ4, hdr->b_l1hdr.b_tmp_cdata,
 	    cdata, l2hdr->b_asize);
 
 	rounded = P2ROUNDUP(csize, (size_t)SPA_MINBLOCKSIZE);
@@ -4873,9 +5456,9 @@
 	if (csize == 0) {
 		/* zero block, indicate that there's nothing to write */
 		zio_data_buf_free(cdata, len);
-		l2hdr->b_compress = ZIO_COMPRESS_EMPTY;
+		HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_EMPTY);
 		l2hdr->b_asize = 0;
-		l2hdr->b_tmp_cdata = NULL;
+		hdr->b_l1hdr.b_tmp_cdata = NULL;
 		ARCSTAT_BUMP(arcstat_l2_compress_zeros);
 		return (B_TRUE);
 	} else if (csize > 0 && csize < len) {
@@ -4883,9 +5466,9 @@
 		 * Compression succeeded, we'll keep the cdata around for
 		 * writing and release it afterwards.
 		 */
-		l2hdr->b_compress = ZIO_COMPRESS_LZ4;
+		HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_LZ4);
 		l2hdr->b_asize = csize;
-		l2hdr->b_tmp_cdata = cdata;
+		hdr->b_l1hdr.b_tmp_cdata = cdata;
 		ARCSTAT_BUMP(arcstat_l2_compress_successes);
 		return (B_TRUE);
 	} else {
@@ -4930,9 +5513,9 @@
 		 * need to fill its io_data after we're done restoring the
 		 * buffer's contents.
 		 */
-		ASSERT(hdr->b_buf != NULL);
-		bzero(hdr->b_buf->b_data, hdr->b_size);
-		zio->io_data = zio->io_orig_data = hdr->b_buf->b_data;
+		ASSERT(hdr->b_l1hdr.b_buf != NULL);
+		bzero(hdr->b_l1hdr.b_buf->b_data, hdr->b_size);
+		zio->io_data = zio->io_orig_data = hdr->b_l1hdr.b_buf->b_data;
 	} else {
 		ASSERT(zio->io_data != NULL);
 		/*
@@ -4970,17 +5553,17 @@
 static void
 l2arc_release_cdata_buf(arc_buf_hdr_t *hdr)
 {
-	l2arc_buf_hdr_t *l2hdr = hdr->b_l2hdr;
-
-	if (l2hdr->b_compress == ZIO_COMPRESS_LZ4) {
+	ASSERT(HDR_HAS_L1HDR(hdr));
+	if (HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_EMPTY) {
 		/*
 		 * If the data was compressed, then we've allocated a
 		 * temporary buffer for it, so now we need to release it.
 		 */
-		ASSERT(l2hdr->b_tmp_cdata != NULL);
-		zio_data_buf_free(l2hdr->b_tmp_cdata, hdr->b_size);
+		ASSERT(hdr->b_l1hdr.b_tmp_cdata != NULL);
+		zio_data_buf_free(hdr->b_l1hdr.b_tmp_cdata,
+		    hdr->b_size);
 	}
-	l2hdr->b_tmp_cdata = NULL;
+	hdr->b_l1hdr.b_tmp_cdata = NULL;
 }
 
 /*
@@ -5121,13 +5704,13 @@
 	adddev->l2ad_first = B_TRUE;
 	adddev->l2ad_writing = B_FALSE;
 
+	mutex_init(&adddev->l2ad_mtx, NULL, MUTEX_DEFAULT, NULL);
 	/*
 	 * This is a list of all ARC buffers that are still valid on the
 	 * device.
 	 */
-	adddev->l2ad_buflist = kmem_zalloc(sizeof (list_t), KM_SLEEP);
-	list_create(adddev->l2ad_buflist, sizeof (arc_buf_hdr_t),
-	    offsetof(arc_buf_hdr_t, b_l2node));
+	list_create(&adddev->l2ad_buflist, sizeof (arc_buf_hdr_t),
+	    offsetof(arc_buf_hdr_t, b_l2hdr.b_l2node));
 
 	vdev_space_update(vd, 0, 0, adddev->l2ad_end - adddev->l2ad_hand);
 
@@ -5173,8 +5756,8 @@
 	 * Clear all buflists and ARC references.  L2ARC device flush.
 	 */
 	l2arc_evict(remdev, 0, B_TRUE);
-	list_destroy(remdev->l2ad_buflist);
-	kmem_free(remdev->l2ad_buflist, sizeof (list_t));
+	list_destroy(&remdev->l2ad_buflist);
+	mutex_destroy(&remdev->l2ad_mtx);
 	kmem_free(remdev, sizeof (l2arc_dev_t));
 }
 
@@ -5189,7 +5772,6 @@
 	mutex_init(&l2arc_feed_thr_lock, NULL, MUTEX_DEFAULT, NULL);
 	cv_init(&l2arc_feed_thr_cv, NULL, CV_DEFAULT, NULL);
 	mutex_init(&l2arc_dev_mtx, NULL, MUTEX_DEFAULT, NULL);
-	mutex_init(&l2arc_buflist_mtx, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&l2arc_free_on_write_mtx, NULL, MUTEX_DEFAULT, NULL);
 
 	l2arc_dev_list = &L2ARC_dev_list;
@@ -5214,7 +5796,6 @@
 	mutex_destroy(&l2arc_feed_thr_lock);
 	cv_destroy(&l2arc_feed_thr_cv);
 	mutex_destroy(&l2arc_dev_mtx);
-	mutex_destroy(&l2arc_buflist_mtx);
 	mutex_destroy(&l2arc_free_on_write_mtx);
 
 	list_destroy(l2arc_dev_list);
--- a/usr/src/uts/common/fs/zfs/dnode.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dnode.c	Sun Jan 04 07:19:22 2015 -0800
@@ -79,16 +79,14 @@
 		return (1);
 	}
 
-	if (d1->db_state < d2->db_state) {
+	if (d1->db_state == DB_SEARCH) {
+		ASSERT3S(d2->db_state, !=, DB_SEARCH);
 		return (-1);
-	}
-	if (d1->db_state > d2->db_state) {
+	} else if (d2->db_state == DB_SEARCH) {
+		ASSERT3S(d1->db_state, !=, DB_SEARCH);
 		return (1);
 	}
 
-	ASSERT3S(d1->db_state, !=, DB_SEARCH);
-	ASSERT3S(d2->db_state, !=, DB_SEARCH);
-
 	if ((uintptr_t)d1 < (uintptr_t)d2) {
 		return (-1);
 	}
--- a/usr/src/uts/common/fs/zfs/sys/arc.h	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/arc.h	Sun Jan 04 07:19:22 2015 -0800
@@ -70,10 +70,29 @@
 	ARC_FLAG_FREED_IN_READ		= 1 << 10,	/* freed during read */
 	ARC_FLAG_BUF_AVAILABLE		= 1 << 11,	/* block not in use */
 	ARC_FLAG_INDIRECT		= 1 << 12,	/* indirect block */
-	ARC_FLAG_FREE_IN_PROGRESS	= 1 << 13,	/*  about to be freed */
-	ARC_FLAG_L2_WRITING		= 1 << 14,	/* write in progress */
-	ARC_FLAG_L2_EVICTED		= 1 << 15,	/* evicted during I/O */
-	ARC_FLAG_L2_WRITE_HEAD		= 1 << 16,	/* head of write list */
+	ARC_FLAG_L2_WRITING		= 1 << 13,	/* write in progress */
+	ARC_FLAG_L2_EVICTED		= 1 << 14,	/* evicted during I/O */
+	ARC_FLAG_L2_WRITE_HEAD		= 1 << 15,	/* head of write list */
+	/* indicates that the buffer contains metadata (otherwise, data) */
+	ARC_FLAG_BUFC_METADATA		= 1 << 16,
+
+	/* Flags specifying whether optional hdr struct fields are defined */
+	ARC_FLAG_HAS_L1HDR		= 1 << 17,
+	ARC_FLAG_HAS_L2HDR		= 1 << 18,
+
+	/*
+	 * The arc buffer's compression mode is stored in the top 7 bits of the
+	 * flags field, so these dummy flags are included so that MDB can
+	 * interpret the enum properly.
+	 */
+	ARC_FLAG_COMPRESS_0		= 1 << 24,
+	ARC_FLAG_COMPRESS_1		= 1 << 25,
+	ARC_FLAG_COMPRESS_2		= 1 << 26,
+	ARC_FLAG_COMPRESS_3		= 1 << 27,
+	ARC_FLAG_COMPRESS_4		= 1 << 28,
+	ARC_FLAG_COMPRESS_5		= 1 << 29,
+	ARC_FLAG_COMPRESS_6		= 1 << 30
+
 } arc_flags_t;
 
 struct arc_buf {
@@ -96,6 +115,7 @@
  */
 typedef enum arc_space_type {
 	ARC_SPACE_DATA,
+	ARC_SPACE_META,
 	ARC_SPACE_HDRS,
 	ARC_SPACE_L2HDRS,
 	ARC_SPACE_OTHER,
--- a/usr/src/uts/common/inet/ipf/fil.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/inet/ipf/fil.c	Sun Jan 04 07:19:22 2015 -0800
@@ -4,6 +4,8 @@
  * See the IPFILTER.LICENCE file for details on licencing.
  *
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #if defined(KERNEL) || defined(_KERNEL)
@@ -134,6 +136,9 @@
 # endif
 #endif
 #include "netinet/ipl.h"
+#if defined(_KERNEL)
+#include <sys/sunddi.h>
+#endif
 /* END OF INCLUDES */
 
 #if !defined(lint)
@@ -5696,6 +5701,54 @@
 
 
 /* ------------------------------------------------------------------------ */
+/* Function:    fr_getzoneid                                                */
+/* Returns:     int     - 0 = success, else failure                         */
+/* Parameters:  idsp(I) - pointer to ipf_devstate_t                         */
+/*              data(I) - pointer to ioctl data                             */
+/*                                                                          */
+/* Set the zone ID in idsp based on the zone name in ipfzoneobj.  Further   */
+/* ioctls will act on the IPF stack for that zone ID.                       */
+/* ------------------------------------------------------------------------ */
+#if defined(_KERNEL)
+int fr_setzoneid(idsp, data)
+ipf_devstate_t *idsp;
+void *data;
+{
+	int error = 0;
+	ipfzoneobj_t ipfzo;
+	zone_t *zone;
+
+	error = BCOPYIN(data, &ipfzo, sizeof(ipfzo));
+	if (error != 0)
+		return EFAULT;
+
+	if (memchr(ipfzo.ipfz_zonename, '\0', ZONENAME_MAX) == NULL)
+		return EFAULT;
+
+	/*
+	 * The global zone doesn't have a GZ-controlled stack, so no
+	 * sense in going any further
+	 */
+	if (strcmp(ipfzo.ipfz_zonename, "global") == 0)
+		return ENODEV;
+
+	if ((zone = zone_find_by_name(ipfzo.ipfz_zonename)) == NULL)
+		return ENODEV;
+
+	/*
+	 * Store the zone ID that to control, and whether it's the
+	 * GZ-controlled stack that's wanted
+	 */
+	idsp->ipfs_zoneid = zone->zone_id;
+	idsp->ipfs_gz = (ipfzo.ipfz_gz == 1) ? B_TRUE : B_FALSE;
+	zone_rele(zone);
+
+	return error;
+}
+#endif
+
+
+/* ------------------------------------------------------------------------ */
 /* Function:    fr_inobj                                                    */
 /* Returns:     int     - 0 = success, else failure                         */
 /* Parameters:  data(I) - pointer to ioctl data                             */
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c	Sun Jan 04 07:19:22 2015 -0800
@@ -4,6 +4,8 @@
  * See the IPFILTER.LICENCE file for details on licencing.
  *
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  */
 
 #if !defined(lint)
@@ -101,6 +103,54 @@
 #endif
 #endif
 
+vmem_t	*ipf_minor;	/* minor number arena */
+void 	*ipf_state;	/* DDI state */
+
+/*
+ * GZ-controlled and per-zone stacks:
+ *
+ * For each non-global zone, we create two ipf stacks: the per-zone stack and
+ * the GZ-controlled stack.  The per-zone stack can be controlled and observed
+ * from inside the zone or from the global zone.  The GZ-controlled stack can
+ * only be controlled and observed from the global zone (though the rules
+ * still only affect that non-global zone).
+ *
+ * The two hooks are always arranged so that the GZ-controlled stack is always
+ * "outermost" with respect to the zone.  The traffic flow then looks like
+ * this:
+ *
+ * Inbound:
+ *
+ *     nic ---> [ GZ-controlled rules ] ---> [ per-zone rules ] ---> zone
+ *
+ * Outbound:
+ *
+ *     nic <--- [ GZ-controlled rules ] <--- [ per-zone rules ] <--- zone
+ */
+
+/* IPv4 hook names */
+char *hook4_nicevents = 	"ipfilter_hook4_nicevents";
+char *hook4_nicevents_gz = 	"ipfilter_hook4_nicevents_gz";
+char *hook4_in = 		"ipfilter_hook4_in";
+char *hook4_in_gz = 		"ipfilter_hook4_in_gz";
+char *hook4_out = 		"ipfilter_hook4_out";
+char *hook4_out_gz = 		"ipfilter_hook4_out_gz";
+char *hook4_loop_in = 		"ipfilter_hook4_loop_in";
+char *hook4_loop_in_gz = 	"ipfilter_hook4_loop_in_gz";
+char *hook4_loop_out = 		"ipfilter_hook4_loop_out";
+char *hook4_loop_out_gz = 	"ipfilter_hook4_loop_out_gz";
+
+/* IPv6 hook names */
+char *hook6_nicevents = 	"ipfilter_hook6_nicevents";
+char *hook6_nicevents_gz = 	"ipfilter_hook6_nicevents_gz";
+char *hook6_in = 		"ipfilter_hook6_in";
+char *hook6_in_gz = 		"ipfilter_hook6_in_gz";
+char *hook6_out = 		"ipfilter_hook6_out";
+char *hook6_out_gz = 		"ipfilter_hook6_out_gz";
+char *hook6_loop_in = 		"ipfilter_hook6_loop_in";
+char *hook6_loop_in_gz = 	"ipfilter_hook6_loop_in_gz";
+char *hook6_loop_out = 		"ipfilter_hook6_loop_out";
+char *hook6_loop_out_gz = 	"ipfilter_hook6_loop_out_gz";
 
 /* ------------------------------------------------------------------------ */
 /* Function:    ipldetach                                                   */
@@ -117,7 +167,7 @@
 ipf_stack_t *ifs;
 {
 
-	ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
+	ASSERT(RW_WRITE_HELD(&ifs->ifs_ipf_global.ipf_lk));
 
 #if SOLARIS2 < 10
 
@@ -143,9 +193,10 @@
 	do {								\
 		if (ifs->_f != NULL) {					\
 			if (ifs->_b) {					\
-				ifs->_b = (net_hook_unregister(ifs->_f,	\
-					   _e, ifs->_h) != 0);		\
-				if (!ifs->_b) {				\
+				int tmp = net_hook_unregister(ifs->_f,	\
+					   _e, ifs->_h);		\
+				ifs->_b = (tmp != 0 && tmp != ENXIO);	\
+				if (!ifs->_b && ifs->_h != NULL) {	\
 					hook_free(ifs->_h);		\
 					ifs->_h = NULL;			\
 				}					\
@@ -243,7 +294,7 @@
 	cmn_err(CE_CONT, "iplattach()\n");
 #endif
 
-	ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0);
+	ASSERT(RW_WRITE_HELD(&ifs->ifs_ipf_global.ipf_lk));
 	ifs->ifs_fr_flags = IPF_LOGGING;
 #ifdef _KERNEL
 	ifs->ifs_fr_update_ipid = 0;
@@ -268,16 +319,39 @@
 	if (fr_initialise(ifs) < 0)
 		return -1;
 
-	HOOK_INIT(ifs->ifs_ipfhook4_nicevents, ipf_nic_event_v4,
-		  "ipfilter_hook4_nicevents", ifs);
-	HOOK_INIT(ifs->ifs_ipfhook4_in, ipf_hook4_in,
-		  "ipfilter_hook4_in", ifs);
-	HOOK_INIT(ifs->ifs_ipfhook4_out, ipf_hook4_out,
-		  "ipfilter_hook4_out", ifs);
-	HOOK_INIT(ifs->ifs_ipfhook4_loop_in, ipf_hook4_loop_in,
-		  "ipfilter_hook4_loop_in", ifs);
-	HOOK_INIT(ifs->ifs_ipfhook4_loop_out, ipf_hook4_loop_out,
-		  "ipfilter_hook4_loop_out", ifs);
+	/*
+	 * For incoming packets, we want the GZ-controlled hooks to run before
+	 * the per-zone hooks, regardless of what order they're are installed.
+	 * See the "GZ-controlled and per-zone stacks" comment block at the top
+	 * of this file.
+	 */
+#define HOOK_INIT_GZ_BEFORE(x, fn, n, gzn, a)				\
+	HOOK_INIT(x, fn, ifs->ifs_gz_controlled ? gzn : n, ifs);	\
+	(x)->h_hint = ifs->ifs_gz_controlled ? HH_BEFORE : HH_AFTER;	\
+	(x)->h_hintvalue = (uintptr_t) (ifs->ifs_gz_controlled ? n : gzn);
+
+	HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_nicevents, ipf_nic_event_v4,
+		  hook4_nicevents, hook4_nicevents_gz, ifs);
+	HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_in, ipf_hook4_in,
+		  hook4_in, hook4_in_gz, ifs);
+	HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_loop_in, ipf_hook4_loop_in,
+		  hook4_loop_in, hook4_loop_in_gz, ifs);
+
+	/*
+	 * For outgoing packets, we want the GZ-controlled hooks to run after
+	 * the per-zone hooks, regardless of what order they're are installed.
+	 * See the "GZ-controlled and per-zone stacks" comment block at the top
+	 * of this file.
+	 */
+#define HOOK_INIT_GZ_AFTER(x, fn, n, gzn, a)				\
+	HOOK_INIT(x, fn, ifs->ifs_gz_controlled ? gzn : n, ifs);	\
+	(x)->h_hint = ifs->ifs_gz_controlled ? HH_AFTER : HH_BEFORE;	\
+	(x)->h_hintvalue = (uintptr_t) (ifs->ifs_gz_controlled ? n : gzn);
+
+	HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook4_out, ipf_hook4_out,
+		  hook4_out, hook4_out_gz, ifs);
+	HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook4_loop_out, ipf_hook4_loop_out,
+		  hook4_loop_out, hook4_loop_out_gz, ifs);
 
 	/*
 	 * If we hold this lock over all of the net_hook_register calls, we
@@ -322,6 +396,7 @@
 		if (!ifs->ifs_hook4_loopback_out)
 			goto hookup_failed;
 	}
+
 	/*
 	 * Add IPv6 hooks
 	 */
@@ -329,16 +404,16 @@
 	if (ifs->ifs_ipf_ipv6 == NULL)
 		goto hookup_failed;
 
-	HOOK_INIT(ifs->ifs_ipfhook6_nicevents, ipf_nic_event_v6,
-		  "ipfilter_hook6_nicevents", ifs);
-	HOOK_INIT(ifs->ifs_ipfhook6_in, ipf_hook6_in,
-		  "ipfilter_hook6_in", ifs);
-	HOOK_INIT(ifs->ifs_ipfhook6_out, ipf_hook6_out,
-		  "ipfilter_hook6_out", ifs);
-	HOOK_INIT(ifs->ifs_ipfhook6_loop_in, ipf_hook6_loop_in,
-		  "ipfilter_hook6_loop_in", ifs);
-	HOOK_INIT(ifs->ifs_ipfhook6_loop_out, ipf_hook6_loop_out,
-		  "ipfilter_hook6_loop_out", ifs);
+	HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_nicevents, ipf_nic_event_v6,
+		  hook6_nicevents, hook6_nicevents_gz, ifs);
+	HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_in, ipf_hook6_in,
+		  hook6_in, hook6_in_gz, ifs);
+	HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_loop_in, ipf_hook6_loop_in,
+		  hook6_loop_in, hook6_loop_in_gz, ifs);
+	HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook6_out, ipf_hook6_out,
+		  hook6_out, hook6_out_gz, ifs);
+	HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook6_loop_out, ipf_hook6_loop_out,
+		  hook6_loop_out, hook6_loop_out_gz, ifs);
 
 	ifs->ifs_hook6_nic_events = (net_hook_register(ifs->ifs_ipf_ipv6,
 	    NH_NIC_EVENTS, ifs->ifs_ipfhook6_nicevents) == 0);
@@ -518,35 +593,47 @@
 	minor_t unit;
 	u_int enable;
 	ipf_stack_t *ifs;
+	zoneid_t zid;
+	ipf_devstate_t *isp;
 
 #ifdef	IPFDEBUG
 	cmn_err(CE_CONT, "iplioctl(%x,%x,%x,%d,%x,%d)\n",
 		dev, cmd, data, mode, cp, rp);
 #endif
 	unit = getminor(dev);
-	if (IPL_LOGMAX < unit)
+
+	isp = ddi_get_soft_state(ipf_state, unit);
+	if (isp == NULL)
 		return ENXIO;
+	unit = isp->ipfs_minor;
+
+	zid = crgetzoneid(cp);
+	if (cmd == SIOCIPFZONESET) {
+		if (zid == GLOBAL_ZONEID)
+			return fr_setzoneid(isp, (caddr_t) data);
+		return EACCES;
+	}
 
         /*
-	 * As we're calling ipf_find_stack in user space, from a given zone
-	 * to find the stack pointer for this zone, there is no need to have
-	 * a hold/refence count here.
+	 * ipf_find_stack returns with a read lock on ifs_ipf_global
 	 */
-	ifs = ipf_find_stack(crgetzoneid(cp));
-	ASSERT(ifs != NULL);
+	ifs = ipf_find_stack(zid, isp);
+	if (ifs == NULL)
+		return ENXIO;
 
 	if (ifs->ifs_fr_running <= 0) {
 		if (unit != IPL_LOGIPF) {
+			RWLOCK_EXIT(&ifs->ifs_ipf_global);
 			return EIO;
 		}
 		if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
 		    cmd != SIOCIPFSET && cmd != SIOCFRENB &&
 		    cmd != SIOCGETFS && cmd != SIOCGETFF) {
+			RWLOCK_EXIT(&ifs->ifs_ipf_global);
 			return EIO;
 		}
 	}
 
-	READ_ENTER(&ifs->ifs_ipf_global);
 	if (ifs->ifs_fr_enable_active != 0) {
 		RWLOCK_EXIT(&ifs->ifs_ipf_global);
 		return EBUSY;
@@ -847,7 +934,9 @@
 int flags, otype;
 cred_t *cred;
 {
+	ipf_devstate_t *isp;
 	minor_t min = getminor(*devp);
+	minor_t minor;
 
 #ifdef	IPFDEBUG
 	cmn_err(CE_CONT, "iplopen(%x,%x,%x,%x)\n", devp, flags, otype, cred);
@@ -855,8 +944,25 @@
 	if (!(otype & OTYP_CHR))
 		return ENXIO;
 
-	min = (IPL_LOGMAX < min) ? ENXIO : 0;
-	return min;
+	if (IPL_LOGMAX < min)
+		return ENXIO;
+
+	minor = (minor_t)(uintptr_t)vmem_alloc(ipf_minor, 1,
+	    VM_BESTFIT | VM_SLEEP);
+
+	if (ddi_soft_state_zalloc(ipf_state, minor) != 0) {
+		vmem_free(ipf_minor, (void *)(uintptr_t)minor, 1);
+		return ENXIO;
+	}
+
+	*devp = makedevice(getmajor(*devp), minor);
+	isp = ddi_get_soft_state(ipf_state, minor);
+	VERIFY(isp != NULL);
+
+	isp->ipfs_minor = min;
+	isp->ipfs_zoneid = IPFS_ZONE_UNSET;
+
+	return 0;
 }
 
 
@@ -872,8 +978,13 @@
 	cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred);
 #endif
 
-	min = (IPL_LOGMAX < min) ? ENXIO : 0;
-	return min;
+	if (IPL_LOGMAX < min)
+		return ENXIO;
+
+	ddi_soft_state_free(ipf_state, min);
+	vmem_free(ipf_minor, (void *)(uintptr_t)min, 1);
+
+	return 0;
 }
 
 #ifdef	IPFILTER_LOG
@@ -891,30 +1002,41 @@
 {
 	ipf_stack_t *ifs;
 	int ret;
+	minor_t unit;
+	ipf_devstate_t *isp;
+
+	unit = getminor(dev);
+	isp = ddi_get_soft_state(ipf_state, unit);
+	if (isp == NULL)
+		return ENXIO;
+	unit = isp->ipfs_minor;
+
 
         /*
-	 * As we're calling ipf_find_stack in user space, from a given zone
-	 * to find the stack pointer for this zone, there is no need to have
-	 * a hold/refence count here.
+	 * ipf_find_stack returns with a read lock on ifs_ipf_global
 	 */
-	ifs = ipf_find_stack(crgetzoneid(cp));
-	ASSERT(ifs != NULL);
+	ifs = ipf_find_stack(crgetzoneid(cp), isp);
+	if (ifs == NULL)
+		return ENXIO;
 
 # ifdef	IPFDEBUG
 	cmn_err(CE_CONT, "iplread(%x,%x,%x)\n", dev, uio, cp);
 # endif
 
 	if (ifs->ifs_fr_running < 1) {
+		RWLOCK_EXIT(&ifs->ifs_ipf_global);
 		return EIO;
 	}
 
 # ifdef	IPFILTER_SYNC
-	if (getminor(dev) == IPL_LOGSYNC) {
+	if (unit == IPL_LOGSYNC) {
+		RWLOCK_EXIT(&ifs->ifs_ipf_global);
 		return ipfsync_read(uio);
 	}
 # endif
 
-	ret = ipflog_read(getminor(dev), uio, ifs);
+	ret = ipflog_read(unit, uio, ifs);
+	RWLOCK_EXIT(&ifs->ifs_ipf_global);
 	return ret;
 }
 #endif /* IPFILTER_LOG */
@@ -932,30 +1054,41 @@
 cred_t *cp;
 {
 	ipf_stack_t *ifs;
+	minor_t unit;
+	ipf_devstate_t *isp;
+
+	unit = getminor(dev);
+	isp = ddi_get_soft_state(ipf_state, unit);
+	if (isp == NULL)
+		return ENXIO;
+	unit = isp->ipfs_minor;
 
         /*
-	 * As we're calling ipf_find_stack in user space, from a given zone
-	 * to find the stack pointer for this zone, there is no need to have
-	 * a hold/refence count here.
+	 * ipf_find_stack returns with a read lock on ifs_ipf_global
 	 */
-	ifs = ipf_find_stack(crgetzoneid(cp));
-	ASSERT(ifs != NULL);
+	ifs = ipf_find_stack(crgetzoneid(cp), isp);
+	if (ifs == NULL)
+		return ENXIO;
 
 #ifdef	IPFDEBUG
 	cmn_err(CE_CONT, "iplwrite(%x,%x,%x)\n", dev, uio, cp);
 #endif
 
 	if (ifs->ifs_fr_running < 1) {
+		RWLOCK_EXIT(&ifs->ifs_ipf_global);
 		return EIO;
 	}
 
 #ifdef	IPFILTER_SYNC
-	if (getminor(dev) == IPL_LOGSYNC)
+	if (getminor(dev) == IPL_LOGSYNC) {
+		RWLOCK_EXIT(&ifs->ifs_ipf_global);
 		return ipfsync_write(uio);
+	}
 #endif /* IPFILTER_SYNC */
 	dev = dev;	/* LINT */
 	uio = uio;	/* LINT */
 	cp = cp;	/* LINT */
+	RWLOCK_EXIT(&ifs->ifs_ipf_global);
 	return ENXIO;
 }
 
@@ -1997,7 +2130,6 @@
 	fw->hpe_mb = qpi.qpi_m;
 	fw->hpe_hdr = qpi.qpi_data;
 	return rval;
-
 }
 
 
--- a/usr/src/uts/common/inet/ipf/ip_log.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/inet/ipf/ip_log.c	Sun Jan 04 07:19:22 2015 -0800
@@ -7,6 +7,8 @@
  *
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #include <sys/param.h>
@@ -572,10 +574,18 @@
 
 	while (ifs->ifs_iplt[unit] == NULL) {
 # if SOLARIS && defined(_KERNEL)
+		/*
+		 * Prevent a deadlock with ipldetach() - see the "ipfilter
+		 * kernel module mutexes and locking" comment block in solaris.c
+		 * for details.
+		 */
+		RWLOCK_EXIT(&ifs->ifs_ipf_global);
 		if (!cv_wait_sig(&ifs->ifs_iplwait, &ifs->ifs_ipl_mutex.ipf_lk)) {
+			READ_ENTER(&ifs->ifs_ipf_global);
 			MUTEX_EXIT(&ifs->ifs_ipl_mutex);
 			return EINTR;
 		}
+		READ_ENTER(&ifs->ifs_ipf_global);
 # else
 #  if defined(__hpux) && defined(_KERNEL)
 		lock_t *l;
--- a/usr/src/uts/common/inet/ipf/ip_state.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/inet/ipf/ip_state.c	Sun Jan 04 07:19:22 2015 -0800
@@ -4,6 +4,8 @@
  * See the IPFILTER.LICENCE file for details on licencing.
  *
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #if defined(KERNEL) || defined(_KERNEL)
@@ -1285,6 +1287,7 @@
 		switch (ic->icmp_type)
 		{
 		case ICMP_ECHO :
+		case ICMP_ECHOREPLY :
 		case ICMP_TSTAMP :
 		case ICMP_IREQ :
 		case ICMP_MASKREQ :
--- a/usr/src/uts/common/inet/ipf/netinet/ip_fil.h	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h	Sun Jan 04 07:19:22 2015 -0800
@@ -7,12 +7,15 @@
  * $Id: ip_fil.h,v 2.170.2.22 2005/07/16 05:55:35 darrenr Exp $
  *
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  */
 
 #ifndef	__IP_FIL_H__
 #define	__IP_FIL_H__
 
 #include "netinet/ip_compat.h"
+#include <sys/zone.h>
 
 #ifndef	SOLARIS
 # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
@@ -106,6 +109,7 @@
 #define	SIOCADDFR	SIOCADAFR
 #define	SIOCDELFR	SIOCRMAFR
 #define	SIOCINSFR	SIOCINAFR
+# define	SIOCIPFZONESET	_IOWR('r', 97, struct ipfzoneobj)
 
 /*
  * What type of table is getting flushed?
@@ -1165,6 +1169,26 @@
 	u_char	ipfo_xxxpad[32];	/* reserved for future use */
 } ipfobj_t;
 
+/*
+ * ioctl struct for setting what zone further ioctls will act on. ipfz_gz is a
+ * boolean: set it to 1 to operate on the GZ-controlled stack.
+ */
+typedef	struct	ipfzoneobj	{
+	u_32_t		ipfz_gz;			/* GZ stack boolean */
+	char		ipfz_zonename[ZONENAME_MAX];	/* zone to act on */
+} ipfzoneobj_t;
+
+#if defined(_KERNEL)
+/* Set ipfs_zoneid to this if no zone has been set: */
+#define IPFS_ZONE_UNSET	-2
+
+typedef	struct	ipf_devstate	{
+	zoneid_t	ipfs_zoneid;
+	minor_t		ipfs_minor;
+	boolean_t	ipfs_gz;
+} ipf_devstate_t;
+#endif
+
 #define	IPFOBJ_FRENTRY		0	/* struct frentry */
 #define	IPFOBJ_IPFSTAT		1	/* struct friostat */
 #define	IPFOBJ_IPFINFO		2	/* struct fr_info */
@@ -1352,7 +1376,6 @@
 extern	int	ipl_enable __P((void));
 extern	int	ipl_disable __P((void));
 # ifdef MENTAT
-extern	ipf_stack_t *ipf_find_stack(const zoneid_t zone);
 extern	int	fr_check __P((struct ip *, int, void *, int, void *,
 			      mblk_t **, ipf_stack_t *));
 #  if SOLARIS
@@ -1365,6 +1388,7 @@
 extern	int	fr_make_rst __P((fr_info_t *));
 extern	int	fr_make_icmp __P((fr_info_t *));
 extern	void	fr_calc_chksum __P((fr_info_t *, mb_t *));
+extern	ipf_stack_t *ipf_find_stack(const zoneid_t, ipf_devstate_t *);
 #   endif
 extern	int	iplopen __P((dev_t *, int, int, cred_t *));
 extern	int	iplclose __P((dev_t, int, int, cred_t *));
@@ -1576,6 +1600,10 @@
 extern	u_32_t		ipf_random __P((void));
 #endif
 
+#if defined(_KERNEL)
+extern	int	fr_setzoneid __P((ipf_devstate_t *, void *));
+#endif
+
 extern	char	ipfilter_version[];
 #ifdef	USE_INET6
 extern	int	icmptoicmp6types[ICMP_MAXTYPE+1];
--- a/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h	Sun Jan 04 07:19:22 2015 -0800
@@ -5,6 +5,8 @@
  *
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2014 Joyent, Inc.  All rights reserved.
  */
 
 #ifndef	__IPF_STACK_H__
@@ -41,8 +43,10 @@
 struct ipf_stack {
 	struct ipf_stack	*ifs_next;
 	struct ipf_stack	**ifs_pnext;
+	struct ipf_stack	*ifs_gz_cont_ifs;
 	netid_t			ifs_netid;
 	zoneid_t		ifs_zone;
+	boolean_t		ifs_gz_controlled;
 
 	/* ipf module */
 	fr_info_t		ifs_frcache[2][8];
--- a/usr/src/uts/common/inet/ipf/solaris.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/inet/ipf/solaris.c	Sun Jan 04 07:19:22 2015 -0800
@@ -5,6 +5,50 @@
  *
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
+ */
+
+/*
+ * ipfilter kernel module mutexes and locking:
+ *
+ * Enabling ipfilter creates a per-netstack ipf_stack_t object that is
+ * stored in the ipf_stacks list, which is protected by ipf_stack_lock.
+ * ipf_stack_t objects are accessed in three contexts:
+ *
+ * 1) administering that filter (eg: ioctls handled with iplioctl())
+ * 2) reading log data (eg: iplread() / iplwrite())
+ * 3) filtering packets (eg: ipf_hook4_* and ipf_hook6_* pfhooks
+ *    functions)
+ *
+ * Each ipf_stack_t has a RW lock, ifs_ipf_global, protecting access to the
+ * whole structure. The structure also has locks protecting the various
+ * data structures used for filtering. The following guidelines should be
+ * followed for ipf_stack_t locks:
+ *
+ * - ipf_stack_lock must be held when accessing the ipf_stacks list
+ * - ipf_stack_lock should be held before acquiring ifs_ipf_global for
+ *   a stack (the exception to this is ipf_stack_destroy(), which removes
+ *   the ipf_stack_t from the list, then drops ipf_stack_lock before
+ *   acquiring ifs_ipf_global)
+ * - ifs_ipf_global must be held when accessing an ipf_stack_t in that list:
+ *   - The write lock is held only during stack creation / destruction
+ *   - The read lock should be held for all other accesses
+ * - To alter the filtering data in the administrative context, one must:
+ *   - acquire the read lock for ifs_ipf_global
+ *   - then acquire the write lock for the data in question
+ * - In the filtering path, the read lock needs to be held for each type of
+ *   filtering data used
+ * - ifs_ipf_global does not need to be held in the filtering path:
+ *   - The filtering hooks don't need to modify the stack itself
+ *   - The ipf_stack_t will not be destroyed until the hooks are unregistered.
+ *     This requires a write lock on the hook, ensuring that no active hooks
+ *     (eg: the filtering path) are running, and that the hooks won't be run
+ *     afterward.
+ *
+ * Note that there is a deadlock possible when calling net_hook_register()
+ * or net_hook_unregister() with ifs_ipf_global held: see the comments in
+ * iplattach() and ipldetach() for details.
  */
 
 #include <sys/systm.h>
@@ -73,7 +117,8 @@
 static	char	*ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
 				    IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
 				    IPLOOKUP_NAME, NULL };
-
+extern void 	*ipf_state;	/* DDI state */
+extern vmem_t	*ipf_minor;	/* minor number arena */
 
 static struct cb_ops ipf_cb_ops = {
 	iplopen,
@@ -221,10 +266,11 @@
 static int	ipf_kstat_update(kstat_t *ksp, int rwflag);
 
 static void
-ipf_kstat_init(ipf_stack_t *ifs)
+ipf_kstat_init(ipf_stack_t *ifs, boolean_t from_gz)
 {
-	ifs->ifs_kstatp[0] = net_kstat_create(ifs->ifs_netid, "ipf", 0,
-	    "inbound", "net", KSTAT_TYPE_NAMED,
+	ifs->ifs_kstatp[0] = net_kstat_create(ifs->ifs_netid,
+	    (from_gz ? "ipf_gz" : "ipf"),
+	    0, "inbound", "net", KSTAT_TYPE_NAMED,
 	    sizeof (filter_kstats_t) / sizeof (kstat_named_t), 0);
 	if (ifs->ifs_kstatp[0] != NULL) {
 		bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[0]->ks_data,
@@ -234,8 +280,9 @@
 		kstat_install(ifs->ifs_kstatp[0]);
 	}
 
-	ifs->ifs_kstatp[1] = net_kstat_create(ifs->ifs_netid, "ipf", 0,
-	    "outbound", "net", KSTAT_TYPE_NAMED,
+	ifs->ifs_kstatp[1] = net_kstat_create(ifs->ifs_netid,
+	    (from_gz ? "ipf_gz" : "ipf"),
+	    0, "outbound", "net", KSTAT_TYPE_NAMED,
 	    sizeof (filter_kstats_t) / sizeof (kstat_named_t), 0);
 	if (ifs->ifs_kstatp[1] != NULL) {
 		bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[1]->ks_data,
@@ -369,12 +416,14 @@
  * Initialize things for IPF for each stack instance
  */
 static void *
-ipf_stack_create(const netid_t id)
+ipf_stack_create_one(const netid_t id, const zoneid_t zid, boolean_t from_gz,
+    ipf_stack_t *ifs_gz)
 {
 	ipf_stack_t	*ifs;
 
 #ifdef IPFDEBUG
-	cmn_err(CE_NOTE, "IP Filter:stack_create id=%d", id);
+	cmn_err(CE_NOTE, "IP Filter:stack_create_one id=%d global=%d", id,
+	    global);
 #endif
 
 	ifs = (ipf_stack_t *)kmem_alloc(sizeof (*ifs), KM_SLEEP);
@@ -398,8 +447,11 @@
 	RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock");
 	RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf cache rwlock");
 	ifs->ifs_netid = id;
-	ifs->ifs_zone = net_getzoneidbynetid(id);
-	ipf_kstat_init(ifs);
+	ifs->ifs_zone = zid;
+	ifs->ifs_gz_controlled = from_gz;
+	ifs->ifs_gz_cont_ifs = ifs_gz;
+
+	ipf_kstat_init(ifs, from_gz);
 
 #ifdef IPFDEBUG
 	cmn_err(CE_CONT, "IP Filter:stack_create zone=%d", ifs->ifs_zone);
@@ -427,31 +479,84 @@
 	return (ifs);
 }
 
+static void *
+ipf_stack_create(const netid_t id)
+{
+	ipf_stack_t	*ifs = NULL;
+	zoneid_t	zid = net_getzoneidbynetid(id);
+
+	/*
+	 * Create two ipfilter stacks for a zone - the first can only be
+	 * controlled from the global zone, and the second is owned by
+	 * the zone itself. There is no need to create a GZ-controlled
+	 * stack for the global zone, since we're already in the global
+	 * zone. See the "GZ-controlled and per-zone stacks" comment block in
+	 * ip_fil_solaris.c for details.
+	 */
+	if (zid != GLOBAL_ZONEID)
+		ifs = ipf_stack_create_one(id, zid, B_TRUE, NULL);
+
+	return (ipf_stack_create_one(id, zid, B_FALSE, ifs));
+}
 
 /*
- * This function should only ever be used to find the pointer to the
- * ipfilter stack structure for the zone that is currently being
- * executed... so if you're running in the context of zone 1, you
- * should not attempt to find the ipf_stack_t for zone 0 or 2 or
- * anything else but 1.  In that way, the returned pointer is safe
- * as it will only be nuked when the instance is destroyed as part
- * of the final shutdown of a zone.
+ * Find an ipfilter stack for the given zone. Return the GZ-controlled or
+ * per-zone stack if set by an earlier SIOCIPFZONESET ioctl call. See the
+ * "GZ-controlled and per-zone stacks" comment block in ip_fil_solaris.c for
+ * details.
+ *
+ * This function returns with the ipf_stack_t's ifs_ipf_global
+ * read lock held (if the stack is found). See the "ipfilter kernel module
+ * mutexes and locking" comment block at the top of this file.
  */
 ipf_stack_t *
-ipf_find_stack(const zoneid_t zone)
+ipf_find_stack(const zoneid_t orig_zone, ipf_devstate_t *isp)
 {
 	ipf_stack_t *ifs;
+	boolean_t gz_stack;
+	zoneid_t zone;
+
+	/*
+	 * If we're in the GZ, determine if we're acting on a zone's stack,
+	 * and whether or not that stack is the GZ-controlled or in-zone
+	 * one.  See the "GZ and per-zone stacks" note at the top of this
+	 * file.
+	 */
+	if (orig_zone == GLOBAL_ZONEID &&
+	    (isp->ipfs_zoneid != IPFS_ZONE_UNSET)) {
+		/* Global zone, and we've set the zoneid for this fd already */
+
+		if (orig_zone == isp->ipfs_zoneid) {
+			/* There's only a per-zone stack for the GZ */
+			gz_stack = B_FALSE;
+		} else {
+			gz_stack = isp->ipfs_gz;
+		}
+
+		zone = isp->ipfs_zoneid;
+	} else {
+		/*
+		 * Non-global zone or GZ without having set a zoneid: act on
+		 * the per-zone stack of the zone that this ioctl originated
+		 * from.
+		 */
+		gz_stack = B_FALSE;
+		zone = orig_zone;
+	}
 
 	mutex_enter(&ipf_stack_lock);
 	for (ifs = ipf_stacks; ifs != NULL; ifs = ifs->ifs_next) {
-		if (ifs->ifs_zone == zone)
+		if (ifs->ifs_zone == zone && ifs->ifs_gz_controlled == gz_stack)
 			break;
 	}
+
+	if (ifs != NULL) {
+		READ_ENTER(&ifs->ifs_ipf_global);
+	}
 	mutex_exit(&ipf_stack_lock);
 	return (ifs);
 }
 
-
 static int ipf_detach_check_zone(ipf_stack_t *ifs)
 {
 	/*
@@ -495,7 +600,8 @@
 
 
 /*
- * Destroy things for ipf for one stack.
+ * Remove ipf kstats for both the per-zone ipf stack and the
+ * GZ-controlled stack for the same zone, if it exists.
  */
 /* ARGSUSED */
 static void
@@ -503,6 +609,15 @@
 {
 	ipf_stack_t *ifs = (ipf_stack_t *)arg;
 
+	/*
+	 * The GZ-controlled stack
+	 */
+	if (ifs->ifs_gz_cont_ifs != NULL)
+		ipf_kstat_fini(ifs->ifs_gz_cont_ifs);
+
+	/*
+	 * The per-zone stack
+	 */
 	ipf_kstat_fini(ifs);
 }
 
@@ -512,13 +627,12 @@
  */
 /* ARGSUSED */
 static void
-ipf_stack_destroy(const netid_t id, void *arg)
+ipf_stack_destroy_one(const netid_t id, ipf_stack_t *ifs)
 {
-	ipf_stack_t *ifs = (ipf_stack_t *)arg;
 	timeout_id_t tid;
 
 #ifdef IPFDEBUG
-	(void) printf("ipf_stack_destroy(%p)\n", (void *)ifs);
+	(void) printf("ipf_stack_destroy_one(%p)\n", (void *)ifs);
 #endif
 
 	/*
@@ -546,7 +660,7 @@
 
 	WRITE_ENTER(&ifs->ifs_ipf_global);
 	if (ipldetach(ifs) != 0) {
-		printf("ipf_stack_destroy: ipldetach failed\n");
+		printf("ipf_stack_destroy_one: ipldetach failed\n");
 	}
 
 	ipftuneable_free(ifs);
@@ -560,6 +674,30 @@
 }
 
 
+/*
+ * Destroy things for ipf for both the per-zone ipf stack and the
+ * GZ-controlled stack for the same zone, if it exists. See the "GZ-controlled
+ * and per-zone stacks" comment block in ip_fil_solaris.c for details.
+ */
+/* ARGSUSED */
+static void
+ipf_stack_destroy(const netid_t id, void *arg)
+{
+	ipf_stack_t *ifs = (ipf_stack_t *)arg;
+
+	/*
+	 * The GZ-controlled stack
+	 */
+	if (ifs->ifs_gz_cont_ifs != NULL)
+		ipf_stack_destroy_one(id, ifs->ifs_gz_cont_ifs);
+
+	/*
+	 * The per-zone stack
+	 */
+	ipf_stack_destroy_one(id, ifs);
+}
+
+
 static int ipf_attach(dip, cmd)
 dev_info_t *dip;
 ddi_attach_cmd_t cmd;
@@ -586,27 +724,39 @@
 
 		(void) ipf_property_g_update(dip);
 
+		if (ddi_soft_state_init(&ipf_state, sizeof (ipf_devstate_t), 1)
+		    != 0) {
+			ddi_prop_remove_all(dip);
+			return (DDI_FAILURE);
+		}
+
 		for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) {
 			s = strrchr(s, '/');
 			if (s == NULL)
 				continue;
 			s++;
 			if (ddi_create_minor_node(dip, s, S_IFCHR, i,
-			    DDI_PSEUDO, 0) ==
-			    DDI_FAILURE) {
-				ddi_remove_minor_node(dip, NULL);
+			    DDI_PSEUDO, 0) == DDI_FAILURE)
 				goto attach_failed;
-			}
 		}
 
 		ipf_dev_info = dip;
 
 		ipfncb = net_instance_alloc(NETINFO_VERSION);
+		if (ipfncb == NULL)
+			goto attach_failed;
+
 		ipfncb->nin_name = "ipf";
 		ipfncb->nin_create = ipf_stack_create;
 		ipfncb->nin_destroy = ipf_stack_destroy;
 		ipfncb->nin_shutdown = ipf_stack_shutdown;
-		i = net_instance_register(ipfncb);
+		if (net_instance_register(ipfncb) == DDI_FAILURE) {
+			net_instance_free(ipfncb);
+			goto attach_failed;
+		}
+
+		ipf_minor = vmem_create("ipf_minor", (void *)1, UINT32_MAX - 1,
+		    1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
 
 #ifdef IPFDEBUG
 		cmn_err(CE_CONT, "IP Filter:stack_create callback_reg=%d", i);
@@ -619,7 +769,9 @@
 	}
 
 attach_failed:
+	ddi_remove_minor_node(dip, NULL);
 	ddi_prop_remove_all(dip);
+	ddi_soft_state_fini(&ipf_state);
 	return (DDI_FAILURE);
 }
 
@@ -652,6 +804,9 @@
 			return (DDI_FAILURE);
 		}
 
+		vmem_destroy(ipf_minor);
+		ddi_soft_state_fini(&ipf_state);
+
 		(void) net_instance_unregister(ipfncb);
 		net_instance_free(ipfncb);
 
--- a/usr/src/uts/common/os/zone.c	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/os/zone.c	Sun Jan 04 07:19:22 2015 -0800
@@ -378,13 +378,6 @@
 rctl_hndl_t rc_zone_shmmni;
 rctl_hndl_t rc_zone_semmni;
 rctl_hndl_t rc_zone_msgmni;
-/*
- * Synchronization primitives used to synchronize between mounts and zone
- * creation/destruction.
- */
-static int mounts_in_progress;
-static kcondvar_t mount_cv;
-static kmutex_t mount_lock;
 
 const char * const zone_default_initname = "/sbin/init";
 static char * const zone_prefix = "/zone/";
@@ -430,17 +423,20 @@
 /*
  * Certain filesystems (such as NFS and autofs) need to know which zone
  * the mount is being placed in.  Because of this, we need to be able to
- * ensure that a zone isn't in the process of being created such that
- * nfs_mount() thinks it is in the global zone, while by the time it
- * gets added the list of mounted zones, it ends up on zoneA's mount
- * list.
+ * ensure that a zone isn't in the process of being created/destroyed such
+ * that nfs_mount() thinks it is in the global/NGZ zone, while by the time
+ * it gets added the list of mounted zones, it ends up on the wrong zone's
+ * mount list. Since a zone can't reside on an NFS file system, we don't
+ * have to worry about the zonepath itself.
  *
  * The following functions: block_mounts()/resume_mounts() and
  * mount_in_progress()/mount_completed() are used by zones and the VFS
- * layer (respectively) to synchronize zone creation and new mounts.
+ * layer (respectively) to synchronize zone state transitions and new
+ * mounts within a zone. This syncronization is on a per-zone basis, so
+ * activity for one zone will not interfere with activity for another zone.
  *
  * The semantics are like a reader-reader lock such that there may
- * either be multiple mounts (or zone creations, if that weren't
+ * either be multiple mounts (or zone state transitions, if that weren't
  * serialized by zonehash_lock) in progress at the same time, but not
  * both.
  *
@@ -448,10 +444,8 @@
  * taking too long.
  *
  * The semantics are such that there is unfair bias towards the
- * "current" operation.  This means that zone creations may starve if
- * there is a rapid succession of new mounts coming in to the system, or
- * there is a remote possibility that zones will be created at such a
- * rate that new mounts will not be able to proceed.
+ * "current" operation.  This means that zone halt may starve if
+ * there is a rapid succession of new mounts coming in to the zone.
  */
 /*
  * Prevent new mounts from progressing to the point of calling
@@ -459,7 +453,7 @@
  * them to complete.
  */
 static int
-block_mounts(void)
+block_mounts(zone_t *zp)
 {
 	int retval = 0;
 
@@ -468,19 +462,21 @@
 	 * called with zonehash_lock held.
 	 */
 	ASSERT(MUTEX_NOT_HELD(&zonehash_lock));
-	mutex_enter(&mount_lock);
-	while (mounts_in_progress > 0) {
-		if (cv_wait_sig(&mount_cv, &mount_lock) == 0)
+	mutex_enter(&zp->zone_mount_lock);
+	while (zp->zone_mounts_in_progress > 0) {
+		if (cv_wait_sig(&zp->zone_mount_cv, &zp->zone_mount_lock) == 0)
 			goto signaled;
 	}
 	/*
 	 * A negative value of mounts_in_progress indicates that mounts
-	 * have been blocked by (-mounts_in_progress) different callers.
-	 */
-	mounts_in_progress--;
+	 * have been blocked by (-mounts_in_progress) different callers
+	 * (remotely possible if two threads enter zone_shutdown at the same
+	 * time).
+	 */
+	zp->zone_mounts_in_progress--;
 	retval = 1;
 signaled:
-	mutex_exit(&mount_lock);
+	mutex_exit(&zp->zone_mount_lock);
 	return (retval);
 }
 
@@ -489,26 +485,26 @@
  * Allow them to progress if we were the last obstacle.
  */
 static void
-resume_mounts(void)
-{
-	mutex_enter(&mount_lock);
-	if (++mounts_in_progress == 0)
-		cv_broadcast(&mount_cv);
-	mutex_exit(&mount_lock);
+resume_mounts(zone_t *zp)
+{
+	mutex_enter(&zp->zone_mount_lock);
+	if (++zp->zone_mounts_in_progress == 0)
+		cv_broadcast(&zp->zone_mount_cv);
+	mutex_exit(&zp->zone_mount_lock);
 }
 
 /*
- * The VFS layer is busy with a mount; zones should wait until all
- * mounts are completed to progress.
+ * The VFS layer is busy with a mount; this zone should wait until all
+ * of its mounts are completed to progress.
  */
 void
-mount_in_progress(void)
-{
-	mutex_enter(&mount_lock);
-	while (mounts_in_progress < 0)
-		cv_wait(&mount_cv, &mount_lock);
-	mounts_in_progress++;
-	mutex_exit(&mount_lock);
+mount_in_progress(zone_t *zp)
+{
+	mutex_enter(&zp->zone_mount_lock);
+	while (zp->zone_mounts_in_progress < 0)
+		cv_wait(&zp->zone_mount_cv, &zp->zone_mount_lock);
+	zp->zone_mounts_in_progress++;
+	mutex_exit(&zp->zone_mount_lock);
 }
 
 /*
@@ -516,12 +512,12 @@
  * callers if this is the last mount.
  */
 void
-mount_completed(void)
-{
-	mutex_enter(&mount_lock);
-	if (--mounts_in_progress == 0)
-		cv_broadcast(&mount_cv);
-	mutex_exit(&mount_lock);
+mount_completed(zone_t *zp)
+{
+	mutex_enter(&zp->zone_mount_lock);
+	if (--zp->zone_mounts_in_progress == 0)
+		cv_broadcast(&zp->zone_mount_cv);
+	mutex_exit(&zp->zone_mount_lock);
 }
 
 /*
@@ -4410,7 +4406,7 @@
 		return (zone_create_error(error, 0, extended_error));
 	}
 
-	if (block_mounts() == 0) {
+	if (block_mounts(zone) == 0) {
 		mutex_enter(&pp->p_lock);
 		if (curthread != pp->p_agenttp)
 			continuelwps(pp);
@@ -4561,7 +4557,7 @@
 	/*
 	 * The zone is fully visible, so we can let mounts progress.
 	 */
-	resume_mounts();
+	resume_mounts(zone);
 	if (rctls)
 		nvlist_free(rctls);
 
@@ -4577,7 +4573,7 @@
 		continuelwps(pp);
 	mutex_exit(&pp->p_lock);
 
-	resume_mounts();
+	resume_mounts(zone);
 	if (rctls)
 		nvlist_free(rctls);
 	/*
@@ -4732,15 +4728,6 @@
 	if (zoneid < MIN_USERZONEID || zoneid > MAX_ZONEID)
 		return (set_errno(EINVAL));
 
-	/*
-	 * Block mounts so that VFS_MOUNT() can get an accurate view of
-	 * the zone's status with regards to ZONE_IS_SHUTTING down.
-	 *
-	 * e.g. NFS can fail the mount if it determines that the zone
-	 * has already begun the shutdown sequence.
-	 */
-	if (block_mounts() == 0)
-		return (set_errno(EINTR));
 	mutex_enter(&zonehash_lock);
 	/*
 	 * Look for zone under hash lock to prevent races with other
@@ -4748,9 +4735,30 @@
 	 */
 	if ((zone = zone_find_all_by_id(zoneid)) == NULL) {
 		mutex_exit(&zonehash_lock);
-		resume_mounts();
 		return (set_errno(EINVAL));
 	}
+
+	/*
+	 * We have to drop zonehash_lock before calling block_mounts.
+	 * Hold the zone so we can continue to use the zone_t.
+	 */
+	zone_hold(zone);
+	mutex_exit(&zonehash_lock);
+
+	/*
+	 * Block mounts so that VFS_MOUNT() can get an accurate view of
+	 * the zone's status with regards to ZONE_IS_SHUTTING down.
+	 *
+	 * e.g. NFS can fail the mount if it determines that the zone
+	 * has already begun the shutdown sequence.
+	 *
+	 */
+	if (block_mounts(zone) == 0) {
+		zone_rele(zone);
+		return (set_errno(EINTR));
+	}
+
+	mutex_enter(&zonehash_lock);
 	mutex_enter(&zone_status_lock);
 	status = zone_status_get(zone);
 	/*
@@ -4759,7 +4767,8 @@
 	if (status < ZONE_IS_READY) {
 		mutex_exit(&zone_status_lock);
 		mutex_exit(&zonehash_lock);
-		resume_mounts();
+		resume_mounts(zone);
+		zone_rele(zone);
 		return (set_errno(EINVAL));
 	}
 	/*
@@ -4769,7 +4778,8 @@
 	if (status >= ZONE_IS_DOWN) {
 		mutex_exit(&zone_status_lock);
 		mutex_exit(&zonehash_lock);
-		resume_mounts();
+		resume_mounts(zone);
+		zone_rele(zone);
 		return (0);
 	}
 	/*
@@ -4804,10 +4814,9 @@
 			}
 		}
 	}
-	zone_hold(zone);	/* so we can use the zone_t later */
 	mutex_exit(&zone_status_lock);
 	mutex_exit(&zonehash_lock);
-	resume_mounts();
+	resume_mounts(zone);
 
 	if (error = zone_empty(zone)) {
 		zone_rele(zone);
--- a/usr/src/uts/common/sys/zone.h	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/common/sys/zone.h	Sun Jan 04 07:19:22 2015 -0800
@@ -600,6 +600,14 @@
 	 * DTrace-private per-zone state
 	 */
 	int		zone_dtrace_getf;	/* # of unprivileged getf()s */
+
+	/*
+	 * Synchronization primitives used to synchronize between mounts and
+	 * zone creation/destruction.
+	 */
+	int		zone_mounts_in_progress;
+	kcondvar_t	zone_mount_cv;
+	kmutex_t	zone_mount_lock;
 } zone_t;
 
 /*
@@ -819,8 +827,8 @@
 extern int zone_kadmin(int, int, const char *, cred_t *);
 extern void zone_shutdown_global(void);
 
-extern void mount_in_progress(void);
-extern void mount_completed(void);
+extern void mount_in_progress(zone_t *);
+extern void mount_completed(zone_t *);
 
 extern int zone_walk(int (*)(zone_t *, void *), void *);
 
--- a/usr/src/uts/intel/ipf/ipf.global-objs.debug64	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/intel/ipf/ipf.global-objs.debug64	Sun Jan 04 07:19:22 2015 -0800
@@ -22,11 +22,33 @@
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
+# Copyright 2013 Joyent, Inc. All rights reserved
+#
 
 fr_availfuncs
 fr_features
 fr_objbytes
 hdrsizes
+hook4_in
+hook4_in_gz
+hook4_loop_in
+hook4_loop_in_gz
+hook4_loop_out
+hook4_loop_out_gz
+hook4_nicevents
+hook4_nicevents_gz
+hook4_out
+hook4_out_gz
+hook6_in
+hook6_in_gz
+hook6_loop_in
+hook6_loop_in_gz
+hook6_loop_out
+hook6_loop_out_gz
+hook6_nicevents
+hook6_nicevents_gz
+hook6_out
+hook6_out_gz
 icmpreplytype4
 icmpreplytype6
 icmptoicmp6types
@@ -37,10 +59,12 @@
 ipf_dev_info
 ipf_devfiles
 ipf_kstat_tmp
+ipf_minor
 ipf_ops
 ipf_proxy_debug
 ipf_stack_lock
 ipf_stacks
+ipf_state
 ipfilter_version
 ipfncb
 ipl_magic
--- a/usr/src/uts/sparc/ipf/ipf.global-objs.debug64	Sun Dec 28 13:11:10 2014 -0800
+++ b/usr/src/uts/sparc/ipf/ipf.global-objs.debug64	Sun Jan 04 07:19:22 2015 -0800
@@ -22,11 +22,33 @@
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
+# Copyright 2013 Joyent, Inc. All rights reserved
+#
 
 fr_availfuncs
 fr_features
 fr_objbytes
 hdrsizes
+hook4_in
+hook4_in_gz
+hook4_loop_in
+hook4_loop_in_gz
+hook4_loop_out
+hook4_loop_out_gz
+hook4_nicevents
+hook4_nicevents_gz
+hook4_out
+hook4_out_gz
+hook6_in
+hook6_in_gz
+hook6_loop_in
+hook6_loop_in_gz
+hook6_loop_out
+hook6_loop_out_gz
+hook6_nicevents
+hook6_nicevents_gz
+hook6_out
+hook6_out_gz
 icmpreplytype4
 icmpreplytype6
 icmptoicmp6types
@@ -37,10 +59,12 @@
 ipf_dev_info
 ipf_devfiles
 ipf_kstat_tmp
+ipf_minor
 ipf_ops
 ipf_proxy_debug
 ipf_stack_lock
 ipf_stacks
+ipf_state
 ipfilter_version
 ipfncb
 ipl_magic
@@ -56,9 +80,9 @@
 sccsid
 secopt
 tcpopts
+lastx
 _drand48_a
 _drand48_c
 _drand48_x
 init48done
 seed_lock
-lastx