changeset 14956:fb8e37100d8d

Merge branch 'master' into core Conflicts: usr/src/man/man5/standards.5
author Garrett D'Amore <garrett@damore.org>
date Wed, 12 Nov 2014 04:51:53 -0800
parents ec5366179d29 (current diff) aa9509419c00 (diff)
children 5f8ea225e580
files exception_lists/packaging usr/src/cmd/fs.d/smbclnt/test/srvenum.c usr/src/cmd/fs.d/smbclnt/test/srvinfo.c usr/src/cmd/fs.d/smbclnt/test/testnp.c usr/src/man/man3c/Makefile usr/src/man/man3c/ucred.3c usr/src/man/man3c/ucred_get.3c usr/src/man/man5/standards.5 usr/src/pkg/manifests/developer-build-onbld.mf usr/src/pkg/manifests/system-library.man3c.inc usr/src/tools/scripts/git-pbchk.py
diffstat 182 files changed, 4360 insertions(+), 1509 deletions(-) [+]
line wrap: on
line diff
--- a/exception_lists/packaging	Thu Nov 06 07:49:31 2014 -0800
+++ b/exception_lists/packaging	Wed Nov 12 04:51:53 2014 -0800
@@ -21,8 +21,8 @@
 
 #
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2012 OmniTI Computer Consulting, Inc.  All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
 #
 
@@ -802,7 +802,7 @@
 #
 usr/lib/fs/smbfs/chacl
 usr/lib/fs/smbfs/lsacl
-usr/lib/fs/smbfs/testnp
+opt/smbcl-tests
 #
 # FC related files
 kernel/kmdb/fcip		i386
--- a/usr/src/cmd/fs.d/smbclnt/test/Makefile	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/fs.d/smbclnt/test/Makefile	Wed Nov 12 04:51:53 2014 -0800
@@ -19,41 +19,63 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 #
 
-FSTYPE=		smbfs
-LIBPROG=	testnp
-ROOTFS_PROG=	$(LIBPROG)
+include $(SRC)/cmd/Makefile.cmd
+
+PROG=	srvenum srvinfo tconn
+OBJS = $(PROG:%=%.o)
+SRCS = $(OBJS:%.o=%.c)
+
+# ROOTFS_PROG=	$(LIBPROG)
+# include		../../Makefile.fstype
 
-include		../../Makefile.fstype
+ROOTOPTPKG = $(ROOT)/opt/smbcl-tests
+TESTDIR = $(ROOTOPTPKG)/tests
+INST_CMDS = $(PROG:%=$(TESTDIR)/%)
+
+# OBJS=	$(LIBPROG).o
+# SRCS=	$(LIBPROG).c $(FSLIBSRC)
 
-OBJS=	$(LIBPROG).o
-SRCS=	$(LIBPROG).c $(FSLIBSRC)
+CPPFLAGS += -I../../../../uts/common
+CPPFLAGS += -I../../../../lib/libsmbfs
 
+LDLIBS += -R '$$ORIGIN/../../../usr/lib'
 LDLIBS += -lsmbfs
+LINTLIBS= -L$(ROOTLIB) -lsmbfs
 
 CFLAGS += $(CCVERBOSE)
 CERRWARN += -_gcc=-Wno-unused-variable
 C99MODE= $(C99_ENABLE)
 
-CLOBBERFILES	+= $(LIBPROG)
+LINTFLAGS += -erroff=E_FUNC_RET_ALWAYS_IGNOR2
+
+# CLOBBERFILES	+= $(LIBPROG)
+
+all:	$(PROG)
 
-# uncomment these for dbx debugging
-#COPTFLAG = -g
-#CTF_FLAGS =
-#CTFCONVERT_O=
-#CTFMERGE_LIB=
+install: all $(ROOTOPTPKG) $(TESTDIR) $(INST_CMDS)
 
-all:	$(ROOTFS_PROG)
+lint:
+	for f in $(SRCS); do ;\
+	$(LINT.c) $$f $(LINTLIBS) ; done
 
-install:	$(ROOTLIBFSTYPEPROG)
-
-lint:	lint_SRCS
+clobber: clean
+	-$(RM) $(PROG)
 
 clean:     
-	$(RM) $(OBJS)
+	-$(RM) $(OBJS)
+
+$(ROOTOPTPKG):
+	$(INS.dir)
+
+$(TESTDIR):
+	$(INS.dir)
+
+$(TESTDIR)/%: %
+	$(INS.file)
 
 .KEEP_STATE:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fs.d/smbclnt/test/srvenum.c	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,436 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Test program for the smbfs named pipe API.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libintl.h>
+
+#include <netsmb/smbfs_api.h>
+
+/*
+ * This is a quick hack for testing client-side named pipes.
+ * Its purpose is to test the ability to connect to a server,
+ * open a pipe, send and receive data.  The "hack" aspect is
+ * the use of hand-crafted RPC messages, which allows testing
+ * of the named pipe API separately from the RPC libraries.
+ *
+ * I captured the two small name pipe messages sent when
+ * requesting a share list via RPC over /pipe/srvsvc and
+ * dropped them into the arrays below (bind and enum).
+ * This program sends the two messages (with adjustments)
+ * and just dumps whatever comes back over the pipe.
+ * Use wireshark if you want to see decoded messages.
+ */
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+/* This is a DCE/RPC bind call for "srvsvc". */
+static const uchar_t
+srvsvc_bind[] = {
+	0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
+	0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+	0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
+	0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88,
+	0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+	0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+	0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
+
+/* This is a srvsvc "enum servers" call, in two parts */
+static const uchar_t
+srvsvc_enum1[] = {
+	0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
+#define	ENUM_RPCLEN_OFF	8
+	/* V - RPC frag length */
+	0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* ... and the operation number is: VVVV */
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00,
+#define	ENUM_SLEN1_OFF	28
+#define	ENUM_SLEN2_OFF	36
+	/* server name, length 14 vv ... */
+	0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 };
+	/* UNC server here, i.e.: "\\192.168.1.6" */
+
+static const uchar_t
+srvsvc_enum2[] = {
+	0x01, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
+
+static uchar_t sendbuf[1024];
+static uchar_t recvbuf[4096];
+static char *server;
+
+static int pipetest(struct smb_ctx *);
+
+static void
+srvenum_usage(void)
+{
+	printf("usage: srvenum [-d domain][-u user][-p passwd] server\n");
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int c, error;
+	struct smb_ctx *ctx = NULL;
+	char *dom = NULL;
+	char *usr = NULL;
+	char *pw = NULL;
+
+	while ((c = getopt(argc, argv, "vd:u:p:")) != -1) {
+		switch (c) {
+		case 'v':
+			smb_verbose = 1;
+			break;
+
+		case 'd':
+			dom = optarg;
+			break;
+		case 'u':
+			usr = optarg;
+			break;
+		case 'p':
+			pw = optarg;
+			break;
+		case '?':
+			srvenum_usage();
+			break;
+		}
+	}
+	if (optind >= argc)
+		srvenum_usage();
+	server = argv[optind];
+
+	if (pw != NULL && (dom == NULL || usr == NULL)) {
+		fprintf(stderr, "%s: -p arg requires -d dom -u usr\n",
+		    argv[0]);
+		srvenum_usage();
+	}
+
+	/*
+	 * This section is intended to demonstrate how an
+	 * RPC client library might use this interface.
+	 */
+	error = smb_ctx_alloc(&ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]);
+		goto out;
+	}
+
+	/*
+	 * Set server, share, domain, user
+	 * (in the ctx handle).
+	 */
+	smb_ctx_setfullserver(ctx, server);
+	smb_ctx_setshare(ctx, "IPC$", USE_IPC);
+	if (dom)
+		smb_ctx_setdomain(ctx, dom, B_TRUE);
+	if (usr)
+		smb_ctx_setuser(ctx, usr, B_TRUE);
+	if (pw)
+		smb_ctx_setpassword(ctx, pw, NULL);
+
+
+	/*
+	 * If this code were in smbutil or mount_smbfs, it would
+	 * get system and $HOME/.nsmbrc settings here, like this:
+	 */
+#if 0
+	error = smb_ctx_readrc(ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_readrc failed\n", argv[0]);
+		goto out;
+	}
+#endif
+
+	/*
+	 * Resolve the server address,
+	 * setup derived defaults.
+	 */
+	error = smb_ctx_resolve(ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]);
+		goto out;
+	}
+
+	/*
+	 * Get the session and tree.
+	 */
+	error = smb_ctx_get_ssn(ctx);
+	if (error) {
+		fprintf(stderr, "//%s: login failed, error %d\n",
+		    server, error);
+		goto out;
+	}
+	error = smb_ctx_get_tree(ctx);
+	if (error) {
+		fprintf(stderr, "//%s/%s: tree connect failed, %d\n",
+		    server, "IPC$", error);
+		goto out;
+	}
+
+	/*
+	 * Do some named pipe I/O.
+	 */
+	error = pipetest(ctx);
+	if (error) {
+		fprintf(stderr, "pipetest, %d\n", error);
+		goto out;
+	}
+
+out:
+	smb_ctx_free(ctx);
+
+	return ((error) ? 1 : 0);
+}
+
+static void
+hexdump(const uchar_t *buf, int len) {
+	int idx;
+	char ascii[24];
+	char *pa = ascii;
+
+	memset(ascii, '\0', sizeof (ascii));
+
+	idx = 0;
+	while (len--) {
+		if ((idx & 15) == 0) {
+			printf("[%04X] ", idx);
+			pa = ascii;
+		}
+		if (*buf > ' ' && *buf <= '~')
+			*pa++ = *buf;
+		else
+			*pa++ = '.';
+		printf("%02x ", *buf++);
+
+		idx++;
+		if ((idx & 7) == 0) {
+			*pa++ = ' ';
+			putchar(' ');
+		}
+		if ((idx & 15) == 0) {
+			*pa = '\0';
+			printf("%s\n", ascii);
+		}
+	}
+
+	if ((idx & 15) != 0) {
+		*pa = '\0';
+		/* column align the last ascii row */
+		do {
+			printf("   ");
+			idx++;
+			if ((idx & 7) == 0)
+				putchar(' ');
+		} while ((idx & 15) != 0);
+		printf("%s\n", ascii);
+	}
+}
+
+/*
+ * Put a unicode UNC server name, including the null.
+ * Quick-n-dirty, just for this test...
+ */
+static int
+put_uncserver(const char *s, uchar_t *buf)
+{
+	uchar_t *p = buf;
+	char c;
+
+	*p++ = '\\'; *p++ = '\0';
+	*p++ = '\\'; *p++ = '\0';
+
+	do {
+		c = *s++;
+		if (c == '/')
+			c = '\\';
+		*p++ = c;
+		*p++ = '\0';
+
+	} while (c != 0);
+
+	return (p - buf);
+}
+
+/*
+ * Send the bind and read the ack.
+ * This tests smb_fh_xactnp.
+ */
+static int
+do_bind(int fid)
+{
+	int err, len, more;
+
+	more = 0;
+	len = sizeof (recvbuf);
+	err = smb_fh_xactnp(fid,
+	    sizeof (srvsvc_bind), (char *)srvsvc_bind,
+	    &len, (char *)recvbuf, &more);
+	if (err) {
+		printf("xact bind, err=%d\n", err);
+		return (err);
+	}
+	if (smb_verbose) {
+		printf("bind ack, len=%d\n", len);
+		hexdump(recvbuf, len);
+	}
+	if (more > 0) {
+		if (more > sizeof (recvbuf)) {
+			printf("bogus more=%d\n", more);
+			more = sizeof (recvbuf);
+		}
+		len = smb_fh_read(fid, 0,
+		    more, (char *)recvbuf);
+		if (len == -1) {
+			err = EIO;
+			printf("read enum resp, err=%d\n", err);
+			return (err);
+		}
+		if (smb_verbose) {
+			printf("bind ack (more), len=%d\n", len);
+			hexdump(recvbuf, len);
+		}
+	}
+
+	return (0);
+}
+
+static int
+do_enum(int fid)
+{
+	int err, len, rlen, wlen;
+	uchar_t *p;
+
+	/*
+	 * Build the enum request - three parts.
+	 * See above: srvsvc_enum1, srvsvc_enum2
+	 *
+	 * First part: RPC header, etc.
+	 */
+	p = sendbuf;
+	len = sizeof (srvsvc_enum1); /* 40 */
+	memcpy(p, srvsvc_enum1, len);
+	p += len;
+
+	/* Second part: UNC server name */
+	len = put_uncserver(server, p);
+	p += len;
+	sendbuf[ENUM_SLEN1_OFF] = len / 2;
+	sendbuf[ENUM_SLEN2_OFF] = len / 2;
+
+	/* Third part: level, etc. (align4) */
+	for (len = (p - sendbuf) & 3; len; len--)
+		*p++ = '\0';
+	len = sizeof (srvsvc_enum2); /* 28 */
+	memcpy(p, srvsvc_enum2, len);
+	p += len;
+
+	/*
+	 * Compute total length, and fixup RPC header.
+	 */
+	len = p - sendbuf;
+	sendbuf[ENUM_RPCLEN_OFF] = len;
+
+	/*
+	 * Send the enum request, read the response.
+	 * This tests smb_fh_write, smb_fh_read.
+	 */
+	wlen = smb_fh_write(fid, 0, len, (char *)sendbuf);
+	if (wlen == -1) {
+		err = errno;
+		printf("write enum req, err=%d\n", err);
+		return (err);
+	}
+	if (wlen != len) {
+		printf("write enum req, short write %d\n", wlen);
+		return (EIO);
+	}
+
+	rlen = smb_fh_read(fid, 0,
+	    sizeof (recvbuf), (char *)recvbuf);
+	if (rlen == -1) {
+		err = errno;
+		printf("read enum resp, err=%d\n", err);
+		return (err);
+	}
+
+	/* Just dump the response data. */
+	printf("enum recv, len=%d\n", rlen);
+	hexdump(recvbuf, rlen);
+
+	return (0);
+}
+
+static int
+pipetest(struct smb_ctx *ctx)
+{
+	static char path[] = "/srvsvc";
+	static uchar_t key[16];
+	int err, fd;
+
+	printf("open pipe: %s\n", path);
+	fd = smb_fh_open(ctx, path, O_RDWR);
+	if (fd < 0) {
+		perror(path);
+		return (errno);
+	}
+
+	/* Test this too. */
+	err = smb_fh_getssnkey(fd, key, sizeof (key));
+	if (err) {
+		printf("getssnkey: %d\n", err);
+		goto out;
+	}
+
+	err = do_bind(fd);
+	if (err) {
+		printf("do_bind: %d\n", err);
+		goto out;
+	}
+	err = do_enum(fd);
+	if (err)
+		printf("do_enum: %d\n", err);
+
+out:
+	smb_fh_close(fd);
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fs.d/smbclnt/test/srvinfo.c	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,415 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Test program for the smbfs named pipe API.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libintl.h>
+
+#include <netsmb/smbfs_api.h>
+
+/*
+ * This is a quick hack for testing client-side named pipes.
+ * Its purpose is to test the ability to connect to a server,
+ * open a pipe, send and receive data.  The "hack" aspect is
+ * the use of hand-crafted RPC messages, which allows testing
+ * of the named pipe API separately from the RPC libraries.
+ *
+ * I captured the two small name pipe messages sent when
+ * requesting a server info via RPC over /pipe/srvsvc and
+ * dropped them into the arrays below (bind and info).
+ * This program sends the two messages (with adjustments)
+ * and just dumps whatever comes back over the pipe.
+ * Use wireshark if you want to see decoded messages.
+ */
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+/* This is a DCE/RPC bind call for "srvsvc". */
+static const uchar_t
+srvsvc_bind[] = {
+	0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
+	0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+	0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
+	0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88,
+	0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+	0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+	0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
+
+/* This is a srvsvc "get server info" call, in two parts */
+static const uchar_t
+srvsvc_info[] = {
+	0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
+#define	INFO_RPCLEN_OFF	8
+	/* V - RPC frag length */
+	0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* ... and the operation number is: VVVV */
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0x00,
+#define	INFO_SLEN1_OFF	28
+#define	INFO_SLEN2_OFF	36
+	/* server name, length 14 vv ... */
+	0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 };
+	/* UNC server here, i.e.: "\\192.168.1.6" */
+
+static uchar_t sendbuf[1024];
+static uchar_t recvbuf[1024];
+static char *server;
+
+static int pipetest(struct smb_ctx *);
+
+static void
+srvinfo_usage(void)
+{
+	printf("usage: srvinfo [-d domain][-u user][-p passwd] server\n");
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int c, error;
+	struct smb_ctx *ctx = NULL;
+	char *dom = NULL;
+	char *usr = NULL;
+	char *pw = NULL;
+
+	while ((c = getopt(argc, argv, "vd:u:p:")) != -1) {
+		switch (c) {
+		case 'v':
+			smb_verbose = 1;
+			break;
+
+		case 'd':
+			dom = optarg;
+			break;
+		case 'u':
+			usr = optarg;
+			break;
+		case 'p':
+			pw = optarg;
+			break;
+		case '?':
+			srvinfo_usage();
+			break;
+		}
+	}
+	if (optind >= argc)
+		srvinfo_usage();
+	server = argv[optind];
+
+	if (pw != NULL && (dom == NULL || usr == NULL)) {
+		fprintf(stderr, "%s: -p arg requires -d dom -u usr\n",
+		    argv[0]);
+		srvinfo_usage();
+	}
+
+	/*
+	 * This section is intended to demonstrate how an
+	 * RPC client library might use this interface.
+	 */
+	error = smb_ctx_alloc(&ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]);
+		goto out;
+	}
+
+	/*
+	 * Set server, share, domain, user
+	 * (in the ctx handle).
+	 */
+	smb_ctx_setfullserver(ctx, server);
+	smb_ctx_setshare(ctx, "IPC$", USE_IPC);
+	if (dom)
+		smb_ctx_setdomain(ctx, dom, B_TRUE);
+	if (usr)
+		smb_ctx_setuser(ctx, usr, B_TRUE);
+	if (pw)
+		smb_ctx_setpassword(ctx, pw, NULL);
+
+
+	/*
+	 * If this code were in smbutil or mount_smbfs, it would
+	 * get system and $HOME/.nsmbrc settings here, like this:
+	 */
+#if 0
+	error = smb_ctx_readrc(ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_readrc failed\n", argv[0]);
+		goto out;
+	}
+#endif
+
+	/*
+	 * Resolve the server address,
+	 * setup derived defaults.
+	 */
+	error = smb_ctx_resolve(ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]);
+		goto out;
+	}
+
+	/*
+	 * Get the session and tree.
+	 */
+	error = smb_ctx_get_ssn(ctx);
+	if (error) {
+		fprintf(stderr, "//%s: login failed, error %d\n",
+		    server, error);
+		goto out;
+	}
+	error = smb_ctx_get_tree(ctx);
+	if (error) {
+		fprintf(stderr, "//%s/%s: tree connect failed, %d\n",
+		    server, "IPC$", error);
+		goto out;
+	}
+
+	/*
+	 * Do some named pipe I/O.
+	 */
+	error = pipetest(ctx);
+	if (error) {
+		fprintf(stderr, "pipetest, %d\n", error);
+		goto out;
+	}
+
+out:
+	smb_ctx_free(ctx);
+
+	return ((error) ? 1 : 0);
+}
+
+static void
+hexdump(const uchar_t *buf, int len) {
+	int ofs = 0;
+
+	while (len--) {
+		if (ofs % 16 == 0)
+			printf("\n%02X: ", ofs);
+		printf("%02x ", *buf++);
+		ofs++;
+	}
+	printf("\n");
+}
+
+/*
+ * Put a unicode UNC server name, including the null.
+ * Quick-n-dirty, just for this test...
+ */
+static int
+put_uncserver(const char *s, uchar_t *buf)
+{
+	uchar_t *p = buf;
+	char c;
+
+	*p++ = '\\'; *p++ = '\0';
+	*p++ = '\\'; *p++ = '\0';
+
+	do {
+		c = *s++;
+		if (c == '/')
+			c = '\\';
+		*p++ = c;
+		*p++ = '\0';
+
+	} while (c != 0);
+
+	return (p - buf);
+}
+
+/* Get a little-endian int.  Just for testing. */
+static int
+getint(const uchar_t *p)
+{
+	return (p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24));
+}
+
+/*
+ * Send the bind and read the ack.
+ * This tests smb_fh_xactnp.
+ */
+static int
+do_bind(int fid)
+{
+	int err, len, more;
+
+	more = 0;
+	len = sizeof (recvbuf);
+	err = smb_fh_xactnp(fid,
+	    sizeof (srvsvc_bind), (char *)srvsvc_bind,
+	    &len, (char *)recvbuf, &more);
+	if (err) {
+		printf("xact bind, err=%d\n", err);
+		return (err);
+	}
+	if (smb_verbose) {
+		printf("bind ack, len=%d\n", len);
+		hexdump(recvbuf, len);
+	}
+	if (more > 0) {
+		if (more > sizeof (recvbuf)) {
+			printf("bogus more=%d\n", more);
+			more = sizeof (recvbuf);
+		}
+		len = smb_fh_read(fid, 0,
+		    more, (char *)recvbuf);
+		if (len == -1) {
+			err = EIO;
+			printf("read info resp, err=%d\n", err);
+			return (err);
+		}
+		if (smb_verbose) {
+			printf("bind ack (more), len=%d\n", len);
+			hexdump(recvbuf, len);
+		}
+	}
+
+	return (0);
+}
+
+static int
+do_info(int fid)
+{
+	int err, len, rlen, wlen, x;
+	uchar_t *p;
+
+	/*
+	 * Build the info request - two parts.
+	 * See above: srvsvc_info
+	 *
+	 * First part: RPC header, etc.
+	 */
+	p = sendbuf;
+	len = sizeof (srvsvc_info); /* 40 */
+	memcpy(p, srvsvc_info, len);
+	p += len;
+
+	/* Second part: UNC server name */
+	len = put_uncserver(server, p);
+	p += len;
+	sendbuf[INFO_SLEN1_OFF] = len / 2;
+	sendbuf[INFO_SLEN2_OFF] = len / 2;
+
+	/* Third part: level, etc. (align4) */
+	for (len = (p - sendbuf) & 3; len; len--)
+		*p++ = '\0';
+	*p++ = 101;	/* the "level" */
+	*p++ = 0; *p++ = 0; *p++ = 0;
+
+	/*
+	 * Compute total length, and fixup RPC header.
+	 */
+	len = p - sendbuf;
+	sendbuf[INFO_RPCLEN_OFF] = len;
+
+	/*
+	 * Send the info request, read the response.
+	 * This tests smb_fh_write, smb_fh_read.
+	 */
+	wlen = smb_fh_write(fid, 0, len, (char *)sendbuf);
+	if (wlen == -1) {
+		err = errno;
+		printf("write info req, err=%d\n", err);
+		return (err);
+	}
+	if (wlen != len) {
+		printf("write info req, short write %d\n", wlen);
+		return (EIO);
+	}
+
+	rlen = smb_fh_read(fid, 0,
+	    sizeof (recvbuf), (char *)recvbuf);
+	if (rlen == -1) {
+		err = errno;
+		printf("read info resp, err=%d\n", err);
+		return (err);
+	}
+
+	if (smb_verbose) {
+		printf("info recv, len=%d\n", rlen);
+		hexdump(recvbuf, rlen);
+	}
+
+	x = getint(recvbuf + 4);
+	if (x != 0x10) {
+		printf("Data representation 0x%x not supported\n", x);
+		return (ENOTSUP);
+	}
+	printf("Platform Id: %d\n", getint(recvbuf + 0x20));
+	printf("Version Major: %d\n", getint(recvbuf + 0x28));
+	printf("Version Minor: %d\n", getint(recvbuf + 0x2c));
+	printf("Srv type flags: 0x%x\n", getint(recvbuf + 0x30));
+
+	return (0);
+}
+
+static int
+pipetest(struct smb_ctx *ctx)
+{
+	static char path[] = "/srvsvc";
+	static uchar_t key[16];
+	int err, fd;
+
+	printf("open pipe: %s\n", path);
+	fd = smb_fh_open(ctx, path, O_RDWR);
+	if (fd < 0) {
+		perror(path);
+		return (errno);
+	}
+
+	/* Test this too. */
+	err = smb_fh_getssnkey(fd, key, sizeof (key));
+	if (err) {
+		printf("getssnkey: %d\n", err);
+		goto out;
+	}
+
+	err = do_bind(fd);
+	if (err) {
+		printf("do_bind: %d\n", err);
+		goto out;
+	}
+	err = do_info(fd);
+	if (err)
+		printf("do_info: %d\n", err);
+
+out:
+	smb_fh_close(fd);
+	return (err);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fs.d/smbclnt/test/tconn.c	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,171 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Test program for opening an SMB connection directly.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <libintl.h>
+
+#include <netsmb/smb_lib.h>
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+extern int smb_iod_connect(struct smb_ctx *);
+
+static char *server;
+
+static void
+tconn_usage(void)
+{
+	printf("usage: tconn [-d domain][-u user][-p passwd] server\n");
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int c, error, aflags;
+	struct smb_ctx *ctx = NULL;
+	char *dom = NULL;
+	char *usr = NULL;
+	char *pw = NULL;
+	char *secopt = NULL;
+	struct addrinfo *ai;
+
+	while ((c = getopt(argc, argv, "vd:p:s:u:")) != -1) {
+		switch (c) {
+		case 'v':
+			smb_debug = 1;
+			smb_verbose = 1;
+			break;
+
+		case 'd':
+			dom = optarg;
+			break;
+		case 'u':
+			usr = optarg;
+			break;
+		case 'p':
+			pw = optarg;
+			break;
+		case 's':
+			secopt = optarg;
+			break;
+		case '?':
+			tconn_usage();
+			break;
+		}
+	}
+	if (optind >= argc)
+		tconn_usage();
+	server = argv[optind];
+
+	if (pw != NULL && (dom == NULL || usr == NULL)) {
+		fprintf(stderr, "%s: -p arg requires -d dom -u usr\n",
+		    argv[0]);
+		tconn_usage();
+	}
+
+	/*
+	 * This section is intended to demonstrate how an
+	 * RPC client library might use this interface.
+	 */
+	error = smb_ctx_alloc(&ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]);
+		goto out;
+	}
+
+	/*
+	 * Set server, share, domain, user
+	 * (in the ctx handle).
+	 */
+	smb_ctx_setfullserver(ctx, server);
+	smb_ctx_setshare(ctx, "IPC$", USE_IPC);
+	if (dom)
+		smb_ctx_setdomain(ctx, dom, B_TRUE);
+	if (usr)
+		smb_ctx_setuser(ctx, usr, B_TRUE);
+	if (pw)
+		smb_ctx_setpassword(ctx, pw, NULL);
+
+	/*
+	 * Hackish option to override the Authentication Type flags.
+	 * Sorry about exposing the flag values here, but this is
+	 * really a programmer's test tool.  See smbfs_api.h for
+	 * the SMB_AT_... flag values.
+	 */
+	if (secopt != NULL) {
+		aflags = atoi(secopt);
+		if (aflags < 1 || aflags > 0x1f) {
+			fprintf(stderr, "%s: -s {0..31}\n", argv[0]);
+			tconn_usage();
+		}
+		smb_ctx_setauthflags(ctx, aflags);
+	}
+
+	/*
+	 * Resolve the server address,
+	 * setup derived defaults.
+	 */
+	error = smb_ctx_resolve(ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]);
+		goto out;
+	}
+
+	if ((ai = ctx->ct_addrinfo) == NULL) {
+		fprintf(stderr, "%s: no ct_addrinfo\n", argv[0]);
+		goto out;
+	}
+	memcpy(&ctx->ct_srvaddr, ai->ai_addr, ai->ai_addrlen);
+
+	/*
+	 * If this code were in smbutil or mount_smbfs, it would
+	 * get system and $HOME/.nsmbrc settings here, like this:
+	 */
+	error = smb_iod_connect(ctx);
+	if (error) {
+		fprintf(stderr, "%s: smb_iod_connect failed\n", argv[0]);
+		goto out;
+	}
+
+	printf("Yea, we connected!\n");
+
+out:
+	smb_ctx_free(ctx);
+
+	return ((error) ? 1 : 0);
+}
--- a/usr/src/cmd/fs.d/smbclnt/test/testnp.c	Thu Nov 06 07:49:31 2014 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,416 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-/*
- * Test program for the smbfs named pipe API.
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <libintl.h>
-
-#include <netsmb/smbfs_api.h>
-
-/*
- * This is a quick hack for testing client-side named pipes.
- * Its purpose is to test the ability to connect to a server,
- * open a pipe, send and receive data.  The "hack" aspect is
- * the use of hand-crafted RPC messages, which allows testing
- * of the named pipe API separately from the RPC libraries.
- *
- * I captured the two small name pipe messages sent when
- * requesting a server info via RPC over /pipe/srvsvc and
- * dropped them into the arrays below (bind and info).
- * This program sends the two messages (with adjustments)
- * and just dumps whatever comes back over the pipe.
- * Use wireshark if you want to see decoded messages.
- */
-
-extern char *optarg;
-extern int optind, opterr, optopt;
-
-/* This is a DCE/RPC bind call for "srvsvc". */
-static const uchar_t
-srvsvc_bind[] = {
-	0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
-	0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-	0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
-	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
-	0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
-	0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88,
-	0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
-	0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
-	0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
-
-/* This is a srvsvc "get server info" call, in two parts */
-static const uchar_t
-srvsvc_info[] = {
-	0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
-#define	INFO_RPCLEN_OFF	8
-	/* V - RPC frag length */
-	0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* ... and the operation number is: VVVV */
-	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0x00,
-#define	INFO_SLEN1_OFF	28
-#define	INFO_SLEN2_OFF	36
-	/* server name, length 14 vv ... */
-	0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 };
-	/* UNC server here, i.e.: "\\192.168.1.6" */
-
-static uchar_t sendbuf[1024];
-static uchar_t recvbuf[1024];
-static char *server;
-
-static int pipetest(struct smb_ctx *);
-
-static void
-testnp_usage(void)
-{
-	printf("usage: testnp [-d domain][-u user][-p passwd] server\n");
-	exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
-	int c, error;
-	struct smb_ctx *ctx = NULL;
-	char *dom = NULL;
-	char *usr = NULL;
-	char *pw = NULL;
-
-	while ((c = getopt(argc, argv, "vd:u:p:")) != -1) {
-		switch (c) {
-		case 'v':
-			smb_verbose = 1;
-			break;
-
-		case 'd':
-			dom = optarg;
-			break;
-		case 'u':
-			usr = optarg;
-			break;
-		case 'p':
-			pw = optarg;
-			break;
-		case '?':
-			testnp_usage();
-			break;
-		}
-	}
-	if (optind >= argc)
-		testnp_usage();
-	server = argv[optind];
-
-	if (pw != NULL && (dom == NULL || usr == NULL)) {
-		fprintf(stderr, "%0: -p arg requires -d dom -u usr\n",
-		    argv[0]);
-		testnp_usage();
-	}
-
-	/*
-	 * This section is intended to demonstrate how an
-	 * RPC client library might use this interface.
-	 */
-	error = smb_ctx_alloc(&ctx);
-	if (error) {
-		fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]);
-		goto out;
-	}
-
-	/*
-	 * Set server, share, domain, user
-	 * (in the ctx handle).
-	 */
-	smb_ctx_setfullserver(ctx, server);
-	smb_ctx_setshare(ctx, "IPC$", USE_IPC);
-	if (dom)
-		smb_ctx_setdomain(ctx, dom, B_TRUE);
-	if (usr)
-		smb_ctx_setuser(ctx, usr, B_TRUE);
-	if (pw)
-		smb_ctx_setpassword(ctx, pw, NULL);
-
-
-	/*
-	 * If this code were in smbutil or mount_smbfs, it would
-	 * get system and $HOME/.nsmbrc settings here, like this:
-	 */
-#if 0
-	error = smb_ctx_readrc(ctx);
-	if (error) {
-		fprintf(stderr, "%s: smb_ctx_readrc failed\n", argv[0]);
-		goto out;
-	}
-#endif
-
-	/*
-	 * Resolve the server address,
-	 * setup derived defaults.
-	 */
-	error = smb_ctx_resolve(ctx);
-	if (error) {
-		fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]);
-		goto out;
-	}
-
-	/*
-	 * Get the session and tree.
-	 */
-	error = smb_ctx_get_ssn(ctx);
-	if (error) {
-		fprintf(stderr, "//%s: login failed, error %d\n",
-		    server, error);
-		goto out;
-	}
-	error = smb_ctx_get_tree(ctx);
-	if (error) {
-		fprintf(stderr, "//%s/%s: tree connect failed, %d\n",
-		    server, "IPC$", error);
-		goto out;
-	}
-
-	/*
-	 * Do some named pipe I/O.
-	 */
-	error = pipetest(ctx);
-	if (error) {
-		fprintf(stderr, "pipetest, %d\n", error);
-		goto out;
-	}
-
-out:
-	smb_ctx_free(ctx);
-
-	return ((error) ? 1 : 0);
-}
-
-static void
-hexdump(const uchar_t *buf, int len) {
-	int ofs = 0;
-
-	while (len--) {
-		if (ofs % 16 == 0)
-			printf("\n%02X: ", ofs);
-		printf("%02x ", *buf++);
-		ofs++;
-	}
-	printf("\n");
-}
-
-/*
- * Put a unicode UNC server name, including the null.
- * Quick-n-dirty, just for this test...
- */
-static int
-put_uncserver(const char *s, uchar_t *buf)
-{
-	uchar_t *p = buf;
-	int slashcnt = 0;
-	char c;
-
-	*p++ = '\\'; *p++ = '\0';
-	*p++ = '\\'; *p++ = '\0';
-
-	do {
-		c = *s++;
-		if (c == '/')
-			c = '\\';
-		*p++ = c;
-		*p++ = '\0';
-
-	} while (c != 0);
-
-	return (p - buf);
-}
-
-/* Get a little-endian int.  Just for testing. */
-static int
-getint(const uchar_t *p)
-{
-	return (p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24));
-}
-
-/*
- * Send the bind and read the ack.
- * This tests smb_fh_xactnp.
- */
-static int
-do_bind(int fid)
-{
-	int err, len, more;
-
-	more = 0;
-	len = sizeof (recvbuf);
-	err = smb_fh_xactnp(fid,
-	    sizeof (srvsvc_bind), (char *)srvsvc_bind,
-	    &len, (char *)recvbuf, &more);
-	if (err) {
-		printf("xact bind, err=%d\n", err);
-		return (err);
-	}
-	if (smb_verbose) {
-		printf("bind ack, len=%d\n", len);
-		hexdump(recvbuf, len);
-	}
-	if (more > 0) {
-		if (more > sizeof (recvbuf)) {
-			printf("bogus more=%d\n", more);
-			more = sizeof (recvbuf);
-		}
-		len = smb_fh_read(fid, 0,
-		    more, (char *)recvbuf);
-		if (len == -1) {
-			err = EIO;
-			printf("read info resp, err=%d\n", err);
-			return (err);
-		}
-		if (smb_verbose) {
-			printf("bind ack (more), len=%d\n", len);
-			hexdump(recvbuf, len);
-		}
-	}
-
-	return (0);
-}
-
-static int
-do_info(int fid)
-{
-	int err, len, rlen, wlen, x;
-	uchar_t *p;
-
-	/*
-	 * Build the info request - two parts.
-	 * See above: srvsvc_info
-	 *
-	 * First part: RPC header, etc.
-	 */
-	p = sendbuf;
-	len = sizeof (srvsvc_info); /* 40 */
-	memcpy(p, srvsvc_info, len);
-	p += len;
-
-	/* Second part: UNC server name */
-	len = put_uncserver(server, p);
-	p += len;
-	sendbuf[INFO_SLEN1_OFF] = len / 2;
-	sendbuf[INFO_SLEN2_OFF] = len / 2;
-
-	/* Third part: level, etc. (align4) */
-	for (len = (p - sendbuf) & 3; len; len--)
-		*p++ = '\0';
-	*p++ = 101;	/* the "level" */
-	*p++ = 0; *p++ = 0; *p++ = 0;
-
-	/*
-	 * Compute total length, and fixup RPC header.
-	 */
-	len = p - sendbuf;
-	sendbuf[INFO_RPCLEN_OFF] = len;
-
-	/*
-	 * Send the info request, read the response.
-	 * This tests smb_fh_write, smb_fh_read.
-	 */
-	wlen = smb_fh_write(fid, 0, len, (char *)sendbuf);
-	if (wlen == -1) {
-		err = errno;
-		printf("write info req, err=%d\n", err);
-		return (err);
-	}
-	if (wlen != len) {
-		printf("write info req, short write %d\n", wlen);
-		return (EIO);
-	}
-
-	rlen = smb_fh_read(fid, 0,
-	    sizeof (recvbuf), (char *)recvbuf);
-	if (rlen == -1) {
-		err = errno;
-		printf("read info resp, err=%d\n", err);
-		return (err);
-	}
-
-	if (smb_verbose) {
-		printf("info recv, len=%d\n", rlen);
-		hexdump(recvbuf, rlen);
-	}
-
-	x = getint(recvbuf + 4);
-	if (x != 0x10) {
-		printf("Data representation 0x%x not supported\n", x);
-		return (ENOTSUP);
-	}
-	printf("Platform Id: %d\n", getint(recvbuf + 0x20));
-	printf("Version Major: %d\n", getint(recvbuf + 0x28));
-	printf("Version Minor: %d\n", getint(recvbuf + 0x2c));
-	printf("Srv type flags: 0x%x\n", getint(recvbuf + 0x30));
-
-	return (0);
-}
-
-static int
-pipetest(struct smb_ctx *ctx)
-{
-	static char path[] = "/srvsvc";
-	static uchar_t key[16];
-	int err, fd;
-
-	printf("open pipe: %s\n", path);
-	fd = smb_fh_open(ctx, path, O_RDWR);
-	if (fd < 0) {
-		perror(path);
-		return (errno);
-	}
-
-	/* Test this too. */
-	err = smb_fh_getssnkey(fd, key, sizeof (key));
-	if (err) {
-		printf("getssnkey: %d\n", err);
-		goto out;
-	}
-
-	err = do_bind(fd);
-	if (err) {
-		printf("do_bind: %d\n", err);
-		goto out;
-	}
-	err = do_info(fd);
-	if (err)
-		printf("do_info: %d\n", err);
-
-out:
-	smb_fh_close(fd);
-	return (err);
-}
--- a/usr/src/cmd/idmap/idmapd/idmap.xml	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/idmap/idmapd/idmap.xml	Wed Nov 12 04:51:53 2014 -0800
@@ -96,6 +96,14 @@
 			name='value_authorization'
 			type='astring'
 			value='solaris.smf.value.idmap' />
+		<propval
+			name='id_cache_timeout'
+			type='count'
+			value='86400' />
+		<propval
+			name='name_cache_timeout'
+			type='count'
+			value='604800' />
 	</property_group>
 
 	<property_group name='debug' type='application' >
--- a/usr/src/cmd/idmap/idmapd/idmap_config.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/idmap/idmapd/idmap_config.c	Wed Nov 12 04:51:53 2014 -0800
@@ -56,8 +56,8 @@
  * config/id_cache_timeout = count: seconds
  * config/name_cache_timeout = count: seconds
  */
-#define	ID_CACHE_TMO_DEFAULT	600
-#define	NAME_CACHE_TMO_DEFAULT	3600
+#define	ID_CACHE_TMO_DEFAULT	86400
+#define	NAME_CACHE_TMO_DEFAULT	604800
 
 enum event_type {
 	EVENT_NOTHING,	/* Woke up for no good reason */
--- a/usr/src/cmd/ls/Makefile.com	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/ls/Makefile.com	Wed Nov 12 04:51:53 2014 -0800
@@ -35,8 +35,6 @@
 
 LDLIBS += -lsec -lnvpair -lcmdutils -lcurses
 CFLAGS	+=	$(CCVERBOSE)
-CERRWARN +=	-_gcc=-Wno-parentheses
-CERRWARN +=	-_gcc=-Wno-uninitialized
 $(XPG4) := CFLAGS += -DXPG4
 
 # Include all XPG4 changes in the XPG6 version
--- a/usr/src/cmd/ls/ls.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/ls/ls.c	Wed Nov 12 04:51:53 2014 -0800
@@ -414,7 +414,7 @@
 	int		option_index = 0;
 	struct lbuf	*ep;
 	struct lbuf	lb;
-	struct ditem	*myinfo;
+	struct ditem	*myinfo = NULL;
 
 	(void) setlocale(LC_ALL, "");
 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
@@ -1096,7 +1096,7 @@
 		qsort(flist, (unsigned)nargs, sizeof (struct lbuf *),
 		    (int (*)(const void *, const void *))compar);
 	for (i = 0; i < nargs; i++) {
-		if (flist[i]->ltype == 'd' && dflg == 0 || fflg)
+		if ((flist[i]->ltype == 'd' && dflg == 0) || fflg)
 			break;
 	}
 
@@ -1210,13 +1210,11 @@
 pem(struct lbuf **slp, struct lbuf **lp, int tot_flag)
 {
 	long row, nrows, i;
-	int col, ncols;
+	int col, ncols = 1;
 	struct lbuf **ep;
 
 	if (Cflg || mflg) {
-		if (colwidth > num_cols) {
-			ncols = 1;
-		} else {
+		if (colwidth <= num_cols) {
 			ncols = num_cols / colwidth;
 		}
 	}
@@ -1268,16 +1266,18 @@
 
 	p = ap;
 	column();
-	if (iflg)
+	if (iflg) {
 		if (mflg && !lflg)
 			curcol += printf("%llu ", (long long)p->lnum);
 		else
 			curcol += printf("%10llu ", (long long)p->lnum);
-	if (sflg)
+	}
+	if (sflg) {
 		curcol += printf((mflg && !lflg) ? "%lld " :
 		    (p->lblocks < 10000) ? "%4lld " : "%lld ",
 		    (p->ltype != 'b' && p->ltype != 'c') ?
 		    p->lblocks : 0LL);
+	}
 	if (lflg) {
 		(void) putchar(p->ltype);
 		curcol++;
@@ -1288,18 +1288,20 @@
 		curcol++;
 
 		curcol += printf("%3lu ", (ulong_t)p->lnl);
-		if (oflg)
+		if (oflg) {
 			if (!nflg) {
 				cp = getname(p->luid);
 				curcol += printf("%-8s ", cp);
 			} else
 				curcol += printf("%-8lu ", (ulong_t)p->luid);
-		if (gflg)
+		}
+		if (gflg) {
 			if (!nflg) {
 				cp = getgroup(p->lgid);
 				curcol += printf("%-8s ", cp);
 			} else
 				curcol += printf("%-8lu ", (ulong_t)p->lgid);
+		}
 		if (p->ltype == 'b' || p->ltype == 'c') {
 			curcol += printf("%3u, %2u",
 			    (uint_t)major((dev_t)p->lsize),
@@ -1561,8 +1563,8 @@
 			if (aflg == 0 && dentry->d_name[0] == '.' &&
 			    (Aflg == 0 ||
 			    dentry->d_name[1] == '\0' ||
-			    dentry->d_name[1] == '.' &&
-			    dentry->d_name[2] == '\0'))
+			    (dentry->d_name[1] == '.' &&
+			    dentry->d_name[2] == '\0')))
 				/*
 				 * check for directory items '.', '..',
 				 *  and items without valid inode-number;
--- a/usr/src/cmd/zdb/zdb.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/zdb/zdb.c	Wed Nov 12 04:51:53 2014 -0800
@@ -2120,6 +2120,8 @@
 	(void) close(fd);
 }
 
+static uint64_t num_large_blocks;
+
 /*ARGSUSED*/
 static int
 dump_one_dir(const char *dsname, void *arg)
@@ -2132,6 +2134,8 @@
 		(void) printf("Could not open %s, error %d\n", dsname, error);
 		return (0);
 	}
+	if (dmu_objset_ds(os)->ds_large_blocks)
+		num_large_blocks++;
 	dump_dir(os);
 	dmu_objset_disown(os, FTAG);
 	fuid_table_destroy();
@@ -2142,7 +2146,7 @@
 /*
  * Block statistics.
  */
-#define	PSIZE_HISTO_SIZE (SPA_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 1)
+#define	PSIZE_HISTO_SIZE (SPA_OLD_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 2)
 typedef struct zdb_blkstats {
 	uint64_t zb_asize;
 	uint64_t zb_lsize;
@@ -2207,7 +2211,15 @@
 		zb->zb_lsize += BP_GET_LSIZE(bp);
 		zb->zb_psize += BP_GET_PSIZE(bp);
 		zb->zb_count++;
-		zb->zb_psize_histogram[BP_GET_PSIZE(bp) >> SPA_MINBLOCKSHIFT]++;
+
+		/*
+		 * The histogram is only big enough to record blocks up to
+		 * SPA_OLD_MAXBLOCKSIZE; larger blocks go into the last,
+		 * "other", bucket.
+		 */
+		int idx = BP_GET_PSIZE(bp) >> SPA_MINBLOCKSHIFT;
+		idx = MIN(idx, SPA_OLD_MAXBLOCKSIZE / SPA_MINBLOCKSIZE + 1);
+		zb->zb_psize_histogram[idx]++;
 
 		zb->zb_gangs += BP_COUNT_GANG(bp);
 
@@ -2917,6 +2929,7 @@
 		dump_metaslab_groups(spa);
 
 	if (dump_opt['d'] || dump_opt['i']) {
+		uint64_t refcount;
 		dump_dir(dp->dp_meta_objset);
 		if (dump_opt['d'] >= 3) {
 			dump_bpobj(&spa->spa_deferred_bpobj,
@@ -2936,8 +2949,21 @@
 		}
 		(void) dmu_objset_find(spa_name(spa), dump_one_dir,
 		    NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
+
+		(void) feature_get_refcount(spa,
+		    &spa_feature_table[SPA_FEATURE_LARGE_BLOCKS], &refcount);
+		if (num_large_blocks != refcount) {
+			(void) printf("large_blocks feature refcount mismatch: "
+			    "expected %lld != actual %lld\n",
+			    (longlong_t)num_large_blocks,
+			    (longlong_t)refcount);
+			rc = 2;
+		} else {
+			(void) printf("Verified large_blocks feature refcount "
+			    "is correct (%llu)\n", (longlong_t)refcount);
+		}
 	}
-	if (dump_opt['b'] || dump_opt['c'])
+	if (rc == 0 && (dump_opt['b'] || dump_opt['c']))
 		rc = dump_block_stats(spa);
 
 	if (rc == 0)
--- a/usr/src/cmd/zfs/zfs_main.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/zfs/zfs_main.c	Wed Nov 12 04:51:53 2014 -0800
@@ -256,9 +256,9 @@
 	case HELP_ROLLBACK:
 		return (gettext("\trollback [-rRf] <snapshot>\n"));
 	case HELP_SEND:
-		return (gettext("\tsend [-DnPpRve] [-[iI] snapshot] "
+		return (gettext("\tsend [-DnPpRvLe] [-[iI] snapshot] "
 		    "<snapshot>\n"
-		    "\tsend [-e] [-i snapshot|bookmark] "
+		    "\tsend [-Le] [-i snapshot|bookmark] "
 		    "<filesystem|volume|snapshot>\n"));
 	case HELP_SET:
 		return (gettext("\tset <property=value> "
@@ -3640,7 +3640,7 @@
 	boolean_t extraverbose = B_FALSE;
 
 	/* check options */
-	while ((c = getopt(argc, argv, ":i:I:RDpvnPe")) != -1) {
+	while ((c = getopt(argc, argv, ":i:I:RDpvnPLe")) != -1) {
 		switch (c) {
 		case 'i':
 			if (fromname)
@@ -3675,6 +3675,9 @@
 		case 'n':
 			flags.dryrun = B_TRUE;
 			break;
+		case 'L':
+			flags.largeblock = B_TRUE;
+			break;
 		case 'e':
 			flags.embed_data = B_TRUE;
 			break;
@@ -3731,6 +3734,8 @@
 		if (zhp == NULL)
 			return (1);
 
+		if (flags.largeblock)
+			lzc_flags |= LZC_SEND_FLAG_LARGE_BLOCK;
 		if (flags.embed_data)
 			lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
 
--- a/usr/src/cmd/zstreamdump/zstreamdump.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/zstreamdump/zstreamdump.c	Wed Nov 12 04:51:53 2014 -0800
@@ -54,7 +54,6 @@
 FILE *send_stream = 0;
 boolean_t do_byteswap = B_FALSE;
 boolean_t do_cksum = B_TRUE;
-#define	INITIAL_BUFLEN (1<<20)
 
 static void
 usage(void)
@@ -67,6 +66,18 @@
 	exit(1);
 }
 
+static void *
+safe_malloc(size_t size)
+{
+	void *rv = malloc(size);
+	if (rv == NULL) {
+		(void) fprintf(stderr, "ERROR; failed to allocate %zu bytes\n",
+		    size);
+		abort();
+	}
+	return (rv);
+}
+
 /*
  * ssread - send stream read.
  *
@@ -158,7 +169,7 @@
 int
 main(int argc, char *argv[])
 {
-	char *buf = malloc(INITIAL_BUFLEN);
+	char *buf = safe_malloc(SPA_MAXBLOCKSIZE);
 	uint64_t drr_record_count[DRR_NUMTYPES] = { 0 };
 	uint64_t total_records = 0;
 	dmu_replay_record_t thedrr;
@@ -307,9 +318,9 @@
 				nvlist_t *nv;
 				int sz = drr->drr_payloadlen;
 
-				if (sz > INITIAL_BUFLEN) {
+				if (sz > SPA_MAXBLOCKSIZE) {
 					free(buf);
-					buf = malloc(sz);
+					buf = safe_malloc(sz);
 				}
 				(void) ssread(buf, sz, &zc);
 				if (ferror(send_stream))
--- a/usr/src/cmd/ztest/ztest.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/cmd/ztest/ztest.c	Wed Nov 12 04:51:53 2014 -0800
@@ -985,9 +985,15 @@
 static int
 ztest_random_blocksize(void)
 {
-	// Choose a block size >= the ashift.
-	uint64_t block_shift =
-	    ztest_random(SPA_MAXBLOCKSHIFT - ztest_spa_get_ashift() + 1);
+	uint64_t block_shift;
+	/*
+	 * Choose a block size >= the ashift.
+	 * If the SPA supports new MAXBLOCKSIZE, test up to 1MB blocks.
+	 */
+	int maxbs = SPA_OLD_MAXBLOCKSHIFT;
+	if (spa_maxblocksize(ztest_spa) == SPA_MAXBLOCKSIZE)
+		maxbs = 20;
+	block_shift = ztest_random(maxbs - ztest_spa_get_ashift() + 1);
 	return (1 << (SPA_MINBLOCKSHIFT + block_shift));
 }
 
@@ -4787,7 +4793,7 @@
 	char path0[MAXPATHLEN];
 	char pathrand[MAXPATHLEN];
 	size_t fsize;
-	int bshift = SPA_MAXBLOCKSHIFT + 2;	/* don't scrog all labels */
+	int bshift = SPA_OLD_MAXBLOCKSHIFT + 2;	/* don't scrog all labels */
 	int iters = 1000;
 	int maxfaults;
 	int mirror_save;
--- a/usr/src/common/zfs/zfeature_common.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/common/zfs/zfeature_common.c	Wed Nov 12 04:51:53 2014 -0800
@@ -57,7 +57,8 @@
 {
 	return ((c >= 'a' && c <= 'z') ||
 	    (c >= '0' && c <= '9') ||
-	    c == (after_colon ? '_' : '.'));
+	    (after_colon && c == '_') ||
+	    (!after_colon && (c == '.' || c == '-')));
 }
 
 /*
@@ -221,4 +222,13 @@
 	    "com.delphix:embedded_data", "embedded_data",
 	    "Blocks which compress very well use even less space.",
 	    B_FALSE, B_TRUE, B_TRUE, NULL);
+
+	static const spa_feature_t large_blocks_deps[] = {
+		SPA_FEATURE_EXTENSIBLE_DATASET,
+		SPA_FEATURE_NONE
+	};
+	zfeature_register(SPA_FEATURE_LARGE_BLOCKS,
+	    "org.open-zfs:large_blocks", "large_blocks",
+	    "Support for blocks larger than 128KB.", B_FALSE, B_FALSE, B_FALSE,
+	    large_blocks_deps);
 }
--- a/usr/src/common/zfs/zfeature_common.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/common/zfs/zfeature_common.h	Wed Nov 12 04:51:53 2014 -0800
@@ -51,6 +51,7 @@
 	SPA_FEATURE_EMBEDDED_DATA,
 	SPA_FEATURE_BOOKMARKS,
 	SPA_FEATURE_FS_SS_LIMIT,
+	SPA_FEATURE_LARGE_BLOCKS,
 	SPA_FEATURES
 } spa_feature_t;
 
--- a/usr/src/common/zfs/zfs_prop.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/common/zfs/zfs_prop.c	Wed Nov 12 04:51:53 2014 -0800
@@ -397,8 +397,8 @@
 
 	/* inherit number properties */
 	zprop_register_number(ZFS_PROP_RECORDSIZE, "recordsize",
-	    SPA_MAXBLOCKSIZE, PROP_INHERIT,
-	    ZFS_TYPE_FILESYSTEM, "512 to 128k, power of 2", "RECSIZE");
+	    SPA_OLD_MAXBLOCKSIZE, PROP_INHERIT,
+	    ZFS_TYPE_FILESYSTEM, "512 to 1M, power of 2", "RECSIZE");
 
 	/* hidden properties */
 	zprop_register_hidden(ZFS_PROP_CREATETXG, "createtxg", PROP_TYPE_NUMBER,
--- a/usr/src/common/zfs/zpool_prop.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/common/zfs/zpool_prop.c	Wed Nov 12 04:51:53 2014 -0800
@@ -127,6 +127,8 @@
 	/* hidden properties */
 	zprop_register_hidden(ZPOOL_PROP_NAME, "name", PROP_TYPE_STRING,
 	    PROP_READONLY, ZFS_TYPE_POOL, "NAME");
+	zprop_register_hidden(ZPOOL_PROP_MAXBLOCKSIZE, "maxblocksize",
+	    PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_POOL, "MAXBLOCKSIZE");
 }
 
 /*
--- a/usr/src/grub/grub-0.97/stage2/fsys_zfs.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/grub/grub-0.97/stage2/fsys_zfs.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1048,6 +1048,7 @@
 	"com.delphix:hole_birth",
 	"com.delphix:extensible_dataset",
 	"com.delphix:embedded_data",
+	"org.open-zfs:large_blocks",
 	NULL
 };
 
@@ -1837,6 +1838,17 @@
 	blksz = DNODE->dn_datablkszsec << SPA_MINBLOCKSHIFT;
 
 	/*
+	 * Note: for GRUB, SPA_MAXBLOCKSIZE is 128KB.  There is not enough
+	 * memory to allocate the new max blocksize (16MB), so while
+	 * GRUB understands the large_blocks on-disk feature, it can't
+	 * actually read large blocks.
+	 */
+	if (blksz > SPA_MAXBLOCKSIZE) {
+		grub_printf("blocks larger than 128K are not supported\n");
+		return (0);
+	}
+
+	/*
 	 * Entire Dnode is too big to fit into the space available.  We
 	 * will need to read it in chunks.  This could be optimized to
 	 * read in as large a chunk as there is space available, but for
--- a/usr/src/grub/grub-0.97/stage2/zfs-include/spa.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/grub/grub-0.97/stage2/zfs-include/spa.h	Wed Nov 12 04:51:53 2014 -0800
@@ -56,17 +56,14 @@
 	BF64_SET(x, low, len, ((val) >> (shift)) - (bias))
 
 /*
- * We currently support nine block sizes, from 512 bytes to 128K.
- * We could go higher, but the benefits are near-zero and the cost
- * of COWing a giant block to modify one byte would become excessive.
+ * Note: GRUB can't actually read blocks larger than 128KB, due to lack
+ * of memory.  Therefore its SPA_MAXBLOCKSIZE is still 128KB.
  */
 #define	SPA_MINBLOCKSHIFT	9
 #define	SPA_MAXBLOCKSHIFT	17
 #define	SPA_MINBLOCKSIZE	(1ULL << SPA_MINBLOCKSHIFT)
 #define	SPA_MAXBLOCKSIZE	(1ULL << SPA_MAXBLOCKSHIFT)
 
-#define	SPA_BLOCKSIZES		(SPA_MAXBLOCKSHIFT - SPA_MINBLOCKSHIFT + 1)
-
 /*
  * Size of block to hold the configuration data (a packed nvlist)
  */
--- a/usr/src/lib/libnvpair/Makefile.com	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libnvpair/Makefile.com	Wed Nov 12 04:51:53 2014 -0800
@@ -23,7 +23,7 @@
 # Use is subject to license terms.
 #
 # Copyright (c) 2012 by Delphix. All rights reserved.
-# Copyright (c) 2013, Joyent, Inc. All rights reserved.
+# Copyright (c) 2014, Joyent, Inc.
 #
 
 LIBRARY=	libnvpair.a
@@ -60,10 +60,12 @@
 LINTFLAGS +=	-erroff=E_INVALID_TOKEN_IN_DEFINE_MACRO
 LINTFLAGS +=	-erroff=E_RET_INT_IMPLICITLY
 LINTFLAGS +=	-erroff=E_FUNC_USED_VAR_ARG2
+LINTFLAGS +=	-erroff=E_CONSTANT_CONDITION
 LINTFLAGS64 +=	-erroff=E_BAD_FORMAT_STR2
 LINTFLAGS64 +=	-erroff=E_INVALID_TOKEN_IN_DEFINE_MACRO
 LINTFLAGS64 +=	-erroff=E_RET_INT_IMPLICITLY
 LINTFLAGS64 +=	-erroff=E_FUNC_USED_VAR_ARG2
+LINTFLAGS64 +=	-erroff=E_CONSTANT_CONDITION
 
 CERRWARN +=	-_gcc=-Wno-type-limits
 CERRWARN +=	-_gcc=-Wno-parentheses
--- a/usr/src/lib/libnvpair/nvpair_json.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libnvpair/nvpair_json.c	Wed Nov 12 04:51:53 2014 -0800
@@ -9,7 +9,7 @@
  * http://www.illumos.org/license/CDDL.
  */
 /*
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2014, Joyent, Inc.
  */
 
 #include <stdio.h>
@@ -20,9 +20,11 @@
 
 #include "libnvpair.h"
 
-#define	FPRINTF(fp, ...)			\
-	if (fprintf(fp, __VA_ARGS__) < 0)	\
-		return (-1)			\
+#define	FPRINTF(fp, ...)				\
+	do {						\
+		if (fprintf(fp, __VA_ARGS__) < 0)	\
+			return (-1);			\
+	} while (0)
 
 /*
  * When formatting a string for JSON output we must escape certain characters,
@@ -328,7 +330,7 @@
 			for (i = 0; i < valsz; i++) {
 				if (i > 0)
 					FPRINTF(fp, ",");
-				FPRINTF(fp, "%hhd", val[i]);
+				FPRINTF(fp, "%hd", val[i]);
 			}
 			FPRINTF(fp, "]");
 			break;
--- a/usr/src/lib/libshare/smb/libshare_smb.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libshare/smb/libshare_smb.c	Wed Nov 12 04:51:53 2014 -0800
@@ -451,12 +451,6 @@
 		if (err != SA_OK) {
 			(void) printf(dgettext(TEXT_DOMAIN,
 			    "SMB: Unable to enable service\n"));
-			/*
-			 * For now, it is OK to not be able to enable
-			 * the service.
-			 */
-			if (err == SA_BUSY || err == SA_SYSTEM_ERR)
-				err = SA_OK;
 		} else {
 			online = B_TRUE;
 		}
@@ -1484,10 +1478,6 @@
 				/* maintenance requires help */
 				ret = SA_SYSTEM_ERR;
 				break;
-			} else if (smb_isdisabled()) {
-				/* disabled is ok */
-				ret = SA_OK;
-				break;
 			} else {
 				/* try another time */
 				ret = SA_BUSY;
--- a/usr/src/lib/libsmbfs/netsmb/smb_lib.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/netsmb/smb_lib.h	Wed Nov 12 04:51:53 2014 -0800
@@ -33,8 +33,8 @@
  */
 
 /*
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _NETSMB_SMB_LIB_H_
@@ -115,10 +115,11 @@
 	/* Strings from the SMB negotiate response. */
 	char		*ct_srv_OS;
 	char		*ct_srv_LM;
+	uint32_t	ct_clnt_caps;
 
 	/* NTLM auth. stuff */
 	uchar_t		ct_clnonce[NTLM_CHAL_SZ];
-	uchar_t		ct_ntlm_chal[NTLM_CHAL_SZ];
+	uchar_t		ct_srv_chal[NTLM_CHAL_SZ];
 	char		ct_password[SMBIOC_MAX_NAME];
 
 	/* See ssp.c */
--- a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h	Wed Nov 12 04:51:53 2014 -0800
@@ -20,9 +20,9 @@
  */
 
 /*
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _NETSMB_SMBFS_API_H
@@ -90,7 +90,6 @@
 #define	SMB_AT_NTLM1	4	/* NTLM (v1) */
 #define	SMB_AT_NTLM2	8	/* NTLMv2 */
 #define	SMB_AT_KRB5	0x10	/* Kerberos5 (AD) */
-#define	SMB_AT_DEFAULT	(SMB_AT_KRB5 | SMB_AT_NTLM2)
 
 struct smb_ctx;	/* anonymous here; real one in smb_lib.h */
 typedef struct smb_ctx smb_ctx_t;
--- a/usr/src/lib/libsmbfs/smb/connect.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/connect.c	Wed Nov 12 04:51:53 2014 -0800
@@ -22,6 +22,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -460,76 +461,68 @@
 	}
 
 	/*
-	 * SMB Negotiate Protocol and
-	 * SMB Session Setup, one of 3 ways:
-	 *	NULL session
-	 *	Extended security,
-	 *	NTLM (v2, v1)
-	 *
+	 * Do SMB Negotiate Protocol.
+	 */
+	err = smb_negprot(ctx, &blob);
+	if (err)
+		goto out;
+
+	/*
 	 * Empty user name means an explicit request for
-	 * NULL session setup.  No fall-back logic here.
-	 *
-	 * For NULL session, don't offer extended security.
-	 * That's a lot simpler than dealing with NTLMSSP.
+	 * NULL session setup, which is a special case.
+	 * If negotiate determined that we want to do
+	 * SMB signing, we have to turn that off for a
+	 * NULL session. [MS-SMB 3.3.5.3].
 	 */
 	if (ctx->ct_user[0] == '\0') {
-		ctx->ct_vopt &= ~SMBVOPT_EXT_SEC;
-		err = smb_negprot(ctx, &blob);
-		if (err)
-			goto out;
-		err = smb_ssnsetup_null(ctx);
+		/* Null user should have null domain too. */
+		ctx->ct_domain[0] = '\0';
+		ctx->ct_authflags = SMB_AT_ANON;
+		ctx->ct_clnt_caps &= ~SMB_CAP_EXT_SECURITY;
+		ctx->ct_vcflags &= ~SMBV_WILL_SIGN;
+	}
+
+	/*
+	 * Do SMB Session Setup (authenticate)
+	 *
+	 * If the server negotiated extended security,
+	 * run the SPNEGO state machine, otherwise do
+	 * one of the old-style variants.
+	 */
+	if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) {
+		err = smb_ssnsetup_spnego(ctx, &blob);
 	} else {
 		/*
-		 * Do SMB Negotiate Protocol.
+		 * Server did NOT negotiate extended security.
+		 * Try NTLMv2, NTLMv1, or ANON (if enabled).
 		 */
-		err = smb_negprot(ctx, &blob);
-		if (err)
-			goto out;
-
-		/*
-		 * Do SMB Session Setup (authenticate)
-		 *
-		 * If the server negotiated extended security,
-		 * run the SPNEGO state machine.
-		 */
-		if (ctx->ct_sopt.sv_caps & SMB_CAP_EXT_SECURITY) {
-			err = smb_ssnsetup_spnego(ctx, &blob);
+		if (ctx->ct_authflags & SMB_AT_NTLM2) {
+			err = smb_ssnsetup_ntlm2(ctx);
+		} else if (ctx->ct_authflags & SMB_AT_NTLM1) {
+			err = smb_ssnsetup_ntlm1(ctx);
+		} else if (ctx->ct_authflags & SMB_AT_ANON) {
+			err = smb_ssnsetup_null(ctx);
 		} else {
 			/*
-			 * Server did NOT negotiate extended security.
-			 * Try NTLMv2, NTLMv1 (if enabled).
+			 * Don't return EAUTH, because a new
+			 * password prompt will not help.
 			 */
-			if ((ctx->ct_authflags &
-			    (SMB_AT_NTLM2 | SMB_AT_NTLM1)) == 0) {
-				/*
-				 * Don't return EAUTH, because a
-				 * new password will not help.
-				 */
-				DPRINT("No NTLM authflags");
-				err = ENOTSUP;
-				goto out;
-			}
-			if (ctx->ct_authflags & SMB_AT_NTLM2)
-				err = smb_ssnsetup_ntlm2(ctx);
-			else
-				err = EAUTH;
-			if (err == EAUTH && 0 !=
-			    (ctx->ct_authflags & SMB_AT_NTLM1))
-				err = smb_ssnsetup_ntlm1(ctx);
+			DPRINT("No NTLM authflags");
+			err = ENOTSUP;
 		}
 	}
 
-	/* Tell library code we have a session. */
-	ctx->ct_flags |= SMBCF_RESOLVED | SMBCF_SSNACTIVE;
-
 out:
 	mb_done(&blob);
 
 	if (err) {
 		close(ctx->ct_tran_fd);
 		ctx->ct_tran_fd = -1;
-	} else
+	} else {
+		/* Tell library code we have a session. */
+		ctx->ct_flags |= SMBCF_SSNACTIVE;
 		DPRINT("tran_fd = %d", ctx->ct_tran_fd);
+	}
 
 	return (err);
 }
--- a/usr/src/lib/libsmbfs/smb/crypt.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/crypt.c	Wed Nov 12 04:51:53 2014 -0800
@@ -22,6 +22,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -29,7 +30,7 @@
  *
  * Some code copied from the server: libsmb smb_crypt.c
  * with minor changes, i.e. errno.h return values.
- * XXX: Move this to a common library (later).
+ * XXX: Later, make the server use these.
  */
 
 #include <sys/types.h>
@@ -67,13 +68,21 @@
 	int K, D;
 	int k, d;
 
-	/* Calculate proper number of iterations */
+	/*
+	 * Calculate proper number of iterations.
+	 * Known call cases include:
+	 *   ResultLen=16, KeyLen=14, DataLen=8
+	 *   ResultLen=24, KeyLen=21, DataLen=8
+	 *   ResultLen=16, KeyLen=14, DataLen=16
+	 */
 	K = KeyLen / 7;
 	D = DataLen / 8;
-
-	if (ResultLen < (K * 8 * D)) {
+	if ((KeyLen % 7) || (DataLen % 8))
 		return (EINVAL);
-	}
+	if (K == 0 || D == 0)
+		return (EINVAL);
+	if (ResultLen < (K * 8))
+		return (EINVAL);
 
 	/*
 	 * Use SUNW convenience function to initialize the cryptoki
@@ -88,7 +97,10 @@
 		return (ENOTSUP);
 	}
 
-	for (k = 0; k < K; k++) {
+	for (d = k = 0; k < K; k++, d++) {
+		/* Cycle the input again, as necessary. */
+		if (d == D)
+			d = 0;
 		smb_initlmkey(des_key, &Key[k * 7]);
 		rv = SUNW_C_KeyToObject(hSession, mechanism.mechanism,
 		    des_key, 8, &hKey);
@@ -102,18 +114,18 @@
 			error = EIO;
 			goto exit_encrypt;
 		}
-		ciphertext_len = DataLen;
-		for (d = 0; d < D; d++) {
-			/* Read in the data and encrypt this portion */
-			rv = C_EncryptUpdate(hSession,
-			    (CK_BYTE_PTR)Data + (d * 8), 8,
-			    &Result[(k * (8 * D)) + (d * 8)],
-			    &ciphertext_len);
-			if (rv != CKR_OK) {
-				error = EIO;
-				goto exit_encrypt;
-			}
+		ciphertext_len = 8;
+
+		/* Read in the data and encrypt this portion */
+		rv = C_EncryptUpdate(hSession,
+		    (CK_BYTE_PTR)Data + (d * 8), 8,
+		    (CK_BYTE_PTR)Result + (k * 8),
+		    &ciphertext_len);
+		if (rv != CKR_OK) {
+			error = EIO;
+			goto exit_encrypt;
 		}
+
 		(void) C_DestroyObject(hSession, hKey);
 	}
 	goto exit_session;
@@ -149,6 +161,59 @@
 }
 
 /*
+ * CKM_RC4
+ */
+int
+smb_encrypt_RC4(uchar_t *Result, int ResultLen,
+	const uchar_t *Key, int KeyLen,
+	const uchar_t *Data, int DataLen)
+{
+	CK_RV rv;
+	CK_MECHANISM mechanism;
+	CK_OBJECT_HANDLE hKey;
+	CK_SESSION_HANDLE hSession;
+	CK_ULONG ciphertext_len;
+	int error = EIO;
+
+	/*
+	 * Use SUNW convenience function to initialize the cryptoki
+	 * library, and open a session with a slot that supports
+	 * the mechanism we plan on using.
+	 */
+	mechanism.mechanism = CKM_RC4;
+	mechanism.pParameter = NULL;
+	mechanism.ulParameterLen = 0;
+	rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession);
+	if (rv != CKR_OK) {
+		return (ENOTSUP);
+	}
+
+	rv = SUNW_C_KeyToObject(hSession, mechanism.mechanism,
+	    Key, KeyLen, &hKey);
+	if (rv != CKR_OK)
+		goto exit_session;
+
+	/* Initialize the encryption operation in the session */
+	rv = C_EncryptInit(hSession, &mechanism, hKey);
+	if (rv != CKR_OK)
+		goto exit_encrypt;
+
+	ciphertext_len = ResultLen;
+	rv = C_EncryptUpdate(hSession,
+	    (CK_BYTE_PTR)Data, DataLen,
+	    (CK_BYTE_PTR)Result, &ciphertext_len);
+	if (rv == CKR_OK)
+		error = 0;
+
+exit_encrypt:
+	(void) C_DestroyObject(hSession, hKey);
+exit_session:
+	(void) C_CloseSession(hSession);
+
+	return (error);
+}
+
+/*
  * Get some random bytes from /dev/urandom
  *
  * There may be a preferred way to call this via libpkcs11
--- a/usr/src/lib/libsmbfs/smb/ctx.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/ctx.c	Wed Nov 12 04:51:53 2014 -0800
@@ -33,8 +33,8 @@
  */
 
 /*
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/param.h>
@@ -75,6 +75,9 @@
 #define	TRUE	1
 #endif
 
+#define	SMB_AT_DEFAULT	(SMB_AT_KRB5 | SMB_AT_NTLM2)
+#define	SMB_AT_MINAUTH	(SMB_AT_KRB5 | SMB_AT_NTLM2 | SMB_AT_NTLM1)
+
 struct nv {
 	char *name;
 	int value;
@@ -260,7 +263,7 @@
 	ctx->ct_vopt = SMBVOPT_EXT_SEC;
 	ctx->ct_owner = SMBM_ANY_OWNER;
 	ctx->ct_authflags = SMB_AT_DEFAULT;
-	ctx->ct_minauth = SMB_AT_DEFAULT;
+	ctx->ct_minauth = SMB_AT_MINAUTH;
 
 	/*
 	 * Default domain, user, ...
@@ -1118,13 +1121,7 @@
 	 * check for a keychain entry.
 	 * XXX: Only for auth NTLM?
 	 */
-	if (ctx->ct_user[0] == '\0') {
-		/*
-		 * No user name (anonymous session).
-		 * The minauth checks do not apply.
-		 */
-		ctx->ct_authflags = SMB_AT_ANON;
-	} else {
+	if (ctx->ct_user[0] != '\0') {
 		/*
 		 * Have a user name.
 		 * If we don't have a p/w yet,
--- a/usr/src/lib/libsmbfs/smb/negprot.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/negprot.c	Wed Nov 12 04:51:53 2014 -0800
@@ -32,11 +32,11 @@
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
  * SMB Negotiate Protocol, and related.
- * Copied from the driver: smb_smb.c
  */
 
 #include <errno.h>
@@ -66,6 +66,7 @@
 #include <netsmb/smb_dev.h>
 
 #include "charsets.h"
+#include "smb_crypt.h"
 #include "private.h"
 
 /*
@@ -87,6 +88,13 @@
 #define	SMB_DIALECT_MAX \
 	(sizeof (smb_dialects) / sizeof (struct smb_dialect) - 2)
 
+static const uint32_t smb_clnt_caps_mask =
+    SMB_CAP_UNICODE |
+    SMB_CAP_LARGE_FILES |
+    SMB_CAP_NT_SMBS |
+    SMB_CAP_STATUS32 |
+    SMB_CAP_EXT_SECURITY;
+
 /*
  * SMB Negotiate Protocol
  * Based on code from the driver: smb_smb.c
@@ -118,9 +126,16 @@
 	 * if we find out it doesn't.  Need to do this because
 	 * some servers reject all non-Unicode requests.
 	 */
-	ctx->ct_hflags = SMB_FLAGS_CASELESS;
-	ctx->ct_hflags2 = SMB_FLAGS2_KNOWS_LONG_NAMES |
-	    SMB_FLAGS2_ERR_STATUS | SMB_FLAGS2_UNICODE;
+	ctx->ct_hflags =
+	    SMB_FLAGS_CASELESS |
+	    SMB_FLAGS_CANONICAL_PATHNAMES;
+	ctx->ct_hflags2 =
+	    SMB_FLAGS2_KNOWS_LONG_NAMES |
+	    SMB_FLAGS2_KNOWS_EAS |
+	    /* SMB_FLAGS2_IS_LONG_NAME |? */
+	    /* EXT_SEC (see below) */
+	    SMB_FLAGS2_ERR_STATUS |
+	    SMB_FLAGS2_UNICODE;
 
 	/*
 	 * Sould we offer extended security?
@@ -362,7 +377,7 @@
 			err = EBADRPC;
 			goto errout;
 		}
-		err = md_get_mem(mbp, ctx->ct_ntlm_chal,
+		err = md_get_mem(mbp, ctx->ct_srv_chal,
 		    NTLM_CHAL_SZ, MB_MSYSTEM);
 		/*
 		 * Server domain follows (ignored)
@@ -423,6 +438,15 @@
 	is->is_rxmax = len;
 	is->is_wxmax = len;
 
+	/*
+	 * Most of the "capability" bits we offer in session setup
+	 * are just copied from those offered by the server.
+	 */
+	ctx->ct_clnt_caps = sv->sv_caps & smb_clnt_caps_mask;
+
+	/* Get the client nonce. */
+	(void) smb_get_urandom(ctx->ct_clnonce, NTLM_CHAL_SZ);
+
 	return (0);
 
 errout:
--- a/usr/src/lib/libsmbfs/smb/ntlm.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/ntlm.c	Wed Nov 12 04:51:53 2014 -0800
@@ -34,6 +34,7 @@
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -62,10 +63,11 @@
 /*
  * ntlm_compute_lm_hash
  *
- * Compute an LM hash given a password
+ * Given a password, compute the LM hash.
+ * a.k.a. ResponseKeyLM in [MS-NLMP]
  *
  * Output:
- *	hash: 16-byte "LanMan" (LM) hash.
+ *	hash: 16-byte "LanMan" (LM) hash (normally ctx->ct_lmhash)
  * Inputs:
  *	ucpw: User's password, upper-case UTF-8 string.
  *
@@ -102,10 +104,11 @@
 /*
  * ntlm_compute_nt_hash
  *
- * Compute an NT hash given a password in UTF-8.
+ * Given a password, compute the NT hash.
+ * a.k.a. the ResponseKeyNT in [MS-NLMP]
  *
  * Output:
- *	hash: 16-byte "NT" hash.
+ *	hash: 16-byte "NT" hash (normally ctx->ct_nthash)
  * Inputs:
  *	upw: User's password, mixed-case UCS-2LE.
  *	pwlen: Size (in bytes) of upw
@@ -134,6 +137,7 @@
 
 /*
  * ntlm_v1_response
+ * a.k.a. DESL() in [MS-NLMP]
  *
  * Create an LM response from the given LM hash and challenge,
  * or an NTLM repsonse from a given NTLM hash and challenge.
@@ -194,32 +198,103 @@
 		return (err);
 
 	/*
-	 * Compute the LM response, derived
-	 * from the challenge and the ASCII
-	 * password (if authflags allow).
-	 */
-	err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
-	if (err)
-		return (err);
-	bzero(lmresp, NTLM_V1_RESP_SZ);
-	if (ctx->ct_authflags & SMB_AT_LM1) {
-		/* They asked to send the LM hash too. */
-		err = ntlm_v1_response(lmresp, ctx->ct_lmhash,
-		    ctx->ct_ntlm_chal, NTLM_CHAL_SZ);
-		if (err)
-			return (err);
-	}
-
-	/*
 	 * Compute the NTLM response, derived from
-	 * the challenge and the NT hash.
+	 * the challenge and the NT hash (a.k.a ResponseKeyNT)
 	 */
 	err = mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp);
 	if (err)
 		return (err);
 	bzero(ntresp, NTLM_V1_RESP_SZ);
 	err = ntlm_v1_response(ntresp, ctx->ct_nthash,
-	    ctx->ct_ntlm_chal, NTLM_CHAL_SZ);
+	    ctx->ct_srv_chal, NTLM_CHAL_SZ);
+
+	/*
+	 * Compute the LM response, derived from
+	 * the challenge and the ASCII password.
+	 * Per. [MS-NLMP 3.3.1] if NoLmResponse,
+	 * send the NT response for both NT+LM.
+	 */
+	err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
+	if (err)
+		return (err);
+	memcpy(lmresp, ntresp, NTLM_V1_RESP_SZ);
+	if (ctx->ct_authflags & SMB_AT_LM1) {
+		/* They asked to send the LM hash too. */
+		err = ntlm_v1_response(lmresp, ctx->ct_lmhash,
+		    ctx->ct_srv_chal, NTLM_CHAL_SZ);
+		if (err)
+			return (err);
+	}
+
+	/*
+	 * Compute the session key
+	 */
+	ntlm_v1_session_key(ctx->ct_ssn_key, ctx->ct_nthash);
+
+	return (err);
+}
+
+/*
+ * Compute both the LM(v1x) response and the NTLM(v1x) response,
+ * and put them in the mbdata chains passed.  "v1x" here refers to
+ * NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY used with NTLMSSP,
+ * also known by its shorter alias NTLMSSP_NEGOTIATE_NTLM2.
+ * [MS-NLMP 3.3.1]
+ *
+ * This allocates mbuf chains in the output args (caller frees).
+ */
+int
+ntlm_put_v1x_responses(struct smb_ctx *ctx,
+	struct mbdata *lm_mbp, struct mbdata *nt_mbp)
+{
+	MD5_CTX context;
+	uchar_t challenges[2 * NTLM_CHAL_SZ];
+	uchar_t digest[NTLM_HASH_SZ];
+	uchar_t *lmresp, *ntresp;
+	int err;
+
+	/* Get mbuf chain for the LM response. */
+	if ((err = mb_init_sz(lm_mbp, NTLM_V1_RESP_SZ)) != 0)
+		return (err);
+
+	/* Get mbuf chain for the NT response. */
+	if ((err = mb_init_sz(nt_mbp, NTLM_V1_RESP_SZ)) != 0)
+		return (err);
+
+	/*
+	 * challenges = ConcatenationOf(ServerChallenge, ClientChallenge)
+	 */
+	memcpy(challenges, ctx->ct_srv_chal, NTLM_CHAL_SZ);
+	memcpy(challenges + NTLM_CHAL_SZ, ctx->ct_clnonce, NTLM_CHAL_SZ);
+
+	/*
+	 * digest = MD5(challenges)
+	 */
+	MD5Init(&context);
+	MD5Update(&context, challenges, sizeof (challenges));
+	MD5Final(digest, &context);
+
+	/*
+	 * Compute the NTLM response, derived from the
+	 * NT hash (a.k.a ResponseKeyNT) and the first
+	 * 8 bytes of the MD5 digest of the challenges.
+	 */
+	err = mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp);
+	if (err)
+		return (err);
+	bzero(ntresp, NTLM_V1_RESP_SZ);
+	err = ntlm_v1_response(ntresp, ctx->ct_nthash,
+	    digest, NTLM_CHAL_SZ);
+
+	/*
+	 * With "Extended Session Security", the LM response
+	 * is simply the client challenge (nonce) padded out.
+	 */
+	err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
+	if (err)
+		return (err);
+	bzero(lmresp, NTLM_V1_RESP_SZ);
+	memcpy(lmresp, ctx->ct_clnonce, NTLM_CHAL_SZ);
 
 	/*
 	 * Compute the session key
@@ -410,22 +485,22 @@
 	uchar_t v2hash[NTLM_HASH_SZ];
 	struct mbuf *tim = ti_mbp->mb_top;
 
-	if ((err = mb_init(lm_mbp)) != 0)
-		return (err);
-	if ((err = mb_init(nt_mbp)) != 0)
-		return (err);
-
 	/*
 	 * Convert the user name to upper-case, as
 	 * that's what's used when computing LMv2
 	 * and NTLMv2 responses.  Note that the
 	 * domain name is NOT upper-cased!
 	 */
+	if (ctx->ct_user[0] == '\0')
+		return (EINVAL);
 	ucuser = utf8_str_toupper(ctx->ct_user);
-	if (ucuser == NULL) {
-		err = ENOMEM;
+	if (ucuser == NULL)
+		return (ENOMEM);
+
+	if ((err = mb_init(lm_mbp)) != 0)
 		goto out;
-	}
+	if ((err = mb_init(nt_mbp)) != 0)
+		goto out;
 
 	/*
 	 * Compute the NTLMv2 hash
@@ -444,10 +519,9 @@
 	 *	1: 16-byte response hash
 	 *	2: Client nonce
 	 */
-	lmresp = (uchar_t *)lm_mbp->mb_pos;
-	mb_put_mem(lm_mbp, NULL, NTLM_HASH_SZ, MB_MSYSTEM);
+	lmresp = mb_reserve(lm_mbp, NTLM_HASH_SZ);
 	err = ntlm_v2_resp_hash(lmresp,
-	    v2hash, ctx->ct_ntlm_chal,
+	    v2hash, ctx->ct_srv_chal,
 	    ctx->ct_clnonce, NTLM_CHAL_SZ);
 	if (err)
 		goto out;
@@ -462,10 +536,9 @@
 	 *	1: 16-byte response hash
 	 *	2: "target info." blob
 	 */
-	ntresp = (uchar_t *)nt_mbp->mb_pos;
-	mb_put_mem(nt_mbp, NULL, NTLM_HASH_SZ, MB_MSYSTEM);
+	ntresp = mb_reserve(nt_mbp, NTLM_HASH_SZ);
 	err = ntlm_v2_resp_hash(ntresp,
-	    v2hash, ctx->ct_ntlm_chal,
+	    v2hash, ctx->ct_srv_chal,
 	    (uchar_t *)tim->m_data, tim->m_len);
 	if (err)
 		goto out;
@@ -533,14 +606,6 @@
 		return (err);
 
 	/*
-	 * Construct the client nonce by getting
-	 * some random data from /dev/urandom
-	 */
-	err = smb_get_urandom(ctx->ct_clnonce, NTLM_CHAL_SZ);
-	if (err)
-		goto out;
-
-	/*
 	 * Get the "NT time" for the target info header.
 	 */
 	(void) gettimeofday(&now, 0);
@@ -583,3 +648,48 @@
 	free(ucdom);
 	return (err);
 }
+
+/*
+ * Build the MAC key (for SMB signing)
+ */
+int
+ntlm_build_mac_key(struct smb_ctx *ctx, struct mbdata *ntresp_mbp)
+{
+	struct mbuf *m;
+	size_t len;
+	char *p;
+
+	/*
+	 * MAC_key = concat(session_key, nt_response)
+	 */
+	m = ntresp_mbp->mb_top;
+	len = NTLM_HASH_SZ + m->m_len;
+	if ((p = malloc(len)) == NULL)
+		return (ENOMEM);
+	ctx->ct_mackeylen = len;
+	ctx->ct_mackey = p;
+	memcpy(p, ctx->ct_ssn_key, NTLM_HASH_SZ);
+	memcpy(p + NTLM_HASH_SZ, m->m_data, m->m_len);
+
+	return (0);
+}
+
+/*
+ * Helper for ntlmssp_put_type3 - Build the "key exchange key"
+ * used when we have both NTLM(v1) and NTLMSSP_NEGOTIATE_NTLM2.
+ * HMAC_MD5(SessionBaseKey, concat(ServerChallenge, LmResponse[0..7]))
+ */
+void
+ntlm2_kxkey(struct smb_ctx *ctx, struct mbdata *lm_mbp, uchar_t *kxkey)
+{
+	uchar_t data[NTLM_HASH_SZ];
+	uchar_t *p = mtod(lm_mbp->mb_top, uchar_t *);
+
+	/* concat(ServerChallenge, LmResponse[0..7]) */
+	memcpy(data, ctx->ct_srv_chal, NTLM_CHAL_SZ);
+	memcpy(data + NTLM_CHAL_SZ, p, NTLM_CHAL_SZ);
+
+	/* HMAC_MD5(SessionBaseKey, concat(...)) */
+	HMACT64(kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ,
+	    data, NTLM_HASH_SZ);
+}
--- a/usr/src/lib/libsmbfs/smb/ntlm.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/ntlm.h	Wed Nov 12 04:51:53 2014 -0800
@@ -22,6 +22,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _NTLM_H
@@ -59,7 +60,17 @@
 	struct mbdata *lm_mbp, struct mbdata *nt_mbp);
 
 int
+ntlm_put_v1x_responses(struct smb_ctx *ctx,
+	struct mbdata *lm_mbp, struct mbdata *nt_mbp);
+
+int
 ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp,
 	struct mbdata *lm_mbp, struct mbdata *nt_mbp);
 
+int
+ntlm_build_mac_key(struct smb_ctx *ctx, struct mbdata *ntresp_mbp);
+
+void
+ntlm2_kxkey(struct smb_ctx *ctx, struct mbdata *lm_mbp, uchar_t *kxkey);
+
 #endif /* _NTLM_H */
--- a/usr/src/lib/libsmbfs/smb/ntlmssp.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/ntlmssp.c	Wed Nov 12 04:51:53 2014 -0800
@@ -20,8 +20,8 @@
  */
 
 /*
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -59,16 +59,22 @@
 
 #include "private.h"
 #include "charsets.h"
+#include "smb_crypt.h"
 #include "spnego.h"
 #include "derparse.h"
 #include "ssp.h"
 #include "ntlm.h"
 #include "ntlmssp.h"
 
+/* A shorter alias for a crazy long name from [MS-NLMP] */
+#define	NTLMSSP_NEGOTIATE_NTLM2 \
+	NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
+
 typedef struct ntlmssp_state {
 	uint32_t ss_flags;
-	char *ss_target_name;
+	char *ss_target_name;	/* Primary domain or server name */
 	struct mbuf *ss_target_info;
+	uchar_t	ss_kxkey[NTLM_HASH_SZ];
 } ntlmssp_state_t;
 
 /*
@@ -83,6 +89,10 @@
 #define	ID_SZ 8
 static const char ntlmssp_id[ID_SZ] = "NTLMSSP";
 
+static int
+ntlm_rand_ssn_key(struct smb_ctx *ctx,
+	ntlmssp_state_t *ssp_st, struct mbdata *ek_mbp);
+
 /*
  * Get a "security buffer" (header part)
  */
@@ -147,10 +157,12 @@
 static int
 mb_put_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf *m)
 {
-	int cnt0, err;
+	int cnt0;
+	int err = 0;
 
 	sb->sb_offset = cnt0 = mbp->mb_count;
-	err = mb_put_mbuf(mbp, m);
+	if (m != NULL)
+		err = mb_put_mbuf(mbp, m);
 	sb->sb_maxlen = sb->sb_length = mbp->mb_count - cnt0;
 
 	return (err);
@@ -164,31 +176,35 @@
  */
 static int
 mb_put_sb_string(struct mbdata *mbp, struct sec_buf *sb,
-	const char *s, int unicode)
+	const char *str, int unicode)
 {
 	int err, trim;
 	struct mbdata tmp_mb;
 
-	/*
-	 * Put the string into a temp. mbuf,
-	 * then chop off the null terminator
-	 * before appending to caller's mbp.
-	 */
-	err = mb_init(&tmp_mb);
-	if (err)
-		return (err);
-	err = mb_put_string(&tmp_mb, s, unicode);
-	if (err)
-		return (err);
+	bzero(&tmp_mb, sizeof (tmp_mb));
 
-	trim = (unicode) ? 2 : 1;
-	if (tmp_mb.mb_cur->m_len < trim)
-		return (EFAULT);
-	tmp_mb.mb_cur->m_len -= trim;
+	if (str != NULL && *str != '\0') {
+		/*
+		 * Put the string into a temp. mbuf,
+		 * then chop off the null terminator
+		 * before appending to caller's mbp.
+		 */
+		err = mb_init(&tmp_mb);
+		if (err)
+			return (err);
+		err = mb_put_string(&tmp_mb, str, unicode);
+		if (err)
+			return (err);
+
+		trim = (unicode) ? 2 : 1;
+		if (tmp_mb.mb_cur->m_len < trim)
+			trim = 0;
+		tmp_mb.mb_cur->m_len -= trim;
+	}
 
 	err = mb_put_sb_data(mbp, sb, tmp_mb.mb_top);
 	/*
-	 * Note: tmp_mb.mb_top is consumed,
+	 * Note: tmp_mb.mb_top (if any) is consumed,
 	 * so do NOT free it (no mb_done)
 	 */
 	return (err);
@@ -215,60 +231,47 @@
 	int err;
 	struct smb_ctx *ctx = sp->smb_ctx;
 	ntlmssp_state_t *ssp_st = sp->sp_private;
-	char *ucdom = NULL;
-	char *ucwks = NULL;
 
 	if ((err = mb_init(&mb2)) != 0)
 		return (err);
 	mb2.mb_count = sizeof (hdr);
 
 	/*
-	 * Initialize the negotiation flags, and
-	 * save what we sent.  For reference:
-	 * [MS-NLMP] spec. (also ntlmssp.h)
+	 * The initial negotiation flags represent the union of all
+	 * options we support.  The server selects from these.
+	 * See: [MS-NLMP 2.2.2.5 NEGOTIATE]
 	 */
 	ssp_st->ss_flags =
+	    NTLMSSP_NEGOTIATE_UNICODE |
+	    NTLMSSP_NEGOTIATE_OEM |
 	    NTLMSSP_REQUEST_TARGET |
+	    NTLMSSP_NEGOTIATE_SIGN |
+	    NTLMSSP_NEGOTIATE_SEAL |
+	    /* NTLMSSP_NEGOTIATE_LM_KEY (never) */
 	    NTLMSSP_NEGOTIATE_NTLM |
-	    NTLMSSP_NEGOTIATE_TARGET_INFO |
+	    /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN (set below) */
+	    NTLMSSP_NEGOTIATE_NTLM2 |
 	    NTLMSSP_NEGOTIATE_128 |
+	    NTLMSSP_NEGOTIATE_KEY_EXCH |
 	    NTLMSSP_NEGOTIATE_56;
 
-	if (ctx->ct_hflags2 & SMB_FLAGS2_UNICODE)
-		ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_UNICODE;
-	else
-		ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_OEM;
-
 	if (ctx->ct_vcflags & SMBV_WILL_SIGN) {
 		ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
 		ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
 	}
 
-	if (ctx->ct_authflags & SMB_AT_NTLM2)
-		ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY;
-	if (ctx->ct_authflags & SMB_AT_NTLM1)
-		ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
-
 	bcopy(ntlmssp_id, &hdr.h_id, ID_SZ);
-	hdr.h_type = 1; /* Type 1 */
+	hdr.h_type = NTLMSSP_MSGTYPE_NEGOTIATE;
 	hdr.h_flags = ssp_st->ss_flags;
 
 	/*
-	 * Put the client domain, client name strings.
-	 * These are always in OEM format, upper-case.
+	 * We could put the client domain, client name strings
+	 * here, (always in OEM format, upper-case), and set
+	 * NTLMSSP_NEGOTIATE_OEM_..._SUPPLIED, but Windows
+	 * leaves these NULL so let's do the same.
 	 */
-	ucdom  = utf8_str_toupper(ctx->ct_domain);
-	ucwks  = utf8_str_toupper(ctx->ct_locname);
-	if (ucdom == NULL || ucwks == NULL) {
-		err = ENOMEM;
-		goto out;
-	}
-	err = mb_put_sb_string(&mb2, &hdr.h_cldom, ucdom, 0);
-	if (err)
-		goto out;
-	err = mb_put_sb_string(&mb2, &hdr.h_wksta, ucwks, 0);
-	if (err)
-		goto out;
+	(void) mb_put_sb_string(&mb2, &hdr.h_cldom, NULL, 0);
+	(void) mb_put_sb_string(&mb2, &hdr.h_wksta, NULL, 0);
 
 	/*
 	 * Marshal the header (in LE order)
@@ -282,10 +285,6 @@
 
 	err = mb_put_mbuf(out_mb, mb2.mb_top);
 
-out:
-	free(ucdom);
-	free(ucwks);
-
 	return (err);
 }
 
@@ -329,7 +328,7 @@
 	bzero(&hdr, sizeof (hdr));
 	(void) md_get_mem(in_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM);
 	(void) md_get_uint32le(in_mb, &hdr.h_type);
-	if (hdr.h_type != 2) {
+	if (hdr.h_type != NTLMSSP_MSGTYPE_CHALLENGE) {
 		err = EPROTO;
 		goto out;
 	}
@@ -338,11 +337,17 @@
 	(void) md_get_mem(in_mb, &hdr.h_challenge, NTLM_CHAL_SZ, MB_MSYSTEM);
 
 	/*
-	 * Save flags, challenge for later.
+	 * Save flags, server challenge for later.
 	 */
 	ssp_st->ss_flags = hdr.h_flags;
+	bcopy(&hdr.h_challenge, ctx->ct_srv_chal, NTLM_CHAL_SZ);
+
+	/*
+	 * Turn off flags that might have been given but
+	 * that we don't want to send with authenticate.
+	 */
 	uc = hdr.h_flags & NTLMSSP_NEGOTIATE_UNICODE;
-	bcopy(&hdr.h_challenge, ctx->ct_ntlm_chal, NTLM_CHAL_SZ);
+	ssp_st->ss_flags &= ~NTLMSSP_NEGOTIATE_VERSION;
 
 	/*
 	 * Now find out if the optional parts are there.
@@ -355,8 +360,9 @@
 	}
 
 	/*
-	 * Get the target name string.  First get a copy of
-	 * the data from the offset/length indicated in the
+	 * Get the target name string.  (Server name or
+	 * Primary domain name.)  First get a copy of the
+	 * data from the offset/length indicated in the
 	 * security buffer header; then parse the string.
 	 */
 	err = md_get_sb_data(&top_mb, &hdr.h_target_name, &m);
@@ -401,19 +407,24 @@
 		struct sec_buf h_wksta;
 		struct sec_buf h_ssn_key;
 		uint32_t h_flags;
+		/* Version struct (ommitted) */
+		uchar_t h_mic[NTLM_HASH_SZ];
 	} hdr;
 	struct mbdata lm_mbc;	/* LM response */
 	struct mbdata nt_mbc;	/* NT response */
 	struct mbdata ti_mbc;	/* target info */
+	struct mbdata ek_mbc;	/* encrypted session key */
 	struct mbdata mb2;	/* payload */
 	int err, uc;
 	struct smb_ctx *ctx = sp->smb_ctx;
 	ntlmssp_state_t *ssp_st = sp->sp_private;
+	uchar_t *pmic;
 
 	bzero(&hdr, sizeof (hdr));
 	bzero(&lm_mbc, sizeof (lm_mbc));
 	bzero(&nt_mbc, sizeof (nt_mbc));
 	bzero(&ti_mbc, sizeof (ti_mbc));
+	bzero(&ek_mbc, sizeof (ek_mbc));
 	bzero(&mb2, sizeof (mb2));
 
 	/*
@@ -425,27 +436,78 @@
 	uc = ssp_st->ss_flags & NTLMSSP_NEGOTIATE_UNICODE;
 
 	bcopy(ntlmssp_id, &hdr.h_id, ID_SZ);
-	hdr.h_type = 3; /* Type 3 */
+	hdr.h_type = NTLMSSP_MSGTYPE_AUTHENTICATE;
 	hdr.h_flags = ssp_st->ss_flags;
 
 	/*
-	 * Put the LMv2,NTLMv2 responses, or
-	 * possibly LM, NTLM (v1) responses.
+	 * Put the NTLMv2/LMv2 or NTLM/LM (v1) responses,
+	 * and compute the session key, etc.
 	 */
-	if (ctx->ct_authflags & SMB_AT_NTLM2) {
-		/* Build the NTLMv2 "target info" blob. */
+	if (ctx->ct_authflags & SMB_AT_ANON) {
+		/*
+		 * We're setting up a NULL session, meaning
+		 * the lm_mbc, nt_mbc parts remain empty.
+		 * Let's add the "anon" flag (hint).
+		 * As there is no session key, disable the
+		 * fancy session key stuff.
+		 */
+		hdr.h_flags |= NTLMSSP_NEGOTIATE_NULL_SESSION;
+		ssp_st->ss_flags &= ~(
+		    NTLMSSP_NEGOTIATE_NTLM2 |
+		    NTLMSSP_NEGOTIATE_KEY_EXCH);
+		err = 0;
+	} else if (ctx->ct_authflags & SMB_AT_NTLM2) {
+		/*
+		 * Doing NTLMv2/LMv2
+		 */
 		err = ntlm_build_target_info(ctx,
 		    ssp_st->ss_target_info, &ti_mbc);
 		if (err)
 			goto out;
 		err = ntlm_put_v2_responses(ctx, &ti_mbc,
 		    &lm_mbc, &nt_mbc);
+		if (err)
+			goto out;
+		/* The "key exg. key" is the session base key */
+		memcpy(ssp_st->ss_kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ);
+
+	} else if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+		/*
+		 * Doing NTLM ("v1x") which is NTLM with
+		 * "Extended Session Security"
+		 */
+		err = ntlm_put_v1x_responses(ctx,
+		    &lm_mbc, &nt_mbc);
+		if (err)
+			goto out;
+		/* Compute the "Key exchange key". */
+		ntlm2_kxkey(ctx, &lm_mbc, ssp_st->ss_kxkey);
 	} else {
+		/*
+		 * Doing plain old NTLM (and LM if enabled)
+		 */
 		err = ntlm_put_v1_responses(ctx,
 		    &lm_mbc, &nt_mbc);
+		if (err)
+			goto out;
+		/* The "key exg. key" is the session base key */
+		memcpy(ssp_st->ss_kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ);
 	}
-	if (err)
-		goto out;
+
+	/*
+	 * Compute the "Exported Session Key" and (possibly)
+	 * the "Encrypted Random Sesion Key".
+	 * [MS-NLMP 3.1.5.1.2]
+	 */
+	if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+		err = ntlm_rand_ssn_key(ctx, ssp_st, &ek_mbc);
+		if (err)
+			goto out;
+	} else {
+		/* ExportedSessionKey is the KeyExchangeKey */
+		memcpy(ctx->ct_ssn_key, ssp_st->ss_kxkey, NTLM_HASH_SZ);
+		/* EncryptedRandomSessionKey remains NULL */
+	}
 
 	err = mb_put_sb_data(&mb2, &hdr.h_lm_resp, lm_mbc.mb_top);
 	lm_mbc.mb_top = NULL; /* consumed */
@@ -470,12 +532,13 @@
 		goto out;
 
 	/*
-	 * Put the "Random Session Key".  We don't set
-	 * NTLMSSP_NEGOTIATE_KEY_EXCH, so it's empty.
-	 * (In-line mb_put_sb_data here.)
+	 * Put the "Encrypted Random Session Key", if any.
+	 * (ek_mbc.mb_top may be NULL)
 	 */
-	hdr.h_ssn_key.sb_maxlen = hdr.h_ssn_key.sb_length = 0;
-	hdr.h_ssn_key.sb_offset = mb2.mb_count;
+	err = mb_put_sb_data(&mb2, &hdr.h_ssn_key, ek_mbc.mb_top);
+	ek_mbc.mb_top = NULL; /* consumed (if any) */
+	if (err)
+		goto out;
 
 	/*
 	 * Marshal the header (in LE order)
@@ -494,14 +557,58 @@
 	(void) mb_put_sb_hdr(out_mb, &hdr.h_ssn_key);
 	(void) mb_put_uint32le(out_mb, hdr.h_flags);
 
+	/* Put zeros for the MIC - filled in later */
+	pmic = mb_reserve(out_mb, NTLM_HASH_SZ);
+
+	/* Put the payload. */
 	err = mb_put_mbuf(out_mb, mb2.mb_top);
 	mb2.mb_top = NULL; /* consumed */
 
+	/*
+	 * Compute the MIC and stuff that in...
+	 * The MIC is apparently optional.
+	 */
+	(void) pmic;
+
 out:
 	mb_done(&mb2);
 	mb_done(&lm_mbc);
 	mb_done(&nt_mbc);
 	mb_done(&ti_mbc);
+	mb_done(&ek_mbc);
+
+	return (err);
+}
+
+/*
+ * Helper for ntlmssp_put_type3 when doing key exchange.
+ *
+ * "ExportedSessionKey" is what we give to the "application"
+ * layer, which in here means the MAC key for SMB signing.
+ * With "key exchange", we replace the ExportedSessionKey
+ * with random data and send that (encrypted) to the peer.
+ */
+static int
+ntlm_rand_ssn_key(
+	struct smb_ctx *ctx,
+	ntlmssp_state_t *ssp_st,
+	struct mbdata *ek_mbp)
+{
+
+	uchar_t *encr_ssn_key;
+	int err;
+
+	if ((err = mb_init(ek_mbp)) != 0)
+		return (err);
+	encr_ssn_key = mb_reserve(ek_mbp, NTLM_HASH_SZ);
+
+	/* Set "ExportedSessionKey to NONCE(16) */
+	(void) smb_get_urandom(ctx->ct_ssn_key, NTLM_HASH_SZ);
+
+	/* Set "EncryptedRandomSessionKey" to RC4(...) */
+	err = smb_encrypt_RC4(encr_ssn_key, NTLM_HASH_SZ,
+	    ssp_st->ss_kxkey, NTLM_HASH_SZ,
+	    ctx->ct_ssn_key, NTLM_HASH_SZ);
 
 	return (err);
 }
@@ -623,9 +730,9 @@
 	ntlmssp_state_t *ssp_st;
 
 	if ((sp->smb_ctx->ct_authflags &
-	    (SMB_AT_NTLM2 | SMB_AT_NTLM1)) == 0) {
+	    (SMB_AT_NTLM2 | SMB_AT_NTLM1 | SMB_AT_ANON)) == 0) {
 		DPRINT("No NTLM authflags");
-		return (ENOTSUP);
+		return (EINVAL);
 	}
 
 	ssp_st = calloc(1, sizeof (*ssp_st));
--- a/usr/src/lib/libsmbfs/smb/ntlmssp.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/ntlmssp.h	Wed Nov 12 04:51:53 2014 -0800
@@ -22,6 +22,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _NTLMSSP_H
@@ -37,6 +38,14 @@
  */
 
 /*
+ * NTLMSSP Message Types
+ * [MS-NLMP] sec. 2.2.1
+ */
+#define	NTLMSSP_MSGTYPE_NEGOTIATE	1
+#define	NTLMSSP_MSGTYPE_CHALLENGE	2
+#define	NTLMSSP_MSGTYPE_AUTHENTICATE	3
+
+/*
  * NTLMSSP Negotiate Flags
  * [MS-NLMP] sec. 2.2.2.5
  */
@@ -48,13 +57,13 @@
 #define	NTLMSSP_NEGOTIATE_SEAL				0x00000020
 #define	NTLMSSP_NEGOTIATE_DATAGRAM			0x00000040
 #define	NTLMSSP_NEGOTIATE_LM_KEY			0x00000080
-/*	reserved					0x00000100 */
+/*	reserved (netware)				0x00000100 */
 #define	NTLMSSP_NEGOTIATE_NTLM				0x00000200
 #define	NTLMSSP_NEGOTIATE_NT_ONLY			0x00000400
-/*	old anonymous_session (ignored by servers)	0x00000800 */
+#define	NTLMSSP_NEGOTIATE_NULL_SESSION			0x00000800
 #define	NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED		0x00001000
 #define	NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED	0x00002000
-/*	reserved					0x00004000 */
+/*	reserved (local caller)				0x00004000 */
 #define	NTLMSSP_NEGOTIATE_ALWAYS_SIGN			0x00008000
 #define	NTLMSSP_TARGET_TYPE_DOMAIN			0x00010000
 #define	NTLMSSP_TARGET_TYPE_SERVER			0x00020000
--- a/usr/src/lib/libsmbfs/smb/smb_crypt.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/smb_crypt.h	Wed Nov 12 04:51:53 2014 -0800
@@ -33,17 +33,36 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
+#ifndef _SMB_CRYPT_H
+#define	_SMB_CRYPT_H
+
 /*
  * Various crypto stuff.
  * from the driver: smb_crypt.c
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 int
 smb_encrypt_DES(uchar_t *Result, int ResultLen,
     const uchar_t *Key, int KeyLen,
     const uchar_t *Data, int DataLen);
 
 int
+smb_encrypt_RC4(uchar_t *Result, int ResultLen,
+    const uchar_t *Key, int KeyLen,
+    const uchar_t *Data, int DataLen);
+
+int
 smb_get_urandom(void *data, size_t dlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SMB_CRYPT_H */
--- a/usr/src/lib/libsmbfs/smb/ssnsetup.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libsmbfs/smb/ssnsetup.c	Wed Nov 12 04:51:53 2014 -0800
@@ -32,11 +32,11 @@
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
  * SMB Session Setup, and related.
- * Copied from the driver: smb_smb.c
  */
 
 #include <errno.h>
@@ -88,7 +88,7 @@
 	uint32_t ntstatus;
 	uint16_t action = 0;
 
-	if (ctx->ct_sopt.sv_caps & SMB_CAP_EXT_SECURITY) {
+	if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) {
 		/* Should not get here with... */
 		err = EINVAL;
 		goto out;
@@ -118,7 +118,7 @@
 	uint32_t ntstatus;
 	uint16_t action = 0;
 
-	if (ctx->ct_sopt.sv_caps & SMB_CAP_EXT_SECURITY) {
+	if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) {
 		/* Should not get here with... */
 		err = EINVAL;
 		goto out;
@@ -133,30 +133,11 @@
 	if (err)
 		goto out;
 
-	/*
-	 * If we negotiated signing, compute the MAC key
-	 * and start signing messages, but only on the
-	 * first non-null session login.
-	 */
-	if ((ctx->ct_vcflags & SMBV_WILL_SIGN) &&
+	if ((ctx->ct_vcflags & SMBV_WILL_SIGN) != 0 &&
 	    (ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) == 0) {
-		struct mbuf *m = nt_mbc.mb_top;
-		char *p;
-
-		/*
-		 * MAC_key = concat(session_key, nt_response)
-		 */
-		ctx->ct_mackeylen = NTLM_HASH_SZ + m->m_len;
-		ctx->ct_mackey = malloc(ctx->ct_mackeylen);
-		if (ctx->ct_mackey == NULL) {
-			ctx->ct_mackeylen = 0;
-			err = ENOMEM;
+		err = ntlm_build_mac_key(ctx, &nt_mbc);
+		if (err)
 			goto out;
-		}
-		p = ctx->ct_mackey;
-		memcpy(p, ctx->ct_ssn_key, NTLM_HASH_SZ);
-		memcpy(p + NTLM_HASH_SZ, m->m_data, m->m_len);
-
 		/* OK, start signing! */
 		ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
 	}
@@ -187,7 +168,7 @@
 	uint32_t ntstatus;
 	uint16_t action = 0;
 
-	if (ctx->ct_sopt.sv_caps & SMB_CAP_EXT_SECURITY) {
+	if (ctx->ct_clnt_caps & SMB_CAP_EXT_SECURITY) {
 		/* Should not get here with... */
 		err = EINVAL;
 		goto out;
@@ -208,30 +189,11 @@
 	if (err)
 		goto out;
 
-	/*
-	 * If we negotiated signing, compute the MAC key
-	 * and start signing messages, but only on the
-	 * first non-null session login.
-	 */
-	if ((ctx->ct_vcflags & SMBV_WILL_SIGN) &&
+	if ((ctx->ct_vcflags & SMBV_WILL_SIGN) != 0 &&
 	    (ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) == 0) {
-		struct mbuf *m = nt_mbc.mb_top;
-		char *p;
-
-		/*
-		 * MAC_key = concat(session_key, nt_response)
-		 */
-		ctx->ct_mackeylen = NTLM_HASH_SZ + m->m_len;
-		ctx->ct_mackey = malloc(ctx->ct_mackeylen);
-		if (ctx->ct_mackey == NULL) {
-			ctx->ct_mackeylen = 0;
-			err = ENOMEM;
+		err = ntlm_build_mac_key(ctx, &nt_mbc);
+		if (err)
 			goto out;
-		}
-		p = ctx->ct_mackey;
-		memcpy(p, ctx->ct_ssn_key, NTLM_HASH_SZ);
-		memcpy(p + NTLM_HASH_SZ, m->m_data, m->m_len);
-
 		/* OK, start signing! */
 		ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
 	}
@@ -334,20 +296,7 @@
 	uint16_t bc, len1, len2, sblen;
 	uint8_t wc;
 
-	/*
-	 * Some of the "capability" bits we offer will be copied
-	 * from those offered by the server, with a mask applied.
-	 * This is the mask of capabilies copied from the server.
-	 * Some others get special handling below.
-	 */
-	static const uint32_t caps_mask =
-	    SMB_CAP_UNICODE |
-	    SMB_CAP_LARGE_FILES |
-	    SMB_CAP_NT_SMBS |
-	    SMB_CAP_STATUS32 |
-	    SMB_CAP_EXT_SECURITY;
-
-	caps = ctx->ct_sopt.sv_caps & caps_mask;
+	caps = ctx->ct_clnt_caps;
 	uc = ctx->ct_hflags2 & SMB_FLAGS2_UNICODE;
 
 	err = smb_rq_init(ctx, SMB_COM_SESSION_SETUP_ANDX, &rqp);
--- a/usr/src/lib/libzfs/common/libzfs.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libzfs/common/libzfs.h	Wed Nov 12 04:51:53 2014 -0800
@@ -591,6 +591,9 @@
 	/* show progress (ie. -v) */
 	boolean_t progress;
 
+	/* large blocks (>128K) are permitted */
+	boolean_t largeblock;
+
 	/* WRITE_EMBEDDED records of type DATA are permitted */
 	boolean_t embed_data;
 } sendflags_t;
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1048,21 +1048,36 @@
 			break;
 		}
 
+		case ZFS_PROP_VOLBLOCKSIZE:
 		case ZFS_PROP_RECORDSIZE:
-		case ZFS_PROP_VOLBLOCKSIZE:
-			/* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */
+		{
+			int maxbs = SPA_MAXBLOCKSIZE;
+			if (zhp != NULL) {
+				maxbs = zpool_get_prop_int(zhp->zpool_hdl,
+				    ZPOOL_PROP_MAXBLOCKSIZE, NULL);
+			}
+			/*
+			 * Volumes are limited to a volblocksize of 128KB,
+			 * because they typically service workloads with
+			 * small random writes, which incur a large performance
+			 * penalty with large blocks.
+			 */
+			if (prop == ZFS_PROP_VOLBLOCKSIZE)
+				maxbs = SPA_OLD_MAXBLOCKSIZE;
+			/*
+			 * The value must be a power of two between
+			 * SPA_MINBLOCKSIZE and maxbs.
+			 */
 			if (intval < SPA_MINBLOCKSIZE ||
-			    intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) {
+			    intval > maxbs || !ISP2(intval)) {
 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-				    "'%s' must be power of 2 from %u "
-				    "to %uk"), propname,
-				    (uint_t)SPA_MINBLOCKSIZE,
-				    (uint_t)SPA_MAXBLOCKSIZE >> 10);
+				    "'%s' must be power of 2 from 512B "
+				    "to %uKB"), propname, maxbs >> 10);
 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
 				goto error;
 			}
 			break;
-
+		}
 		case ZFS_PROP_MLSLABEL:
 		{
 			/*
@@ -1437,7 +1452,8 @@
 		break;
 
 	case ERANGE:
-		if (prop == ZFS_PROP_COMPRESSION) {
+		if (prop == ZFS_PROP_COMPRESSION ||
+		    prop == ZFS_PROP_RECORDSIZE) {
 			(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 			    "property setting is not allowed on "
 			    "bootable datasets"));
@@ -3136,9 +3152,7 @@
 		case EDOM:
 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 			    "volume block size must be power of 2 from "
-			    "%u to %uk"),
-			    (uint_t)SPA_MINBLOCKSIZE,
-			    (uint_t)SPA_MAXBLOCKSIZE >> 10);
+			    "512B to 128KB"));
 
 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
 
--- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c	Wed Nov 12 04:51:53 2014 -0800
@@ -206,7 +206,7 @@
 cksummer(void *arg)
 {
 	dedup_arg_t *dda = arg;
-	char *buf = malloc(1<<20);
+	char *buf = zfs_alloc(dda->dedup_hdl, SPA_MAXBLOCKSIZE);
 	dmu_replay_record_t thedrr;
 	dmu_replay_record_t *drr = &thedrr;
 	struct drr_begin *drrb = &thedrr.drr_u.drr_begin;
@@ -271,9 +271,9 @@
 			    DMU_COMPOUNDSTREAM && drr->drr_payloadlen != 0) {
 				int sz = drr->drr_payloadlen;
 
-				if (sz > 1<<20) {
-					free(buf);
-					buf = malloc(sz);
+				if (sz > SPA_MAXBLOCKSIZE) {
+					buf = zfs_realloc(dda->dedup_hdl, buf,
+					    SPA_MAXBLOCKSIZE, sz);
 				}
 				(void) ssread(buf, sz, ofp);
 				if (ferror(stdin))
@@ -806,7 +806,7 @@
 	char prevsnap[ZFS_MAXNAMELEN];
 	uint64_t prevsnap_obj;
 	boolean_t seenfrom, seento, replicate, doall, fromorigin;
-	boolean_t verbose, dryrun, parsable, progress, embed_data;
+	boolean_t verbose, dryrun, parsable, progress, embed_data, large_block;
 	int outfd;
 	boolean_t err;
 	nvlist_t *fss;
@@ -1153,6 +1153,8 @@
 		}
 
 		enum lzc_send_flags flags = 0;
+		if (sdd->large_block)
+			flags |= LZC_SEND_FLAG_LARGE_BLOCK;
 		if (sdd->embed_data)
 			flags |= LZC_SEND_FLAG_EMBED_DATA;
 
@@ -1501,6 +1503,7 @@
 	sdd.parsable = flags->parsable;
 	sdd.progress = flags->progress;
 	sdd.dryrun = flags->dryrun;
+	sdd.large_block = flags->largeblock;
 	sdd.embed_data = flags->embed_data;
 	sdd.filter_cb = filter_func;
 	sdd.filter_cb_arg = cb_arg;
@@ -2506,7 +2509,7 @@
 recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
 {
 	dmu_replay_record_t *drr;
-	void *buf = malloc(1<<20);
+	void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE);
 	char errbuf[1024];
 
 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
--- a/usr/src/lib/libzfs_core/common/libzfs_core.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libzfs_core/common/libzfs_core.c	Wed Nov 12 04:51:53 2014 -0800
@@ -455,6 +455,10 @@
  *
  * "fd" is the file descriptor to write the send stream to.
  *
+ * If "flags" contains LZC_SEND_FLAG_LARGE_BLOCK, the stream is permitted
+ * to contain DRR_WRITE records with drr_length > 128K, and DRR_OBJECT
+ * records with drr_blksz > 128K.
+ *
  * If "flags" contains LZC_SEND_FLAG_EMBED_DATA, the stream is permitted
  * to contain DRR_WRITE_EMBEDDED records with drr_etype==BP_EMBEDDED_TYPE_DATA,
  * which the receiving system must support (as indicated by support
@@ -471,6 +475,8 @@
 	fnvlist_add_int32(args, "fd", fd);
 	if (from != NULL)
 		fnvlist_add_string(args, "fromsnap", from);
+	if (flags & LZC_SEND_FLAG_LARGE_BLOCK)
+		fnvlist_add_boolean(args, "largeblockok");
 	if (flags & LZC_SEND_FLAG_EMBED_DATA)
 		fnvlist_add_boolean(args, "embedok");
 	err = lzc_ioctl(ZFS_IOC_SEND_NEW, snapname, args, NULL);
--- a/usr/src/lib/libzfs_core/common/libzfs_core.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/libzfs_core/common/libzfs_core.h	Wed Nov 12 04:51:53 2014 -0800
@@ -53,7 +53,8 @@
 int lzc_get_holds(const char *, nvlist_t **);
 
 enum lzc_send_flags {
-	LZC_SEND_FLAG_EMBED_DATA = 1 << 0
+	LZC_SEND_FLAG_EMBED_DATA = 1 << 0,
+	LZC_SEND_FLAG_LARGE_BLOCK = 1 << 1
 };
 
 int lzc_send(const char *, const char *, int, enum lzc_send_flags);
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Wed Nov 12 04:51:53 2014 -0800
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -348,6 +348,11 @@
 		break;
 
 	case NETR_NETWORK_LOGON:
+		if (user_info->lg_challenge_key.len < 8 ||
+		    user_info->lg_challenge_key.val == NULL) {
+			ndr_rpc_release(netr_handle);
+			return (NT_STATUS_INVALID_PARAMETER);
+		}
 		netr_setup_identity(heap, user_info, &info2.identity);
 		netr_network_samlogon(heap, netr_info, user_info, &info2);
 		arg.logon_info.ru.info2 = &info2;
@@ -433,7 +438,13 @@
 {
 	uint32_t len;
 
-	bcopy(user_info->lg_challenge_key.val, info2->lm_challenge.data, 8);
+	if (user_info->lg_challenge_key.len >= 8 &&
+	    user_info->lg_challenge_key.val != 0) {
+		bcopy(user_info->lg_challenge_key.val,
+		    info2->lm_challenge.data, 8);
+	} else {
+		bzero(info2->lm_challenge.data, 8);
+	}
 
 	if ((len = user_info->lg_nt_password.len) != 0) {
 		ndr_heap_mkvcb(heap, user_info->lg_nt_password.val, len,
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers	Wed Nov 12 04:51:53 2014 -0800
@@ -19,7 +19,7 @@
 #
 #
 # Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 #
 
 #
@@ -79,7 +79,6 @@
 	smb_auth_ntlm_hash;
 	smb_auth_ntlmv2_hash;
 	smb_auth_qnd_unicode;
-	smb_auth_set_info;
 	smb_auth_validate_lm;
 	smb_auth_validate_nt;
 	smb_buf32_xdr;
--- a/usr/src/man/man1m/zfs.1m	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/man/man1m/zfs.1m	Wed Nov 12 04:51:53 2014 -0800
@@ -176,12 +176,12 @@
 
 .LP
 .nf
-\fBzfs\fR \fBsend\fR [\fB-DnPpRve\fR] [\fB-\fR[\fBiI\fR] \fIsnapshot\fR] \fIsnapshot\fR
+\fBzfs\fR \fBsend\fR [\fB-DnPpRveL\fR] [\fB-\fR[\fBiI\fR] \fIsnapshot\fR] \fIsnapshot\fR
 .fi
 
 .LP
 .nf
-\fBzfs\fR \fBsend\fR [\fB-e\fR] [\fB-i \fIsnapshot\fR|\fIbookmark\fR]\fR \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR
+\fBzfs\fR \fBsend\fR [\fB-eL\fR] [\fB-i \fIsnapshot\fR|\fIbookmark\fR]\fR \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR
 .fi
 
 .LP
@@ -1244,7 +1244,9 @@
 systems is strongly discouraged, and may adversely affect performance.
 .sp
 The size specified must be a power of two greater than or equal to 512 and less
-than or equal to 128 Kbytes.
+than or equal to 128 Kbytes.  If the \fBlarge_blocks\fR feature is enabled
+on the pool, the size may be up to 1 Mbyte.  See \fBzpool-features\fR(5)
+for details on ZFS feature flags.
 .sp
 Changing the file system's \fBrecordsize\fR affects only files created
 afterward; existing files are unaffected.
@@ -2923,7 +2925,7 @@
 .sp
 .ne 2
 .na
-\fBzfs send\fR [\fB-DnPpRve\fR] [\fB-\fR[\fBiI\fR] \fIsnapshot\fR] \fIsnapshot\fR
+\fBzfs send\fR [\fB-DnPpRveL\fR] [\fB-\fR[\fBiI\fR] \fIsnapshot\fR] \fIsnapshot\fR
 .ad
 .sp .6
 .RS 4n
@@ -2999,6 +3001,21 @@
 .sp
 .ne 2
 .na
+\fB\fB-L\fR\fR
+.ad
+.sp .6
+.RS 4n
+Generate a stream which may contain blocks larger than 128KB.  This flag
+has no effect if the \fBlarge_blocks\fR pool feature is disabled, or if
+the \fRrecordsize\fR property of this filesystem has never been set above
+128KB.  The receiving system must have the \fBlarge_blocks\fR pool feature
+enabled as well.  See \fBzpool-features\fR(5) for details on ZFS feature
+flags and the \fBlarge_blocks\fR feature.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-e\fR\fR
 .ad
 .sp .6
@@ -3064,7 +3081,7 @@
 .sp
 .ne 2
 .na
-\fBzfs send\fR [\fB-e\fR] [\fB-i\fR \fIsnapshot\fR|\fIbookmark\fR] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR
+\fBzfs send\fR [\fB-eL\fR] [\fB-i\fR \fIsnapshot\fR|\fIbookmark\fR] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR
 .ad
 .sp .6
 .RS 4n
@@ -3095,6 +3112,21 @@
 .sp
 .ne 2
 .na
+\fB\fB-L\fR\fR
+.ad
+.sp .6
+.RS 4n
+Generate a stream which may contain blocks larger than 128KB.  This flag
+has no effect if the \fBlarge_blocks\fR pool feature is disabled, or if
+the \fRrecordsize\fR property of this filesystem has never been set above
+128KB.  The receiving system must have the \fBlarge_blocks\fR pool feature
+enabled as well.  See \fBzpool-features\fR(5) for details on ZFS feature
+flags and the \fBlarge_blocks\fR feature.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-e\fR\fR
 .ad
 .sp .6
--- a/usr/src/man/man3c/Makefile	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/man/man3c/Makefile	Wed Nov 12 04:51:53 2014 -0800
@@ -477,7 +477,7 @@
 	 	u8_validate.3c					\
 	 	ualarm.3c					\
 	 	uconv_u16tou32.3c				\
-	 	ucred_get.3c					\
+	 	ucred.3c					\
 	 	ungetc.3c					\
 	 	ungetwc.3c					\
 	 	unlockpt.3c					\
@@ -1194,6 +1194,7 @@
 	 	uconv_u8tou16.3c			\
 	 	uconv_u8tou32.3c			\
 	 	ucred_free.3c				\
+	 	ucred_get.3c				\
 	 	ucred_getegid.3c			\
 	 	ucred_geteuid.3c			\
 	 	ucred_getgroups.3c			\
@@ -2208,21 +2209,22 @@
 uconv_u8tou16.3c			:= LINKSRC = uconv_u16tou32.3c
 uconv_u8tou32.3c			:= LINKSRC = uconv_u16tou32.3c
 
-ucred_free.3c				:= LINKSRC = ucred_get.3c
-ucred_getegid.3c			:= LINKSRC = ucred_get.3c
-ucred_geteuid.3c			:= LINKSRC = ucred_get.3c
-ucred_getgroups.3c			:= LINKSRC = ucred_get.3c
-ucred_getlabel.3c			:= LINKSRC = ucred_get.3c
-ucred_getpflags.3c			:= LINKSRC = ucred_get.3c
-ucred_getpid.3c				:= LINKSRC = ucred_get.3c
-ucred_getprivset.3c			:= LINKSRC = ucred_get.3c
-ucred_getprojid.3c			:= LINKSRC = ucred_get.3c
-ucred_getrgid.3c			:= LINKSRC = ucred_get.3c
-ucred_getruid.3c			:= LINKSRC = ucred_get.3c
-ucred_getsgid.3c			:= LINKSRC = ucred_get.3c
-ucred_getsuid.3c			:= LINKSRC = ucred_get.3c
-ucred_getzoneid.3c			:= LINKSRC = ucred_get.3c
-ucred_size.3c				:= LINKSRC = ucred_get.3c
+ucred_free.3c				:= LINKSRC = ucred.3c
+ucred_get.3c				:= LINKSRC = ucred.3c
+ucred_getegid.3c			:= LINKSRC = ucred.3c
+ucred_geteuid.3c			:= LINKSRC = ucred.3c
+ucred_getgroups.3c			:= LINKSRC = ucred.3c
+ucred_getlabel.3c			:= LINKSRC = ucred.3c
+ucred_getpflags.3c			:= LINKSRC = ucred.3c
+ucred_getpid.3c				:= LINKSRC = ucred.3c
+ucred_getprivset.3c			:= LINKSRC = ucred.3c
+ucred_getprojid.3c			:= LINKSRC = ucred.3c
+ucred_getrgid.3c			:= LINKSRC = ucred.3c
+ucred_getruid.3c			:= LINKSRC = ucred.3c
+ucred_getsgid.3c			:= LINKSRC = ucred.3c
+ucred_getsuid.3c			:= LINKSRC = ucred.3c
+ucred_getzoneid.3c			:= LINKSRC = ucred.3c
+ucred_size.3c				:= LINKSRC = ucred.3c
 
 vswprintf.3c				:= LINKSRC = vfwprintf.3c
 vwprintf.3c				:= LINKSRC = vfwprintf.3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/man/man3c/ucred.3c	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,289 @@
+'\" te
+.\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved.
+.\" 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 UCRED 3C "Nov 6, 2014"
+.SH NAME
+ucred, ucred_get, ucred_free, ucred_geteuid, ucred_getruid, ucred_getsuid,
+ucred_getegid, ucred_getrgid, ucred_getsgid, ucred_getgroups, ucred_getprivset,
+ucred_getpid, ucred_getprojid, ucred_getzoneid, ucred_getpflags,
+ucred_getlabel, ucred_size \- user credential functions
+.SH SYNOPSIS
+.LP
+.nf
+#include <ucred.h>
+
+\fBucred_t *\fR\fBucred_get\fR(\fBpid_t\fR \fIpid\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBucred_free\fR(\fBucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBuid_t\fR \fBucred_geteuid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBuid_t\fR \fBucred_getruid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBuid_t\fR \fBucred_getsuid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBgid_t\fR \fBucred_getegid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBgid_t\fR \fBucred_getrgid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBgid_t\fR \fBucred_getsgid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBint\fR \fBucred_getgroups\fR(\fBconst ucred_t *\fR\fIuc\fR, \fBconst gid_t **\fR\fIgroups\fR);
+.fi
+
+.LP
+.nf
+\fBconst priv_set_t *\fR\fBucred_getprivset\fR(\fBconst ucred_t *\fR\fIuc\fR,
+     \fBpriv_ptype_t\fR \fIset\fR);
+.fi
+
+.LP
+.nf
+\fBpid_t\fR \fBucred_getpid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBprojid_t\fR \fBucred_getprojid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBzoneid_t\fR \fBucred_getzoneid\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBuint_t\fR \fBucred_getpflags\fR(\fBconst ucred_t *\fR\fIuc\fR, \fBuint_t\fR \fIflags\fR);
+.fi
+
+.LP
+.nf
+\fBm_label_t *\fR\fBucred_getlabel\fR(\fBconst ucred_t *\fR\fIuc\fR);
+.fi
+
+.LP
+.nf
+\fBsize_t\fR \fBucred_size\fR(\fBvoid\fR);
+.fi
+
+.SH DESCRIPTION
+.LP
+These functions return or act on a user credential, \fBucred_t\fR. User
+credentials are returned by various functions and describe the credentials of a
+process. Information about the process can then be obtained by calling the
+access functions. Access functions can fail if the underlying mechanism did not
+return sufficient information.
+.sp
+.LP
+The \fBucred_get()\fR function returns the user credential of the specified
+\fIpid\fR or \fINULL\fR if none can be obtained. A \fIpid\fR value of
+\fBP_MYID\fR returns information about the calling process. The return value is
+dynamically allocated and must be freed using \fBucred_free()\fR.
+.sp
+.LP
+The \fBucred_geteuid()\fR, \fBucred_getruid()\fR, \fBucred_getsuid()\fR,
+\fBucred_getegid()\fR, \fBucred_getrgid()\fR, and \fBucred_getsgid()\fR
+functions return the effective UID, real UID, saved UID, effective GID, real
+GID, saved GID, respectively, or -1 if the user credential does not contain
+sufficient information.
+.sp
+.LP
+The \fBucred_getgroups()\fR function stores a pointer to the group list in the
+\fBgid_t *\fR pointed to by the second argument and returns the number of
+groups in the list. It returns -1 if the information is not available. The
+returned group list is valid until \fBucred_free()\fR is called on the user
+credential given as argument.
+.sp
+.LP
+The \fBucred_getpid()\fR function returns the process ID of the process or -1
+if the process ID is not available. The process ID returned in a user
+credential is only guaranteed to be correct in a very limited number of cases
+when returned by \fBdoor_ucred\fR(3C) and \fBucred_get()\fR. In all other
+cases, the process in question might have handed of the file descriptor, the
+process might have exited or executed another program, or the process ID might
+have been reused by a completely unrelated process after the original program
+exited.
+.sp
+.LP
+The \fBucred_getprojid()\fR function returns the project ID of the process or
+-1 if the project ID is not available.
+.sp
+.LP
+The \fBucred_getzoneid()\fR function returns the zone ID of the process or
+\(mi1 if the zone ID is not available.
+.sp
+.LP
+The \fBucred_getprivset()\fR function returns the specified privilege set
+specified as second argument, or \fINULL\fR if either the requested information
+is not available or the privilege set name is invalid. The returned privilege
+set is valid until \fBucred_free()\fR is called on the specified user
+credential.
+.sp
+.LP
+The \fBucred_getpflags()\fR function returns the value of the specified
+privilege flags from the \fBucred\fR structure, or (\fBuint_t\fR)-1 if none was
+present.
+.sp
+.LP
+The \fBucred_getlabel()\fR function returns the value of the label, or
+\fINULL\fR if the label is not available. The returned label is valid until
+\fBucred_free()\fR is called on the specified user credential. This function is
+available only if the system is configured with Trusted Extensions.
+.sp
+.LP
+The \fBucred_free()\fR function frees the memory allocated for the specified
+user credential.
+.sp
+.LP
+The \fBucred_size()\fR function returns \fBsizeof\fR(\fBucred_t\fR). This value
+is constant only until the next boot, at which time it could change. The
+\fBucred_size()\fR function can be used to determine the size of the buffer
+needed to receive a credential option with \fBSO_RECVUCRED\fR. See
+\fBsocket.h\fR(3HEAD).
+.SH RETURN VALUES
+.LP
+See DESCRIPTION.
+.SH ERRORS
+.LP
+The \fBucred_get()\fR function will fail if:
+.sp
+.ne 2
+.na
+\fB\fBEAGAIN\fR\fR
+.ad
+.RS 10n
+There is not enough memory available to allocate sufficient memory to hold a
+user credential. The application can try again later.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBEACCES\fR\fR
+.ad
+.RS 10n
+The caller does not have sufficient privileges to examine the target process.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBEMFILE\fR\fR
+.ad
+.br
+.na
+\fB\fBENFILE\fR\fR
+.ad
+.RS 10n
+The calling process cannot open any more files.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBENOMEM\fR\fR
+.ad
+.RS 10n
+The physical limits of the system are exceeded by the memory allocation needed
+to hold a user credential.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBESRCH\fR\fR
+.ad
+.RS 10n
+The target process does not exist.
+.RE
+
+.sp
+.LP
+The \fBucred_getprivset()\fR function will fail if:
+.sp
+.ne 2
+.na
+\fB\fBEINVAL\fR\fR
+.ad
+.RS 10n
+The privilege set argument is invalid.
+.RE
+
+.sp
+.LP
+The \fBucred_getlabel()\fR function will fail if:
+.sp
+.ne 2
+.na
+\fB\fBEINVAL\fR\fR
+.ad
+.RS 10n
+The label is not present.
+.RE
+
+.sp
+.LP
+The \fBucred_geteuid()\fR, \fBucred_getruid()\fR, \fBucred_getsuid()\fR,
+\fBucred_getegid()\fR, \fBucred_getrgid()\fR, \fBucred_getsgid()\fR,
+\fBucred_getgroups()\fR, \fBucred_getpflags()\fR, \fBucred_getprivset()\fR,
+\fBucred_getprojid()\fR, \fBucred_getpid()\fR, and \fBucred_getlabel()\fR
+functions will fail if:
+.sp
+.ne 2
+.na
+\fB\fBEINVAL\fR\fR
+.ad
+.RS 10n
+The requested user credential attribute is not available in the specified user
+credential.
+.RE
+
+.SH ATTRIBUTES
+.LP
+See \fBattributes\fR(5) for descriptions of the following attributes:
+.sp
+
+.sp
+.TS
+box;
+c | c
+l | l .
+ATTRIBUTE TYPE	ATTRIBUTE VALUE
+_
+Interface Stability	Committed
+_
+MT-Level	MT-Safe
+.TE
+
+.SH SEE ALSO
+.LP
+\fBgetpflags\fR(2), \fBgetppriv\fR(2), \fBdoor_ucred\fR(3C),
+\fBgetpeerucred\fR(3C), \fBpriv_set\fR(3C), \fBsocket.h\fR(3HEAD),
+\fBattributes\fR(5), \fBlabels\fR(5), \fBprivileges\fR(5)
--- a/usr/src/man/man3c/ucred_get.3c	Thu Nov 06 07:49:31 2014 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,294 +0,0 @@
-'\" te
-.\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved.
-.\" 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 UCRED_GET 3C "Apr 4, 2008"
-.SH NAME
-ucred_get, ucred_free, ucred_geteuid, ucred_getruid, ucred_getsuid,
-ucred_getegid, ucred_getrgid, ucred_getsgid, ucred_getgroups, ucred_getprivset,
-ucred_getpid, ucred_getprojid, ucred_getzoneid, ucred_getpflags,
-ucred_getlabel, ucred_size \- user credential functions
-.SH SYNOPSIS
-.LP
-.nf
-#include <ucred.h>
-
-\fBucred_t *\fR\fBucred_get\fR(\fBpid_t\fR \fIpid\fR);
-.fi
-
-.LP
-.nf
-\fBvoid\fR \fBucred_free\fR(\fBucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBuid_t\fR \fBucred_geteuid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBuid_t\fR \fBucred_getruid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBuid_t\fR \fBucred_getsuid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBgid_t\fR \fBucred_getegid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBgid_t\fR \fBucred_getrgid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBgid_t\fR \fBucred_getsgid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBint\fR \fBucred_getgroups\fR(\fBconst ucred_t *\fR\fIuc\fR, \fBconst gid_t **\fR\fIgroups\fR);
-.fi
-
-.LP
-.nf
-\fBconst priv_set_t *\fR\fBucred_getprivset\fR(\fBconst ucred_t *\fR\fIuc\fR,
-     \fBpriv_ptype_t\fR \fIset\fR);
-.fi
-
-.LP
-.nf
-\fBpid_t\fR \fBucred_getpid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBprojid_t\fR \fBucred_getprojid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBzoneid_t\fR \fBucred_getzoneid\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBuint_t\fR \fBucred_getpflags\fR(\fBconst ucred_t *\fR\fIuc\fR, \fBuint_t\fR \fIflags\fR);
-.fi
-
-.LP
-.nf
-\fBm_label_t *\fR\fBucred_getlabel\fR(\fBconst ucred_t *\fR\fIuc\fR);
-.fi
-
-.LP
-.nf
-\fBsize_t\fR \fBucred_size\fR(\fBvoid\fR);
-.fi
-
-.SH DESCRIPTION
-.sp
-.LP
-These functions return or act on a user credential, \fBucred_t\fR. User
-credentials are returned by various functions and describe the credentials of a
-process. Information about the process can then be obtained by calling the
-access functions. Access functions can fail if the underlying mechanism did not
-return sufficient information.
-.sp
-.LP
-The \fBucred_get()\fR function returns the user credential of the specified
-\fIpid\fR or \fINULL\fR if none can be obtained. A \fIpid\fR value of
-\fBP_MYID\fR returns information about the calling process. The return value is
-dynamically allocated and must be freed using \fBucred_free()\fR.
-.sp
-.LP
-The \fBucred_geteuid()\fR, \fBucred_getruid()\fR, \fBucred_getsuid()\fR,
-\fBucred_getegid()\fR, \fBucred_getrgid()\fR, and \fBucred_getsgid()\fR
-functions return the effective UID, real UID, saved UID, effective GID, real
-GID, saved GID, respectively, or -1 if the user credential does not contain
-sufficient information.
-.sp
-.LP
-The \fBucred_getgroups()\fR function stores a pointer to the group list in the
-\fBgid_t *\fR pointed to by the second argument and returns the number of
-groups in the list. It returns -1 if the information is not available. The
-returned group list is valid until \fBucred_free()\fR is called on the user
-credential given as argument.
-.sp
-.LP
-The \fBucred_getpid()\fR function returns the process ID of the process or -1
-if the process ID is not available. The process ID returned in a user
-credential is only guaranteed to be correct in a very limited number of cases
-when returned by \fBdoor_ucred\fR(3C) and \fBucred_get()\fR. In all other
-cases, the process in question might have handed of the file descriptor, the
-process might have exited or executed another program, or the process ID might
-have been reused by a completely unrelated process after the original program
-exited.
-.sp
-.LP
-The \fBucred_getprojid()\fR function returns the project ID of the process or
--1 if the project ID is not available.
-.sp
-.LP
-The \fBucred_getzoneid()\fR function returns the zone ID of the process or
-\(mi1 if the zone ID is not available.
-.sp
-.LP
-The \fBucred_getprivset()\fR function returns the specified privilege set
-specified as second argument, or \fINULL\fR if either the requested information
-is not available or the privilege set name is invalid. The returned privilege
-set is valid until \fBucred_free()\fR is called on the specified user
-credential.
-.sp
-.LP
-The \fBucred_getpflags()\fR function returns the value of the specified
-privilege flags from the \fBucred\fR structure, or (\fBuint_t\fR)-1 if none was
-present.
-.sp
-.LP
-The \fBucred_getlabel()\fR function returns the value of the label, or
-\fINULL\fR if the label is not available. The returned label is valid until
-\fBucred_free()\fR is called on the specified user credential. This function is
-available only if the system is configured with Trusted Extensions.
-.sp
-.LP
-The \fBucred_free()\fR function frees the memory allocated for the specified
-user credential.
-.sp
-.LP
-The \fBucred_size()\fR function returns \fBsizeof\fR(\fBucred_t\fR). This value
-is constant only until the next boot, at which time it could change. The
-\fBucred_size()\fR function can be used to determine the size of the buffer
-needed to receive a credential option with \fBSO_RECVUCRED\fR. See
-\fBsocket.h\fR(3HEAD).
-.SH RETURN VALUES
-.sp
-.LP
-See DESCRIPTION.
-.SH ERRORS
-.sp
-.LP
-The \fBucred_get()\fR function will fail if:
-.sp
-.ne 2
-.na
-\fB\fBEAGAIN\fR\fR
-.ad
-.RS 10n
-There is not enough memory available to allocate sufficient memory to hold a
-user credential. The application can try again later.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBEACCES\fR\fR
-.ad
-.RS 10n
-The caller does not have sufficient privileges to examine the target process.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBEMFILE\fR\fR
-.ad
-.br
-.na
-\fB\fBENFILE\fR\fR
-.ad
-.RS 10n
-The calling process cannot open any more files.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBENOMEM\fR\fR
-.ad
-.RS 10n
-The physical limits of the system are exceeded by the memory allocation needed
-to hold a user credential.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBESRCH\fR\fR
-.ad
-.RS 10n
-The target process does not exist.
-.RE
-
-.sp
-.LP
-The \fBucred_getprivset()\fR function will fail if:
-.sp
-.ne 2
-.na
-\fB\fBEINVAL\fR\fR
-.ad
-.RS 10n
-The privilege set argument is invalid.
-.RE
-
-.sp
-.LP
-The \fBucred_getlabel()\fR function will fail if:
-.sp
-.ne 2
-.na
-\fB\fBEINVAL\fR\fR
-.ad
-.RS 10n
-The label is not present.
-.RE
-
-.sp
-.LP
-The \fBucred_geteuid()\fR, \fBucred_getruid()\fR, \fBucred_getsuid()\fR,
-\fBucred_getegid()\fR, \fBucred_getrgid()\fR, \fBucred_getsgid()\fR,
-\fBucred_getgroups()\fR, \fBucred_getpflags()\fR, \fBucred_getprivset()\fR,
-\fBucred_getprojid()\fR, \fBucred_getpid()\fR, and \fBucred_getlabel()\fR
-functions will fail if:
-.sp
-.ne 2
-.na
-\fB\fBEINVAL\fR\fR
-.ad
-.RS 10n
-The requested user credential attribute is not available in the specified user
-credential.
-.RE
-
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(5) for descriptions of the following attributes:
-.sp
-
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE	ATTRIBUTE VALUE
-_
-Interface Stability	Committed
-_
-MT-Level	MT-Safe
-.TE
-
-.SH SEE ALSO
-.sp
-.LP
-\fBgetpflags\fR(2), \fBgetppriv\fR(2), \fBdoor_ucred\fR(3C),
-\fBgetpeerucred\fR(3C), \fBpriv_set\fR(3C), \fBsocket.h\fR(3HEAD),
-\fBattributes\fR(5), \fBlabels\fR(5), \fBprivileges\fR(5)
--- a/usr/src/man/man3lib/libpthread.3lib	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/man/man3lib/libpthread.3lib	Wed Nov 12 04:51:53 2014 -0800
@@ -1,9 +1,10 @@
 '\" te
+.\" Copyright (c) 2014, Joyent, Inc.
 .\" Copyright (c) 2004, Sun Microsystems, Inc.  All Rights Reserved.
 .\" 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 LIBPTHREAD 3LIB "Mar 24, 2004"
+.TH LIBPTHREAD 3LIB "Oct 1, 2014"
 .SH NAME
 libpthread \- POSIX threads library
 .SH SYNOPSIS
@@ -13,19 +14,15 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 Historically, functions in this library provided POSIX threading support. See
 \fBstandards\fR(5). This functionality now resides in \fBlibc\fR(3LIB).
-.sp
 .LP
 This library is maintained to provide backward compatibility for both runtime
 and compilation environments. The shared object is implemented as a filter on
-\fBlibc.so.1\fR. New application development needs to specify \fB-lpthread\fR
-only to obtain POSIX semantics for \fBfork\fR(2) that assumes the behavior of
-\fBfork1\fR(2) rather than the default behavior that forks all threads.
+\fBlibc.so.1\fR. New application development need not specify \fB-lpthread\fR
+although doing so has no effect.
 .SH INTERFACES
-.sp
 .LP
 The shared object \fBlibpthread.so.1\fR provides the public interfaces defined
 below. See \fBIntro\fR(3) for additional information on shared object
@@ -81,7 +78,6 @@
 .TE
 
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/lib/libpthread.so.1\fR\fR
@@ -100,7 +96,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -116,7 +111,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBpvs\fR(1), \fBIntro\fR(2), \fBIntro\fR(3), \fBlibc\fR(3LIB),
 \fBlibc_db\fR(3LIB), \fBlibthread\fR(3LIB), \fBattributes\fR(5),
--- a/usr/src/man/man5/zpool-features.5	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/man/man5/zpool-features.5	Wed Nov 12 04:51:53 2014 -0800
@@ -18,7 +18,6 @@
 .SH NAME
 zpool\-features \- ZFS pool feature descriptions
 .SH DESCRIPTION
-.sp
 .LP
 ZFS pool on\-disk format versions are specified via "features" which replace
 the old on\-disk format numbers (the last supported on\-disk format number is
@@ -36,7 +35,6 @@
 \fBactive\fR on the pool. If the pool was created by another software version
 this set may include unsupported features.
 .SS "Identifying features"
-.sp
 .LP
 Every feature has a guid of the form \fIcom.example:feature_name\fR. The reverse
 DNS name ensures that the feature's guid is unique across all ZFS
@@ -51,7 +49,6 @@
 however a feature's short name may differ across ZFS implementations if
 following the convention would result in name conflicts.
 .SS "Feature states"
-.sp
 .LP
 Features can be in one of three states:
 .sp
@@ -97,7 +94,6 @@
 The state of supported features is exposed through pool properties of the form
 \fIfeature@short_name\fR.
 .SS "Read\-only compatibility"
-.sp
 .LP
 Some features may make on\-disk format changes that do not interfere with other
 software's ability to read from the pool. These features are referred to as
@@ -106,7 +102,6 @@
 \fBreadonly\fR property during import (see \fBzpool\fR(1M) for details on
 importing pools).
 .SS "Unsupported features"
-.sp
 .LP
 For each unsupported feature enabled on an imported pool a pool property
 named \fIunsupported@feature_guid\fR will indicate why the import was allowed
@@ -133,13 +128,11 @@
 .RE
 
 .SS "Feature dependencies"
-.sp
 .LP
 Some features depend on other features being enabled in order to function
 properly. Enabling a feature will automatically enable any features it
 depends on.
 .SH FEATURES
-.sp
 .LP
 The following features are supported on this system:
 .sp
@@ -430,5 +423,26 @@
 
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fBlarge_blocks\fR\fR
+.ad
+.RS 4n
+.TS
+l l .
+GUID	org.open-zfs:large_block
+READ\-ONLY COMPATIBLE	no
+DEPENDENCIES	extensible_dataset
+.TE
+
+The \fBlarge_block\fR feature allows the record size on a dataset to be
+set larger than 128KB.
+
+This feature becomes \fBactive\fR once a \fBrecordsize\fR property has been
+set larger than 128KB, and will return to being \fBenabled\fR once all
+filesystems that have ever had their recordsize larger than 128KB are destroyed.
+.RE
+
 .SH "SEE ALSO"
 \fBzpool\fR(1M)
--- a/usr/src/pkg/manifests/developer-build-onbld.mf	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/pkg/manifests/developer-build-onbld.mf	Wed Nov 12 04:51:53 2014 -0800
@@ -24,6 +24,7 @@
 # Copyright 2010, Richard Lowe
 # Copyright 2012, Piotr Jasiukajtis
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright (c) 2014, Joyent, Inc.
 #
 
 set name=pkg.fmri value=pkg:/developer/build/onbld@$(PKGVERS)
@@ -169,6 +170,8 @@
 file path=opt/onbld/lib/python2.6/onbld/Checks/__init__.pyc mode=0444
 file path=opt/onbld/lib/python2.6/onbld/Scm/Backup.py mode=0444
 file path=opt/onbld/lib/python2.6/onbld/Scm/Backup.pyc mode=0444
+file path=opt/onbld/lib/python2.6/onbld/Scm/Ignore.py mode=0444
+file path=opt/onbld/lib/python2.6/onbld/Scm/Ignore.pyc mode=0444
 file path=opt/onbld/lib/python2.6/onbld/Scm/Version.py mode=0444
 file path=opt/onbld/lib/python2.6/onbld/Scm/Version.pyc mode=0444
 file path=opt/onbld/lib/python2.6/onbld/Scm/WorkSpace.py mode=0444
--- a/usr/src/pkg/manifests/system-library.man3c.inc	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/pkg/manifests/system-library.man3c.inc	Wed Nov 12 04:51:53 2014 -0800
@@ -473,7 +473,7 @@
 file path=usr/share/man/man3c/u8_validate.3c
 file path=usr/share/man/man3c/ualarm.3c
 file path=usr/share/man/man3c/uconv_u16tou32.3c
-file path=usr/share/man/man3c/ucred_get.3c
+file path=usr/share/man/man3c/ucred.3c
 file path=usr/share/man/man3c/ungetc.3c
 file path=usr/share/man/man3c/ungetwc.3c
 file path=usr/share/man/man3c/unlockpt.3c
@@ -1264,21 +1264,22 @@
 link path=usr/share/man/man3c/uconv_u32tou8.3c target=uconv_u16tou32.3c
 link path=usr/share/man/man3c/uconv_u8tou16.3c target=uconv_u16tou32.3c
 link path=usr/share/man/man3c/uconv_u8tou32.3c target=uconv_u16tou32.3c
-link path=usr/share/man/man3c/ucred_free.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getegid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_geteuid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getgroups.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getlabel.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getpflags.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getpid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getprivset.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getprojid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getrgid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getruid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getsgid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getsuid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_getzoneid.3c target=ucred_get.3c
-link path=usr/share/man/man3c/ucred_size.3c target=ucred_get.3c
+link path=usr/share/man/man3c/ucred_free.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_get.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getegid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_geteuid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getgroups.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getlabel.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getpflags.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getpid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getprivset.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getprojid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getrgid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getruid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getsgid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getsuid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_getzoneid.3c target=ucred.3c
+link path=usr/share/man/man3c/ucred_size.3c target=ucred.3c
 link path=usr/share/man/man3c/ulckpwdf.3c target=lckpwdf.3c
 link path=usr/share/man/man3c/ulltostr.3c target=strtol.3c
 link path=usr/share/man/man3c/unordered.3c target=isnand.3c
--- a/usr/src/pkg/manifests/system-test-utiltest.mf	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/pkg/manifests/system-test-utiltest.mf	Wed Nov 12 04:51:53 2014 -0800
@@ -24,10 +24,21 @@
 dir path=opt/util-tests/bin
 dir path=opt/util-tests/runfiles
 dir path=opt/util-tests/tests
+dir path=opt/util-tests/tests/libnvpair_json
 file path=opt/util-tests/README mode=0444
+file path=opt/util-tests/bin/print_json mode=0555
 file path=opt/util-tests/bin/utiltest mode=0555
 file path=opt/util-tests/runfiles/default.run mode=0444
 file path=opt/util-tests/tests/allowed-ips mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_00_blank mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_01_boolean mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_02_numbers mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_03_empty_arrays mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_04_number_arrays mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_05_strings mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_06_nested mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_07_nested_arrays mode=0555
+file path=opt/util-tests/tests/libnvpair_json/json_common mode=0555
 file path=opt/util-tests/tests/printf_test mode=0555
 file path=opt/util-tests/tests/xargs_test mode=0555
 license lic_CDDL license=lic_CDDL
--- a/usr/src/test/util-tests/runfiles/default.run	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/test/util-tests/runfiles/default.run	Wed Nov 12 04:51:53 2014 -0800
@@ -26,3 +26,8 @@
 [/opt/util-tests/tests/allowed-ips]
 
 [/opt/util-tests/tests/xargs_test]
+
+[/opt/util-tests/tests/libnvpair_json]
+tests = ['json_00_blank', 'json_01_boolean', 'json_02_numbers',
+    'json_03_empty_arrays', 'json_04_number_arrays', 'json_05_strings',
+    'json_06_nested', 'json_07_nested_arrays']
--- a/usr/src/test/util-tests/tests/Makefile	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/test/util-tests/tests/Makefile	Wed Nov 12 04:51:53 2014 -0800
@@ -15,5 +15,6 @@
 #
 
 SUBDIRS = dladm printf xargs
+SUBDIRS = dladm libnvpair_json printf xargs
 
 include $(SRC)/test/Makefile.com
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/Makefile	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,76 @@
+#
+# 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.
+#
+
+include $(SRC)/Makefile.master
+
+ROOTOPTPKG = $(ROOT)/opt/util-tests
+TESTDIR = $(ROOTOPTPKG)/tests/libnvpair_json
+ROOTBINDIR = $(ROOTOPTPKG)/bin
+
+PROG = print_json
+
+SCRIPTS = \
+	json_00_blank \
+	json_01_boolean \
+	json_02_numbers \
+	json_03_empty_arrays \
+	json_04_number_arrays \
+	json_05_strings \
+	json_06_nested \
+	json_07_nested_arrays \
+	json_common
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+OBJS = $(PROG:%=%.o)
+SRCS = $(OBJS:%.o=%.c)
+
+CMDS = $(PROG:%=$(ROOTBINDIR)/%) $(SCRIPTS:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+LDLIBS += -lnvpair
+
+LINTFLAGS += -erroff=E_FUNC_ARG_UNUSED
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+	$(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+	$(POST_PROCESS)
+
+install: all $(CMDS)
+
+lint: lint_SRCS
+
+clobber: clean
+	-$(RM) $(PROG)
+
+clean:
+	-$(RM) $(OBJS)
+
+$(CMDS): $(TESTDIR) $(PROG)
+
+$(ROOTBINDIR):
+	$(INS.dir)
+
+$(ROOTBINDIR)/%: %
+	$(INS.file)
+
+$(TESTDIR):
+	$(INS.dir)
+
+$(TESTDIR)/%: %.ksh
+	$(INS.rename)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_00_blank.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,31 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+DIR=$(dirname $(whence $0))
+. ${DIR}/json_common
+
+BASELINE="$(cat <<EOF
+{\
+}
+EOF)"
+
+OUTPUT="$(${DIR}/../../bin/print_json <<'EOF'
+/*
+ * Emit a blank object.
+ */
+EOF)"
+
+complete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_01_boolean.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,46 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+DIR=$(dirname $(whence $0))
+. ${DIR}/json_common
+
+BASELINE="$(cat <<EOF
+{\
+"bool0":true,\
+"a fact":true,\
+"a fiction":false,\
+"1":true,\
+" ":true\
+}
+EOF)"
+
+OUTPUT="$(${DIR}/../../bin/print_json <<'EOF'
+/*
+ * add_boolean calls nvlist_add_boolean(), which the JSON formatter
+ * will emit as a true-valued boolean.
+ */
+add_boolean "bool0";
+add_boolean_value "a fact" "true";
+add_boolean_value "a fiction" "false";
+add_boolean "1";
+
+/*
+ * Test a key with a whitespace-only name:
+ */
+add_boolean " ";
+EOF)"
+
+complete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_02_numbers.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,64 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+DIR=$(dirname $(whence $0))
+. ${DIR}/json_common
+
+BASELINE="$(cat <<EOF
+{\
+"byte":255,\
+"uint8_0":0,\
+"uint8_100":100,\
+"uint8_255":255,\
+"uint16":12345,\
+"uint32":23423423,\
+"uint64":19850709000000,\
+"int16_small":-32768,\
+"int8_neg":-128,\
+"int8_pos":127,\
+"int16_big":32767,\
+"int32":-1270000,\
+"int64":-12700000000001,\
+"double_small":0.000023,\
+"double_big":2342300000000.000000\
+}
+EOF)"
+
+OUTPUT="$(${DIR}/../../bin/print_json <<'EOF'
+add_byte "byte" "0";
+add_byte "byte" "255";
+
+add_uint8 "uint8_0" "0";
+add_uint8 "uint8_100" "100";
+add_uint8 "uint8_255" "255";
+
+add_uint16 "uint16" "12345";
+add_uint32 "uint32" "23423423";
+add_uint64 "uint64" "19850709000000";
+
+add_int16 "int16_small" "-32768";
+add_int8 "int8_neg" "-128";
+add_int8 "int8_pos" "127";
+add_int16 "int16_big" "32767";
+
+add_int32 "int32" "-1270000";
+add_int64 "int64" "-12700000000001";
+
+add_double "double_small" "0.000023423";
+add_double "double_big" "0.000023423e17";
+EOF)"
+
+complete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_03_empty_arrays.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,63 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+DIR=$(dirname $(whence $0))
+. ${DIR}/json_common
+
+BASELINE="$(cat <<EOF
+{\
+"boolean_array":[],\
+"byte_array":[],\
+"uint8_array":[],\
+"uint16_array":[],\
+"uint32_array":[],\
+"uint64_array":[],\
+"int8_array":[],\
+"int16_array":[],\
+"int32_array":[],\
+"int64_array":[],\
+"string_array":[],\
+"object_array":[{}]\
+}
+EOF)"
+
+OUTPUT="$(${DIR}/../../bin/print_json <<'EOF'
+add_boolean_array "boolean_array";
+
+add_byte_array "byte_array";
+
+add_uint8_array "uint8_array";
+add_uint16_array "uint16_array";
+add_uint32_array "uint32_array";
+add_uint64_array "uint64_array";
+
+add_int8_array "int8_array";
+add_int16_array "int16_array";
+add_int32_array "int32_array";
+add_int64_array "int64_array";
+
+add_string_array "string_array";
+
+/*
+ * The testing DSL does not presently support the generation of a completely
+ * empty object array.  Thus, the following directive will produce an array
+ * with a single keyless object:
+ */
+add_object_array "object_array";
+end;
+EOF)"
+
+complete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_04_number_arrays.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,65 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+DIR=$(dirname $(whence $0))
+. ${DIR}/json_common
+
+BASELINE="$(cat <<EOF
+{\
+"byte_array":[0,1,2,10,15,100,103,127,128,254,255],\
+"uint8_array":[128,254,255,10,15,100,103,127,0,1,2],\
+"uint16_array":[0,1000,2000,3210,4321,5432,10000,15000,16384,\
+17992,35012,65535,0],\
+"uint32_array":[0,4294967295,4026531855,1,2,1000,501],\
+"uint64_array":[19850907,0,18446744073709551615],\
+"int8_array":[39,39,39,39,39,39,39,-128,-127,0,127],\
+"int16_array":[7532,-32768,0,32767,0,-32768,100],\
+"int32_array":[-2147483648,0,32767,-32768,2147483647],\
+"int64_array":[0,0,9223372036854775807,1,1,1,-9223372036854775808,0]\
+}
+EOF)"
+
+OUTPUT="$(${DIR}/../../bin/print_json <<'EOF'
+add_byte_array "byte_array"
+  "0" "1" "2" "10" "15" "100" "103" "127" "128" "254" "255";
+
+add_uint8_array "uint8_array"
+  "128" "254" "255" "10" "15" "100" "103" "127" "0" "1" "2";
+
+add_uint16_array "uint16_array"
+  "0" "1000" "2000" "3210" "4321" "5432" "10000" "15000" "16384"
+  "17992" "35012" "65535" "0";
+
+add_uint32_array "uint32_array"
+  "0" "4294967295" "4026531855" "1" "2" "1000" "501";
+
+add_uint64_array "uint64_array"
+  "19850907" "0" "18446744073709551615";
+
+add_int8_array "int8_array"
+  "39" "39" "39" "39" "39" "39" "39" "-128" "-127" "0" "127";
+
+add_int16_array "int16_array"
+  "7532" "-32768" "0" "32767" "0" "-32768" "100";
+
+add_int32_array "int32_array"
+  "-2147483648" "0" "32767" "-32768" "2147483647";
+
+add_int64_array "int64_array"
+  "0" "0" "9223372036854775807" "1" "1" "1" "-9223372036854775808" "0";
+EOF)"
+
+complete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_05_strings.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,65 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+DIR=$(dirname $(whence $0))
+. ${DIR}/json_common
+
+#
+# This test checks UTF-8 parsing behaviour
+#
+export LC_ALL="en_US.UTF-8"
+export LANG="${LANG}"
+
+BASELINE="$(cat <<EOF
+{\
+"blank":"",\
+"":"blank key",\
+" ":"whitespace key",\
+"\ttab\t":"tab key",\
+"escapes":"escape \u001b newline \n cr \r backslash \\\\ quote \"",\
+"escape array":[\
+"escape \u001b",\
+"alarm \u0007",\
+"backspace \b",\
+"formfeed \f",\
+"newline \n",\
+"return \r",\
+"tab \t",\
+"vertical tab \u000b",\
+"black circle (UTF-8) \u25cf"\
+]\
+}
+EOF)"
+
+OUTPUT="$(${DIR}/../../bin/print_json <<'EOF'
+add_string "blank" "";
+add_string "" "blank key";
+add_string " " "whitespace key";
+add_string "	tab	" "tab key";
+add_string "escapes" "escape \x1b newline \n cr \r backslash \\ quote \"";
+add_string_array "escape array"
+    "escape \x1b"
+    "alarm \a"
+    "backspace \b"
+    "formfeed \f"
+    "newline \n"
+    "return \r"
+    "tab \t"
+    "vertical tab \v"
+    "black circle (UTF-8) \xe2\x97\x8f";
+EOF)"
+
+complete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_06_nested.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,68 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+DIR=$(dirname $(whence $0))
+. ${DIR}/json_common
+
+BASELINE="$(cat <<EOF
+{\
+"a":{},\
+"b":{\
+"name":"Roger","age":35\
+},\
+"c":{\
+"d":{\
+"name":"Stephen","age":27},\
+"e":{\
+"name":"Roberta","age":43,"pet":{\
+"name":"Mister Bumberscratch",\
+"species":"cat",\
+"alive":true,\
+"available_legs":[1,2,3,4]\
+}\
+}\
+}\
+}
+EOF)"
+
+OUTPUT="$(${DIR}/../../bin/print_json <<'EOF'
+add_object "a";
+end;
+
+add_object "b";
+	add_string "name" "Roger";
+	add_uint16 "age" "35";
+end;
+
+add_object "c";
+	add_object "d";
+		add_string "name" "Stephen";
+		add_uint16 "age" "27";
+	end;
+	add_object "e";
+		add_string "name" "Roberta";
+		add_uint16 "age" "43";
+		add_object "pet";
+			add_string "name" "Mister Bumberscratch";
+			add_string "species" "cat";
+			add_boolean_value "alive" "true";
+			add_uint8_array "available_legs" "1" "2" "3" "4";
+		end;
+	end;
+end;
+EOF)"
+
+complete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_07_nested_arrays.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,96 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+DIR=$(dirname $(whence $0))
+. ${DIR}/json_common
+
+BASELINE="$(cat <<EOF
+{\
+"event_store":{\
+"name":"Occurences",\
+"events":[\
+{"time":489715200,"desc":"inception"},\
+{"time":1057708800,"desc":"maturation"},\
+{"time":1344816000,"desc":"migration"},\
+{"time":1405296000,"desc":"integration"},\
+{}\
+]\
+},\
+"first level":[\
+{"second_level_0":[{\
+"sl0_a":true,\
+"sl0_b":"aaaa"\
+},\
+{"x":1234}\
+],\
+"second_level_1":[{}],\
+"second_level_2":[\
+{"alpha":"a"},\
+{"beta":"b"},\
+{"gamma":"c"},\
+{"delta":"d"},\
+{"order":["a","b","c","d"]}\
+]\
+}\
+]\
+}
+EOF)"
+
+OUTPUT="$(${DIR}/../../bin/print_json <<'EOF'
+add_object "event_store";
+	add_string "name" "Occurences";
+	add_object_array "events";
+		add_uint32 "time" "489715200";
+		add_string "desc" "inception";
+		next;
+
+		add_uint32 "time" "1057708800";
+		add_string "desc" "maturation";
+		next;
+
+		add_uint32 "time" "1344816000";
+		add_string "desc" "migration";
+		next;
+
+		add_uint32 "time" "1405296000";
+		add_string "desc" "integration";
+		next;
+	end;
+end;
+add_object_array "first level";
+	add_object_array "second_level_0";
+		add_boolean "sl0_a";
+		add_string "sl0_b" "aaaa";
+		next;
+		add_int32 "x" "1234";
+	end;
+	add_object_array "second_level_1";
+	end;
+	add_object_array "second_level_2";
+		add_string "alpha" "a";
+		next;
+		add_string "beta" "b";
+		next;
+		add_string "gamma" "c";
+		next;
+		add_string "delta" "d";
+		next;
+		add_string_array "order" "a" "b" "c" "d";
+	end;
+end;
+EOF)"
+
+complete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/json_common.ksh	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,30 @@
+#!/bin/ksh
+#
+# 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.
+#
+
+function complete {
+  if [[ "${PRINT_OUTPUT}" ]]; then
+    printf "%s\n" "${OUTPUT}"
+    exit 0
+  elif [[ "${OUTPUT}" == "${BASELINE}" ]]; then
+    printf "TEST PASS: %s\n" "$(basename $0)"
+    exit 0
+  else
+    printf "TEST FAIL: %s\n" "$(basename $0)"
+    printf "EXPECTED: %s\n" "${BASELINE}"
+    printf "ACTUAL:   %s\n" "${OUTPUT}"
+    exit 1
+  fi
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/util-tests/tests/libnvpair_json/print_json.c	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,827 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Joyent, Inc.
+ */
+
+/*
+ * This program implements a small domain-specific language (DSL) for the
+ * generation of nvlists, and subsequent printing in JSON-formatted output.
+ * The test suite uses this tool to drive the JSON formatting routines in
+ * libnvpair(3LIB) for testing.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <locale.h>
+
+#include <libnvpair.h>
+
+#define	MAX_ARGS	100
+#define	CMD_NAME_LEN	50
+
+/*
+ * As we are parsing a language that allows the creation of arbitrarily nested
+ * state, i.e. both nested nvlists and arrays of nested nvlists, we store that
+ * state in a stack.  The top frame in the stack represents the nested nvlist
+ * (or nvlists, for an array) that we are currently building.
+ *
+ * When creating an array, the "next" directive advances lw_pos and allocates a
+ * new nvlist.  The "end" directive commits either the nvlist, or array of
+ * nvlists, into the parent nvlist.  It then pops and frees the stack frame
+ * before returning control to the parser.
+ */
+
+typedef struct list_wrap {
+	nvlist_t *lw_nvl[MAX_ARGS];
+	char *lw_name;
+	int lw_pos;
+	boolean_t lw_array;
+	struct list_wrap *lw_next;
+} list_wrap_t;
+
+int
+list_wrap_depth(list_wrap_t *lw)
+{
+	int d = 0;
+
+	while (lw != NULL) {
+		d++;
+		lw = lw->lw_next;
+	}
+
+	return (d);
+}
+
+list_wrap_t *
+list_wrap_alloc(list_wrap_t *next)
+{
+	list_wrap_t *out = calloc(1, sizeof (list_wrap_t));
+
+	if (out == NULL)
+		abort();
+
+	out->lw_next = next;
+
+	return (out);
+}
+
+list_wrap_t *
+list_wrap_pop_and_free(list_wrap_t *lw)
+{
+	list_wrap_t *next = lw->lw_next;
+
+	free(lw->lw_name);
+	free(lw);
+
+	return (next);
+}
+
+/*
+ * Generic integer and floating point parsing routines:
+ */
+
+int
+parse_int(char *in, int64_t *val, int64_t min, int64_t max)
+{
+	int64_t t;
+	char *end = NULL;
+
+	errno = 0;
+	t = strtoll(in, &end, 10);
+	if (errno != 0 || end == in || *end != '\0') {
+		if (errno == ERANGE) {
+			(void) fprintf(stderr, "ERROR: integer %s not in "
+			    "range [%lld,%lld]\n", in, min, max);
+			return (-1);
+		}
+		(void) fprintf(stderr, "ERROR: could not parse \"%s\" as "
+		    "signed integer (%s)\n", in, strerror(errno));
+		return (-1);
+	}
+
+	if (t < min || t > max) {
+		(void) fprintf(stderr, "ERROR: integer %lld not in range "
+		    "[%lld,%lld]\n", t, min, max);
+		return (-1);
+	}
+
+	*val = t;
+	return (0);
+}
+
+int
+parse_uint(char *in, uint64_t *val, uint64_t min, uint64_t max)
+{
+	uint64_t t;
+	char *end = NULL;
+
+	errno = 0;
+	t = strtoull(in, &end, 10);
+	if (errno != 0 || end == in || *end != '\0') {
+		if (errno == ERANGE) {
+			(void) fprintf(stderr, "ERROR: integer %s not in "
+			    "range [%llu,%llu]\n", in, min, max);
+			return (-1);
+		}
+		(void) fprintf(stderr, "ERROR: could not parse \"%s\" as "
+		    "unsigned integer (%s)\n", in, strerror(errno));
+		return (-1);
+	}
+
+	if (t < min || t > max) {
+		(void) fprintf(stderr, "ERROR: integer %llu not in range "
+		    "[%llu,%llu]\n", t, min, max);
+		return (-1);
+	}
+
+	*val = t;
+	return (0);
+}
+
+int
+parse_double(char *in, double *val)
+{
+	double t;
+	char *end = NULL;
+
+	errno = 0;
+	t = strtod(in, &end);
+	if (errno != 0 || end == in || *end != '\0') {
+		(void) fprintf(stderr, "ERROR: could not parse \"%s\" as "
+		    "double\n", in);
+		return (-1);
+	}
+
+	*val = t;
+	return (0);
+}
+
+/*
+ * Command-specific handlers for directives specified in the DSL input:
+ */
+
+typedef int (*command_handler_t)(list_wrap_t **, boolean_t, int,
+    char **);
+
+static int
+ch_add_string(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	if (array) {
+		if (nvlist_add_string_array(nvl, argv[0], &argv[1],
+		    argc - 1) != 0) {
+			(void) fprintf(stderr, "fail at "
+			    "nvlist_add_string_array\n");
+			return (-1);
+		}
+	} else {
+		if (nvlist_add_string(nvl, argv[0], argv[1]) != 0) {
+			(void) fprintf(stderr, "fail at nvlist_add_string\n");
+			return (-1);
+		}
+	}
+
+	return (0);
+}
+
+static int
+ch_add_boolean(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	if (array)
+		abort();
+
+	if (nvlist_add_boolean(nvl, argv[0]) != 0) {
+		(void) fprintf(stderr, "fail at nvlist_add_boolean\n");
+		return (-1);
+	}
+	return (0);
+}
+
+static int
+ch_add_boolean_value(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	int i;
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+	boolean_t arrval[MAX_ARGS];
+
+	for (i = 1; i < argc; i++) {
+		if (strcmp(argv[i], "true") == 0) {
+			arrval[i - 1] = B_TRUE;
+		} else if (strcmp(argv[i], "false") == 0) {
+			arrval[i - 1] = B_FALSE;
+		} else {
+			(void) fprintf(stderr, "invalid boolean value: %s\n",
+			    argv[i]);
+			return (-1);
+		}
+	}
+
+	if (array) {
+		if (nvlist_add_boolean_array(nvl, argv[0], arrval,
+		    argc - 1) != 0) {
+			(void) fprintf(stderr, "fail at "
+			    "nvlist_add_boolean_array\n");
+			return (-1);
+		}
+	} else {
+		if (nvlist_add_boolean_value(nvl, argv[0], arrval[0]) != 0) {
+			(void) fprintf(stderr, "fail at "
+			    "nvlist_add_boolean_value\n");
+			return (-1);
+		}
+	}
+
+	return (0);
+}
+
+
+/*
+ * The confluence of a strongly typed C API for libnvpair(3LIB) and the
+ * combinatorial explosion of both sizes and signedness is unfortunate.  Rather
+ * than reproduce the same code over and over, this macro parses an integer,
+ * checks applicable bounds based on size and signedness, and stores the value
+ * (or array of values).
+ */
+#define	DO_CMD_NUMBER(typ, nam, min, max, ptyp, func)			\
+	ptyp val;							\
+	typ ## _t arrval[MAX_ARGS];					\
+	int i;								\
+	for (i = 1; i < argc; i++) {					\
+		if (func(argv[i], &val, min, max) != 0) {		\
+			return (-1);					\
+		}							\
+		arrval[i - 1] = (typ ## _t) val;			\
+	}								\
+	if (array) {							\
+		if (nvlist_add_ ## nam ## _array(nvl, argv[0],		\
+		    arrval, argc - 1) != 0) {				\
+			(void) fprintf(stderr, "fail at "		\
+			    "nvlist_add_" #nam "_array\n");		\
+			return (-1);					\
+		}							\
+	} else {							\
+		if (nvlist_add_ ## nam(nvl, argv[0],			\
+		    arrval[0]) == -1) {					\
+			(void) fprintf(stderr, "fail at "		\
+			    "nvlist_add_" #nam "\n");			\
+			return (-1);					\
+		}							\
+	}								\
+	return (0);
+
+static int
+ch_add_byte(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(uchar, byte, 0, UCHAR_MAX, uint64_t, parse_uint)
+}
+
+static int
+ch_add_int8(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(int8, int8, INT8_MIN, INT8_MAX, int64_t, parse_int)
+}
+
+static int
+ch_add_uint8(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(uint8, uint8, 0, UINT8_MAX, uint64_t, parse_uint)
+}
+
+static int
+ch_add_int16(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(int16, int16, INT16_MIN, INT16_MAX, int64_t, parse_int)
+}
+
+static int
+ch_add_uint16(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(uint16, uint16, 0, UINT16_MAX, uint64_t, parse_uint)
+}
+
+static int
+ch_add_int32(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(int32, int32, INT32_MIN, INT32_MAX, int64_t, parse_int)
+}
+
+static int
+ch_add_uint32(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(uint32, uint32, 0, UINT32_MAX, uint64_t, parse_uint)
+}
+
+static int
+ch_add_int64(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(int64, int64, INT64_MIN, INT64_MAX, int64_t, parse_int)
+}
+
+static int
+ch_add_uint64(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+
+	DO_CMD_NUMBER(uint64, uint64, 0, UINT64_MAX, uint64_t, parse_uint)
+}
+
+static int
+ch_add_double(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *nvl = (*lw)->lw_nvl[(*lw)->lw_pos];
+	double val;
+
+	if (array)
+		abort();
+
+	if (parse_double(argv[1], &val) != 0) {
+		return (-1);
+	}
+
+	if (nvlist_add_double(nvl, argv[0], val) != 0) {
+		(void) fprintf(stderr, "fail at nvlist_add_double_value\n");
+		return (-1);
+	}
+
+	return (0);
+}
+
+static int
+ch_end(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	nvlist_t *parent;
+	char *name;
+
+	if (list_wrap_depth(*lw) < 2) {
+		(void) fprintf(stderr, "ERROR: not nested, cannot end.\n");
+		return (-1);
+	}
+
+	parent = (*lw)->lw_next->lw_nvl[(*lw)->lw_next->lw_pos];
+	name = (*lw)->lw_name;
+	if ((*lw)->lw_array) {
+		/*
+		 * This was an array of objects.
+		 */
+		nvlist_t **children = (*lw)->lw_nvl;
+		int nelems = (*lw)->lw_pos + 1;
+
+		if (nvlist_add_nvlist_array(parent, name, children,
+		    nelems) != 0) {
+			(void) fprintf(stderr, "fail at "
+			    "nvlist_add_nvlist_array\n");
+			return (-1);
+		}
+	} else {
+		/*
+		 * This was a single object.
+		 */
+		nvlist_t *child = (*lw)->lw_nvl[0];
+
+		if ((*lw)->lw_pos != 0)
+			abort();
+
+		if (nvlist_add_nvlist(parent, name, child) != 0) {
+			(void) fprintf(stderr, "fail at nvlist_add_nvlist\n");
+			return (-1);
+		}
+	}
+
+	*lw = list_wrap_pop_and_free(*lw);
+
+	return (0);
+}
+
+static int
+ch_next(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	if (!(*lw)->lw_array) {
+		(void) fprintf(stderr, "ERROR: cannot use 'next' outside an "
+		    "object array.\n");
+		return (-1);
+	}
+
+	if ((*lw)->lw_pos++ >= MAX_ARGS) {
+		(void) fprintf(stderr, "ERROR: object array too long\n");
+		return (-1);
+	}
+
+	if (nvlist_alloc(&(*lw)->lw_nvl[(*lw)->lw_pos], NV_UNIQUE_NAME,
+	    0) != 0) {
+		(void) fprintf(stderr, "ERROR: failed at nvlist_alloc\n");
+		return (-1);
+	}
+
+	return (0);
+}
+
+static int
+ch_add_object(list_wrap_t **lw, boolean_t array, int argc, char **argv)
+{
+	*lw = list_wrap_alloc(*lw);
+
+	(*lw)->lw_name = strdup(argv[0]);
+	(*lw)->lw_array = array;
+
+	if (nvlist_alloc(&(*lw)->lw_nvl[0], NV_UNIQUE_NAME, 0) != 0) {
+		(void) fprintf(stderr, "fail at nvlist_alloc\n");
+		return (-1);
+	}
+
+	return (0);
+}
+
+typedef struct command {
+	char cmd_name[CMD_NAME_LEN];
+	command_handler_t cmd_func;
+	int cmd_min_args;
+	int cmd_max_args;
+	boolean_t cmd_array_mode;
+} command_t;
+
+/*
+ * These are the commands we support in the testing DSL, and their
+ * handling functions:
+ */
+command_t command_handlers[] = {
+	{ "add_boolean", ch_add_boolean, 1, 1, B_FALSE },
+	{ "add_boolean_value", ch_add_boolean_value, 2, 2, B_FALSE },
+	{ "add_byte", ch_add_byte, 2, 2, B_FALSE },
+	{ "add_int8", ch_add_int8, 2, 2, B_FALSE },
+	{ "add_uint8", ch_add_uint8, 2, 2, B_FALSE },
+	{ "add_int16", ch_add_int16, 2, 2, B_FALSE },
+	{ "add_uint16", ch_add_uint16, 2, 2, B_FALSE },
+	{ "add_int32", ch_add_int32, 2, 2, B_FALSE },
+	{ "add_uint32", ch_add_uint32, 2, 2, B_FALSE },
+	{ "add_int64", ch_add_int64, 2, 2, B_FALSE },
+	{ "add_uint64", ch_add_uint64, 2, 2, B_FALSE },
+	{ "add_double", ch_add_double, 2, 2, B_FALSE },
+	{ "add_string", ch_add_string, 2, 2, B_FALSE },
+	{ "add_object", ch_add_object, 1, 1, B_FALSE },
+	{ "add_boolean_array", ch_add_boolean_value, 1, MAX_ARGS, B_TRUE },
+	{ "add_byte_array", ch_add_byte, 1, MAX_ARGS, B_TRUE },
+	{ "add_int8_array", ch_add_int8, 1, MAX_ARGS, B_TRUE },
+	{ "add_uint8_array", ch_add_uint8, 1, MAX_ARGS, B_TRUE },
+	{ "add_int16_array", ch_add_int16, 1, MAX_ARGS, B_TRUE },
+	{ "add_uint16_array", ch_add_uint16, 1, MAX_ARGS, B_TRUE },
+	{ "add_int32_array", ch_add_int32, 1, MAX_ARGS, B_TRUE },
+	{ "add_uint32_array", ch_add_uint32, 1, MAX_ARGS, B_TRUE },
+	{ "add_int64_array", ch_add_int64, 1, MAX_ARGS, B_TRUE },
+	{ "add_uint64_array", ch_add_uint64, 1, MAX_ARGS, B_TRUE },
+	{ "add_string_array", ch_add_string, 1, MAX_ARGS, B_TRUE },
+	{ "add_object_array", ch_add_object, 1, 1, B_TRUE },
+	{ "end", ch_end, 0, 0, B_FALSE },
+	{ "next", ch_next, 0, 0, B_FALSE },
+	{ 0 }
+};
+
+/*
+ * This function determines which command we are executing, checks argument
+ * counts, and dispatches to the appropriate handler:
+ */
+static int
+command_call(list_wrap_t **lw, char *command, int argc, char **argv)
+{
+	int ch;
+
+	for (ch = 0; command_handlers[ch].cmd_name[0] != '\0'; ch++) {
+		if (strcmp(command, command_handlers[ch].cmd_name) != 0)
+			continue;
+
+		if (argc > command_handlers[ch].cmd_max_args ||
+		    argc < command_handlers[ch].cmd_min_args) {
+
+			(void) fprintf(stderr, "ERROR: command \"%s\""
+			    " expects between %d and %d arguments,"
+			    " but %d were provided.\n", command,
+			    command_handlers[ch].cmd_min_args,
+			    command_handlers[ch].cmd_max_args,
+			    argc);
+
+			return (-1);
+		}
+
+		return (command_handlers[ch].cmd_func(lw,
+		    command_handlers[ch].cmd_array_mode, argc, argv));
+	}
+
+	(void) fprintf(stderr, "ERROR: invalid command: \"%s\"\n", command);
+
+	return (-1);
+}
+
+/*
+ * The primary state machine for parsing the input DSL is implemented in
+ * this function:
+ */
+
+typedef enum state {
+	STATE_REST = 1,
+	STATE_COMMAND,
+	STATE_ARG_FIND,
+	STATE_ARG,
+	STATE_ARG_ESCAPE,
+	STATE_ARG_ESCAPE_HEX,
+	STATE_C_COMMENT_0,
+	STATE_C_COMMENT_1,
+	STATE_C_COMMENT_2
+} state_t;
+
+int
+parse(FILE *in, list_wrap_t **lw)
+{
+	char b[8192];
+	int bp;
+	state_t st = STATE_REST;
+	int argc = 0;
+	char *argv[MAX_ARGS];
+	int line = 1;
+	char hex[3];
+	int nhex = 0;
+
+	b[0] = '\0';
+	bp = 0;
+
+	for (;;) {
+		int c = fgetc(in);
+
+		/*
+		 * Signal an error if the file ends part way through a
+		 * construct:
+		 */
+		if (st != STATE_REST && c == EOF) {
+			(void) fprintf(stderr, "ERROR: unexpected end of "
+			    "file\n");
+			return (-1);
+		} else if (c == EOF) {
+			return (0);
+		}
+
+		if (c == '\n')
+			line++;
+
+		switch (st) {
+		case STATE_REST:
+			if (isalpha(c) || c == '_') {
+				argc = 0;
+				bp = 0;
+				b[bp++] = c;
+				b[bp] = '\0';
+				st = STATE_COMMAND;
+				continue;
+			} else if (c == ' ' || c == '\t' || c == '\n') {
+				/*
+				 * Ignore whitespace.
+				 */
+				continue;
+			} else if (c == '/') {
+				st = STATE_C_COMMENT_0;
+				continue;
+			} else {
+				goto unexpected;
+			}
+
+		case STATE_C_COMMENT_0:
+			if (c != '*') {
+				goto unexpected;
+			}
+			st = STATE_C_COMMENT_1;
+			continue;
+
+		case STATE_C_COMMENT_1:
+			if (c == '*') {
+				st = STATE_C_COMMENT_2;
+			}
+			continue;
+
+		case STATE_C_COMMENT_2:
+			if (c == '/') {
+				st = STATE_REST;
+			} else if (c != '*') {
+				st = STATE_C_COMMENT_1;
+			}
+			continue;
+
+		case STATE_COMMAND:
+			if (isalnum(c) || c == '_') {
+				b[bp++] = c;
+				b[bp] = '\0';
+				st = STATE_COMMAND;
+
+				continue;
+
+			} else if (isspace(c)) {
+				/*
+				 * Start collecting arguments into 'b'
+				 * after the command.
+				 */
+				st = STATE_ARG_FIND;
+				bp++;
+
+				continue;
+			} else if (c == ';') {
+				/*
+				 * This line was _just_ a command,
+				 * so break out and process now:
+				 */
+				goto execute;
+			} else {
+				goto unexpected;
+			}
+
+		case STATE_ARG_FIND:
+			if (isspace(c)) {
+				/*
+				 * Whitespace, ignore.
+				 */
+				continue;
+
+			} else if (c == ';') {
+				/*
+				 * Break out to process command.
+				 */
+				goto execute;
+
+			} else if (c == '"') {
+				st = STATE_ARG;
+
+				argv[argc] = &b[++bp];
+				b[bp] = '\0';
+
+				continue;
+			} else {
+				goto unexpected;
+			}
+
+		case STATE_ARG:
+			if (c == '"') {
+				if (argc++ >= MAX_ARGS) {
+					(void) fprintf(stderr, "ERROR: too "
+					    "many args\n");
+					return (-1);
+				}
+				st = STATE_ARG_FIND;
+				continue;
+			} else if (c == '\n') {
+				(void) fprintf(stderr, "ERROR: line not "
+				    "finished\n");
+				return (-1);
+			} else if (c == '\\') {
+				st = STATE_ARG_ESCAPE;
+				continue;
+			} else {
+				b[bp++] = c;
+				b[bp] = '\0';
+				continue;
+			}
+
+		case STATE_ARG_ESCAPE:
+			if (c == 'a') {
+				c = '\a';
+			} else if (c == 'b') {
+				c = '\b';
+			} else if (c == 'f') {
+				c = '\f';
+			} else if (c == 'n') {
+				c = '\n';
+			} else if (c == 'r') {
+				c = '\r';
+			} else if (c == 't') {
+				c = '\t';
+			} else if (c == 'v') {
+				c = '\v';
+			} else if (c == 'x') {
+				st = STATE_ARG_ESCAPE_HEX;
+				hex[0] = hex[1] = hex[2] = '\0';
+				nhex = 0;
+				continue;
+			} else if (c != '\\' && c != '"') {
+				goto unexpected;
+			}
+
+			b[bp++] = c;
+			b[bp] = '\0';
+			st = STATE_ARG;
+			continue;
+
+		case STATE_ARG_ESCAPE_HEX:
+			if (!isxdigit(c)) {
+				goto unexpected;
+			}
+			hex[nhex] = c;
+			if (nhex++ >= 1) {
+				/*
+				 * The hex escape pair is complete, parse
+				 * the integer and insert it as a character:
+				 */
+				int x;
+				errno = 0;
+				if ((x = strtol(hex, NULL, 16)) == 0 ||
+				    errno != 0) {
+					goto unexpected;
+				}
+				b[bp++] = (char)x;
+				b[bp] = '\0';
+				st = STATE_ARG;
+			}
+			continue;
+		}
+
+		/*
+		 * We do not ever expect to break out of the switch block
+		 * above.  If we do, it's a programmer error.
+		 */
+		abort();
+
+execute:
+		if (command_call(lw, b, argc, argv) == -1)
+			return (-1);
+
+		st = STATE_REST;
+		continue;
+
+unexpected:
+		(void) fprintf(stderr, "ERROR: (line %d) unexpected "
+		    "character: %c\n", line, c);
+		return (-1);
+	}
+}
+
+/*
+ * Entry point:
+ */
+int
+main(int argc, char **argv)
+{
+	int rc = EXIT_FAILURE;
+	list_wrap_t *lw;
+
+	/*
+	 * Be locale-aware.  The JSON output functions will process multibyte
+	 * characters in the current locale, and emit a correct JSON encoding
+	 * for unprintable characters.
+	 */
+	if (setlocale(LC_ALL, "") == NULL) {
+		(void) fprintf(stderr, "Could not set locale: %s\n",
+		    strerror(errno));
+		goto out;
+	}
+
+	lw = list_wrap_alloc(NULL);
+
+	if (nvlist_alloc(&lw->lw_nvl[0], NV_UNIQUE_NAME, 0) != 0)
+		goto out;
+
+	/*
+	 * Generate the list from the commands passed to us on stdin:
+	 */
+	if (parse(stdin, &lw) != 0)
+		goto out;
+
+	/*
+	 * Print the resultant list, and a terminating newline:
+	 */
+	if (nvlist_print_json(stdout, lw->lw_nvl[0]) != 0 ||
+	    fprintf(stdout, "\n") < 0)
+		goto out;
+
+	rc = EXIT_SUCCESS;
+
+out:
+	(void) list_wrap_pop_and_free(lw);
+
+	return (rc);
+}
--- a/usr/src/tools/ctf/cvt/ctftools.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/tools/ctf/cvt/ctftools.h	Wed Nov 12 04:51:53 2014 -0800
@@ -26,8 +26,6 @@
 #ifndef _CTFTOOLS_H
 #define	_CTFTOOLS_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Functions and data structures used in the manipulation of stabs and CTF data
  */
@@ -39,6 +37,8 @@
 #include <gelf.h>
 #include <pthread.h>
 
+#include <sys/ccompile.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -434,8 +434,8 @@
 int findelfsecidx(Elf *, const char *, const char *);
 size_t elf_ptrsz(Elf *);
 char *mktmpname(const char *, const char *);
-void terminate(char *, ...);
-void aborterr(char *, ...);
+void terminate(char *, ...) __NORETURN;
+void aborterr(char *, ...) __NORETURN;
 void set_terminate_cleanup(void (*)());
 void elfterminate(const char *, const char *, ...);
 void warning(char *, ...);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/tools/onbld/Scm/Ignore.py	Wed Nov 12 04:51:53 2014 -0800
@@ -0,0 +1,91 @@
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE
+#
+# Copyright (c) 2014, Joyent, Inc.
+#
+
+'''
+Process our ignore/exception_list file format.
+
+The format is broadly similar, if not identical, to .gitignore and .hgignore
+files.
+'''
+
+import re
+import fnmatch
+
+RE_SYNTAX = re.compile(r'^syntax:\s*(.*)\s*$')
+
+#
+# It is important that this module not rely on Mercurial
+#
+
+def _read_ignore_file(ignorefile):
+    '''Read an ignore file and return an array of regular expressions
+    to match ignored paths.'''
+
+    syntax = 'regex'
+    ignore_list = []
+    lc = 0
+
+    with open(ignorefile, 'r') as f:
+        for l in f:
+            lc += 1
+            # Remove comments and blank lines
+            l = l.split('#', 2)[0].strip()
+            if l == '':
+                continue
+            # Process "syntax:" lines
+            m = RE_SYNTAX.match(l)
+            if m:
+                syntax = m.group(1)
+                continue
+            # All other lines are considered patterns
+            if (syntax == 'glob'):
+                ignore_list.append(re.compile('.*' + fnmatch.translate(l)))
+            elif (syntax == 'regex'):
+                ignore_list.append(re.compile(l))
+            else:
+                raise Exception('%s:%d: syntax "%s" is not supported' %
+                    (ignorefile, lc, syntax))
+
+    return ignore_list
+
+def ignore(root, ignorefiles):
+    # If we aren't provided any ignore files, we'll never ignore
+    # any paths:
+    if (len(ignorefiles) < 1):
+        return lambda x: False
+
+    ignore_list = []
+    for ignorefile in ignorefiles:
+        ignore_list.extend(_read_ignore_file(ignorefile))
+
+    # If the ignore files contained no patterns, we'll never ignore
+    # any paths:
+    if (len(ignore_list) < 1):
+        return lambda x: False
+
+    def _ignore_func(path):
+        for regex in ignore_list:
+            if (regex.match(path)):
+                return True
+        return False
+
+    return _ignore_func
--- a/usr/src/tools/onbld/Scm/Makefile	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/tools/onbld/Scm/Makefile	Wed Nov 12 04:51:53 2014 -0800
@@ -21,6 +21,7 @@
 
 #
 # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, Joyent, Inc.
 #
 
 include $(SRC)/Makefile.master
@@ -29,6 +30,7 @@
 PYSRCS = \
 	__init__.py	\
 	Backup.py	\
+	Ignore.py	\
 	Version.py	\
 	WorkSpace.py
 
--- a/usr/src/tools/onbld/hgext/cdm.py	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/tools/onbld/hgext/cdm.py	Wed Nov 12 04:51:53 2014 -0800
@@ -17,6 +17,7 @@
 # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 # Copyright 2008, 2011 Richard Lowe
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright (c) 2014, Joyent, Inc.
 #
 
 '''OpenSolaris extensions to Mercurial
@@ -93,6 +94,7 @@
 sys.path.insert(2, os.path.join(os.path.dirname(__file__), "..", ".."))
 
 from onbld.Scm import Version
+from onbld.Scm import Ignore
 from mercurial import util
 
 try:
@@ -100,7 +102,7 @@
 except Version.VersionMismatch, badversion:
     raise util.Abort("Version Mismatch:\n %s\n" % badversion)
 
-from mercurial import cmdutil, ignore, node, patch
+from mercurial import cmdutil, node, patch
 
 from onbld.Scm.WorkSpace import WorkSpace, WorkList
 from onbld.Scm.Backup import CdmBackup
@@ -168,7 +170,7 @@
             ignorefiles.append(f)
 
     if ignorefiles:
-        ign = ignore.ignore(repo.root, ignorefiles, repo.ui.warn)
+        ign = Ignore.ignore(repo.root, ignorefiles)
         return canonified_check(ign)
     else:
         return util.never
--- a/usr/src/tools/scripts/git-pbchk.py	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/tools/scripts/git-pbchk.py	Wed Nov 12 04:51:53 2014 -0800
@@ -18,6 +18,7 @@
 # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 # Copyright 2008, 2012 Richard Lowe
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright (c) 2014, Joyent, Inc.
 #
 
 import getopt
@@ -29,10 +30,6 @@
 
 from cStringIO import StringIO
 
-# This is necessary because, in a fit of pique, we used hg-format ignore lists
-# for NOT files.
-from mercurial import ignore
-
 #
 # Adjust the load path based on our location and the version of python into
 # which it is being loaded.  This assumes the normal onbld directory
@@ -48,6 +45,7 @@
 #
 sys.path.insert(2, os.path.join(os.path.dirname(__file__), ".."))
 
+from onbld.Scm import Ignore
 from onbld.Checks import Comments, Copyright, CStyle, HdrChk
 from onbld.Checks import JStyle, Keywords, ManLint, Mapfile
 
@@ -178,10 +176,7 @@
     ignorefiles = filter(os.path.exists,
                          [os.path.join(root, ".git", "%s.NOT" % cmd),
                           os.path.join(root, "exception_lists", cmd)])
-    if len(ignorefiles) > 0:
-        return ignore.ignore(root, ignorefiles, sys.stderr.write)
-    else:
-        return lambda x: False
+    return Ignore.ignore(root, ignorefiles)
 
 
 def gen_files(root, parent, paths, exclude):
--- a/usr/src/uts/common/cpr/cpr_main.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/cpr/cpr_main.c	Wed Nov 12 04:51:53 2014 -0800
@@ -90,7 +90,6 @@
 int curthreadremapped;
 
 extern cpuset_t cpu_ready_set;
-extern void *(*cpu_pause_func)(void *);
 
 extern processorid_t i_cpr_bootcpuid(void);
 extern cpu_t *i_cpr_bootcpu(void);
@@ -416,8 +415,7 @@
 	/*
 	 * pause all other running CPUs and save the CPU state at the sametime
 	 */
-	cpu_pause_func = i_cpr_save_context;
-	pause_cpus(NULL);
+	pause_cpus(NULL, i_cpr_save_context);
 
 	mutex_exit(&cpu_lock);
 
@@ -792,12 +790,6 @@
 
 	mutex_enter(&cpu_lock);
 	/*
-	 * Restore this cpu to use the regular cpu_pause(), so that
-	 * online and offline will work correctly
-	 */
-	cpu_pause_func = NULL;
-
-	/*
 	 * clear the affinity set in cpr_suspend_cpus()
 	 */
 	affinity_clear();
@@ -820,13 +812,6 @@
 	PMD(PMD_SX, ("cpr_unpause_cpus: restoring system\n"))
 
 	mutex_enter(&cpu_lock);
-
-	/*
-	 * Restore this cpu to use the regular cpu_pause(), so that
-	 * online and offline will work correctly
-	 */
-	cpu_pause_func = NULL;
-
 	/*
 	 * Restart the paused cpus
 	 */
@@ -1094,7 +1079,7 @@
 	 */
 	if (cpr_resume_uniproc) {
 		mutex_enter(&cpu_lock);
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 		mutex_exit(&cpu_lock);
 	}
 #endif
--- a/usr/src/uts/common/disp/cmt.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/disp/cmt.c	Wed Nov 12 04:51:53 2014 -0800
@@ -355,7 +355,7 @@
 	 * We're changing around the hierarchy, which is actively traversed
 	 * by the dispatcher. Pause CPUS to ensure exclusivity.
 	 */
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 
 	/*
 	 * If necessary, update the parent's sibling set, replacing parent
@@ -1555,7 +1555,7 @@
 	 * We're operating on the PG hierarchy. Pause CPUs to ensure
 	 * exclusivity with respect to the dispatcher.
 	 */
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 
 	/*
 	 * Prune all PG instances of the hardware sharing relationship
@@ -1675,7 +1675,7 @@
 
 	ASSERT(MUTEX_HELD(&cpu_lock));
 
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	cpu = cpu_list;
 
 	do {
--- a/usr/src/uts/common/disp/cpupart.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/disp/cpupart.c	Wed Nov 12 04:51:53 2014 -0800
@@ -441,7 +441,7 @@
 		return (EBUSY);
 	}
 
-	pause_cpus(cp);
+	pause_cpus(cp, NULL);
 
 	if (move_threads) {
 		/*
@@ -865,7 +865,7 @@
 	 * the clock thread (which traverses the list without holding
 	 * cpu_lock) isn't running.
 	 */
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	pp->cp_next = cp_list_head;
 	pp->cp_prev = cp_list_head->cp_prev;
 	cp_list_head->cp_prev->cp_next = pp;
@@ -1011,7 +1011,7 @@
 	 * the clock thread (which traverses the list without holding
 	 * cpu_lock) isn't running.
 	 */
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	pp->cp_prev->cp_next = pp->cp_next;
 	pp->cp_next->cp_prev = pp->cp_prev;
 	if (cp_list_head == pp)
--- a/usr/src/uts/common/disp/disp.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/disp/disp.c	Wed Nov 12 04:51:53 2014 -0800
@@ -340,7 +340,7 @@
 	} while (cpup != cpu_list);
 	num = i;
 
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	for (i = 0; i < num; i++)
 		disp_dq_assign(&disp_mem[i], numpris);
 	start_cpus();
--- a/usr/src/uts/common/dtrace/dtrace.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/dtrace/dtrace.c	Wed Nov 12 04:51:53 2014 -0800
@@ -13039,7 +13039,7 @@
 		if (!(sec->dofs_flags & DOF_SECF_LOAD))
 			continue; /* just ignore non-loadable sections */
 
-		if (sec->dofs_align & (sec->dofs_align - 1)) {
+		if (!ISP2(sec->dofs_align)) {
 			dtrace_dof_error(dof, "bad section alignment");
 			return (-1);
 		}
--- a/usr/src/uts/common/dtrace/fasttrap.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/dtrace/fasttrap.c	Wed Nov 12 04:51:53 2014 -0800
@@ -2156,7 +2156,7 @@
 	if (nent == 0 || nent > 0x1000000)
 		nent = FASTTRAP_TPOINTS_DEFAULT_SIZE;
 
-	if ((nent & (nent - 1)) == 0)
+	if (ISP2(nent))
 		fasttrap_tpoints.fth_nent = nent;
 	else
 		fasttrap_tpoints.fth_nent = 1 << fasttrap_highbit(nent);
@@ -2169,7 +2169,7 @@
 	 * ... and the providers hash table...
 	 */
 	nent = FASTTRAP_PROVIDERS_DEFAULT_SIZE;
-	if ((nent & (nent - 1)) == 0)
+	if (ISP2(nent))
 		fasttrap_provs.fth_nent = nent;
 	else
 		fasttrap_provs.fth_nent = 1 << fasttrap_highbit(nent);
@@ -2182,7 +2182,7 @@
 	 * ... and the procs hash table.
 	 */
 	nent = FASTTRAP_PROCS_DEFAULT_SIZE;
-	if ((nent & (nent - 1)) == 0)
+	if (ISP2(nent))
 		fasttrap_procs.fth_nent = nent;
 	else
 		fasttrap_procs.fth_nent = 1 << fasttrap_highbit(nent);
--- a/usr/src/uts/common/fs/dcfs/dc_vnops.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/dcfs/dc_vnops.c	Wed Nov 12 04:51:53 2014 -0800
@@ -948,8 +948,7 @@
 	if (error || hdr->ch_magic != CH_MAGIC_ZLIB ||
 	    hdr->ch_version != CH_VERSION || hdr->ch_algorithm != CH_ALG_ZLIB ||
 	    hdr->ch_fsize == 0 || hdr->ch_blksize < PAGESIZE ||
-	    hdr->ch_blksize > ptob(DCCACHESIZE) ||
-	    (hdr->ch_blksize & (hdr->ch_blksize - 1)) != 0)
+	    hdr->ch_blksize > ptob(DCCACHESIZE) || !ISP2(hdr->ch_blksize))
 		return (NULL);
 
 	/* get underlying file size */
--- a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c	Wed Nov 12 04:51:53 2014 -0800
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -188,7 +189,6 @@
 #include <sys/strsubr.h>
 #include <sys/socketvar.h>
 #include <sys/socket.h>
-#include <sys/random.h>
 #include <netinet/in.h>
 #include <smbsrv/smb_kproto.h>
 #include <smbsrv/smbinfo.h>
@@ -229,7 +229,6 @@
 static uint32_t	smb_dos_tcp_rcvbuf = 8700;
 static uint32_t	smb_nt_tcp_rcvbuf = 1048560;	/* scale factor of 4 */
 
-static void smb_negotiate_genkey(smb_request_t *);
 static int smb_xlate_dialect(const char *);
 
 int smb_cap_passthru = 1;
@@ -303,13 +302,13 @@
 	sr->session->secmode = NEGOTIATE_SECURITY_CHALLENGE_RESPONSE |
 	    NEGOTIATE_SECURITY_USER_LEVEL;
 	secmode = sr->session->secmode;
-
-	smb_negotiate_genkey(sr);
 	sesskey = sr->session->sesskey;
 
 	(void) microtime(&negprot->ni_servertime);
 	negprot->ni_tzcorrection = sr->sr_gmtoff / 60;
 	negprot->ni_maxmpxcount = sr->sr_cfg->skc_maxworkers;
+	negprot->ni_keylen = SMB_CHALLENGE_SZ;
+	bcopy(&sr->session->challenge_key, negprot->ni_key, SMB_CHALLENGE_SZ);
 	nbdomain = sr->sr_cfg->skc_nbdomain;
 
 	/*
@@ -484,23 +483,6 @@
 	return (SDRC_SUCCESS);
 }
 
-static void
-smb_negotiate_genkey(smb_request_t *sr)
-{
-	smb_arg_negotiate_t	*negprot = sr->sr_negprot;
-	uint8_t			tmp_key[8];
-
-	(void) random_get_pseudo_bytes(tmp_key, 8);
-	bcopy(tmp_key, &sr->session->challenge_key, 8);
-	sr->session->challenge_len = 8;
-	negprot->ni_keylen = 8;
-	bcopy(tmp_key, negprot->ni_key, 8);
-
-	(void) random_get_pseudo_bytes(tmp_key, 4);
-	sr->session->sesskey = tmp_key[0] | tmp_key[1] << 8 |
-	    tmp_key[2] << 16 | tmp_key[3] << 24;
-}
-
 static int
 smb_xlate_dialect(const char *dialect)
 {
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c	Wed Nov 12 04:51:53 2014 -0800
@@ -28,6 +28,7 @@
 #include <sys/types.h>
 #include <sys/socketvar.h>
 #include <sys/sdt.h>
+#include <sys/random.h>
 #include <smbsrv/netbios.h>
 #include <smbsrv/smb_kproto.h>
 #include <smbsrv/string.h>
@@ -45,6 +46,7 @@
 static void smb_session_logoff(smb_session_t *);
 static void smb_request_init_command_mbuf(smb_request_t *sr);
 void dump_smb_inaddr(smb_inaddr_t *ipaddr);
+static void smb_session_genkey(smb_session_t *);
 
 void
 smb_session_timers(smb_llist_t *ll)
@@ -643,6 +645,8 @@
 	session->keep_alive = smb_keep_alive;
 	session->activity_timestamp = now;
 
+	smb_session_genkey(session);
+
 	smb_slist_constructor(&session->s_req_list, sizeof (smb_request_t),
 	    offsetof(smb_request_t, sr_session_lnd));
 
@@ -1214,3 +1218,17 @@
 	}
 	smb_rwx_rwexit(&session->s_lock);
 }
+
+static void
+smb_session_genkey(smb_session_t *session)
+{
+	uint8_t		tmp_key[SMB_CHALLENGE_SZ];
+
+	(void) random_get_pseudo_bytes(tmp_key, SMB_CHALLENGE_SZ);
+	bcopy(tmp_key, &session->challenge_key, SMB_CHALLENGE_SZ);
+	session->challenge_len = SMB_CHALLENGE_SZ;
+
+	(void) random_get_pseudo_bytes(tmp_key, 4);
+	session->sesskey = tmp_key[0] | tmp_key[1] << 8 |
+	    tmp_key[2] << 16 | tmp_key[3] << 24;
+}
--- a/usr/src/uts/common/fs/zfs/bpobj.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/bpobj.c	Wed Nov 12 04:51:53 2014 -0800
@@ -43,7 +43,7 @@
 		if (!spa_feature_is_active(spa, SPA_FEATURE_EMPTY_BPOBJ)) {
 			ASSERT0(dp->dp_empty_bpobj);
 			dp->dp_empty_bpobj =
-			    bpobj_alloc(os, SPA_MAXBLOCKSIZE, tx);
+			    bpobj_alloc(os, SPA_OLD_MAXBLOCKSIZE, tx);
 			VERIFY(zap_add(os,
 			    DMU_POOL_DIRECTORY_OBJECT,
 			    DMU_POOL_EMPTY_BPOBJ, sizeof (uint64_t), 1,
@@ -396,7 +396,8 @@
 	dmu_buf_will_dirty(bpo->bpo_dbuf, tx);
 	if (bpo->bpo_phys->bpo_subobjs == 0) {
 		bpo->bpo_phys->bpo_subobjs = dmu_object_alloc(bpo->bpo_os,
-		    DMU_OT_BPOBJ_SUBOBJ, SPA_MAXBLOCKSIZE, DMU_OT_NONE, 0, tx);
+		    DMU_OT_BPOBJ_SUBOBJ, SPA_OLD_MAXBLOCKSIZE,
+		    DMU_OT_NONE, 0, tx);
 	}
 
 	dmu_object_info_t doi;
--- a/usr/src/uts/common/fs/zfs/bptree.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/bptree.c	Wed Nov 12 04:51:53 2014 -0800
@@ -65,7 +65,7 @@
 	bptree_phys_t *bt;
 
 	obj = dmu_object_alloc(os, DMU_OTN_UINT64_METADATA,
-	    SPA_MAXBLOCKSIZE, DMU_OTN_UINT64_METADATA,
+	    SPA_OLD_MAXBLOCKSIZE, DMU_OTN_UINT64_METADATA,
 	    sizeof (bptree_phys_t), tx);
 
 	/*
--- a/usr/src/uts/common/fs/zfs/dbuf.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dbuf.c	Wed Nov 12 04:51:53 2014 -0800
@@ -2022,10 +2022,8 @@
 		return (SET_ERROR(ENOTSUP));
 	if (blksz == 0)
 		blksz = SPA_MINBLOCKSIZE;
-	if (blksz > SPA_MAXBLOCKSIZE)
-		blksz = SPA_MAXBLOCKSIZE;
-	else
-		blksz = P2ROUNDUP(blksz, SPA_MINBLOCKSIZE);
+	ASSERT3U(blksz, <=, spa_maxblocksize(dmu_objset_spa(db->db_objset)));
+	blksz = P2ROUNDUP(blksz, SPA_MINBLOCKSIZE);
 
 	DB_DNODE_ENTER(db);
 	dn = DB_DNODE(db);
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c	Wed Nov 12 04:51:53 2014 -0800
@@ -255,6 +255,14 @@
 		zil_set_logbias(os->os_zil, newval);
 }
 
+static void
+recordsize_changed_cb(void *arg, uint64_t newval)
+{
+	objset_t *os = arg;
+
+	os->os_recordsize = newval;
+}
+
 void
 dmu_objset_byteswap(void *buf, size_t size)
 {
@@ -384,6 +392,11 @@
 				    ZFS_PROP_REDUNDANT_METADATA),
 				    redundant_metadata_changed_cb, os);
 			}
+			if (err == 0) {
+				err = dsl_prop_register(ds,
+				    zfs_prop_to_name(ZFS_PROP_RECORDSIZE),
+				    recordsize_changed_cb, os);
+			}
 		}
 		if (err != 0) {
 			VERIFY(arc_buf_remove_ref(os->os_phys_buf,
@@ -642,6 +655,9 @@
 			VERIFY0(dsl_prop_unregister(ds,
 			    zfs_prop_to_name(ZFS_PROP_REDUNDANT_METADATA),
 			    redundant_metadata_changed_cb, os));
+			VERIFY0(dsl_prop_unregister(ds,
+			    zfs_prop_to_name(ZFS_PROP_RECORDSIZE),
+			    recordsize_changed_cb, os));
 		}
 		VERIFY0(dsl_prop_unregister(ds,
 		    zfs_prop_to_name(ZFS_PROP_PRIMARYCACHE),
--- a/usr/src/uts/common/fs/zfs/dmu_send.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dmu_send.c	Wed Nov 12 04:51:53 2014 -0800
@@ -206,11 +206,12 @@
 	drrw->drr_offset = offset;
 	drrw->drr_length = blksz;
 	drrw->drr_toguid = dsp->dsa_toguid;
-	if (BP_IS_EMBEDDED(bp)) {
+	if (bp == NULL || BP_IS_EMBEDDED(bp)) {
 		/*
-		 * There's no pre-computed checksum of embedded BP's, so
-		 * (like fletcher4-checkummed blocks) userland will have
-		 * to compute a dedup-capable checksum itself.
+		 * There's no pre-computed checksum for partial-block
+		 * writes or embedded BP's, so (like
+		 * fletcher4-checkummed blocks) userland will have to
+		 * compute a dedup-capable checksum itself.
 		 */
 		drrw->drr_checksumtype = ZIO_CHECKSUM_OFF;
 	} else {
@@ -372,6 +373,10 @@
 	drro->drr_compress = dnp->dn_compress;
 	drro->drr_toguid = dsp->dsa_toguid;
 
+	if (!(dsp->dsa_featureflags & DMU_BACKUP_FEATURE_LARGE_BLOCKS) &&
+	    drro->drr_blksz > SPA_OLD_MAXBLOCKSIZE)
+		drro->drr_blksz = SPA_OLD_MAXBLOCKSIZE;
+
 	if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0)
 		return (SET_ERROR(EINTR));
 
@@ -491,6 +496,7 @@
 		uint32_t aflags = ARC_WAIT;
 		arc_buf_t *abuf;
 		int blksz = BP_GET_LSIZE(bp);
+		uint64_t offset;
 
 		ASSERT3U(blksz, ==, dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
 		ASSERT0(zb->zb_level);
@@ -511,8 +517,24 @@
 			}
 		}
 
-		err = dump_write(dsp, type, zb->zb_object, zb->zb_blkid * blksz,
-		    blksz, bp, abuf->b_data);
+		offset = zb->zb_blkid * blksz;
+
+		if (!(dsp->dsa_featureflags &
+		    DMU_BACKUP_FEATURE_LARGE_BLOCKS) &&
+		    blksz > SPA_OLD_MAXBLOCKSIZE) {
+			char *buf = abuf->b_data;
+			while (blksz > 0 && err == 0) {
+				int n = MIN(blksz, SPA_OLD_MAXBLOCKSIZE);
+				err = dump_write(dsp, type, zb->zb_object,
+				    offset, n, NULL, buf);
+				offset += n;
+				buf += n;
+				blksz -= n;
+			}
+		} else {
+			err = dump_write(dsp, type, zb->zb_object,
+			    offset, blksz, bp, abuf->b_data);
+		}
 		(void) arc_buf_remove_ref(abuf, &abuf);
 	}
 
@@ -526,7 +548,7 @@
 static int
 dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds,
     zfs_bookmark_phys_t *fromzb, boolean_t is_clone, boolean_t embedok,
-    int outfd, vnode_t *vp, offset_t *off)
+    boolean_t large_block_ok, int outfd, vnode_t *vp, offset_t *off)
 {
 	objset_t *os;
 	dmu_replay_record_t *drr;
@@ -561,6 +583,8 @@
 	}
 #endif
 
+	if (large_block_ok && ds->ds_large_blocks)
+		featureflags |= DMU_BACKUP_FEATURE_LARGE_BLOCKS;
 	if (embedok &&
 	    spa_feature_is_active(dp->dp_spa, SPA_FEATURE_EMBEDDED_DATA)) {
 		featureflags |= DMU_BACKUP_FEATURE_EMBED_DATA;
@@ -656,7 +680,8 @@
 
 int
 dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap,
-    boolean_t embedok, int outfd, vnode_t *vp, offset_t *off)
+    boolean_t embedok, boolean_t large_block_ok,
+    int outfd, vnode_t *vp, offset_t *off)
 {
 	dsl_pool_t *dp;
 	dsl_dataset_t *ds;
@@ -690,18 +715,19 @@
 		zb.zbm_guid = fromds->ds_phys->ds_guid;
 		is_clone = (fromds->ds_dir != ds->ds_dir);
 		dsl_dataset_rele(fromds, FTAG);
-		err = dmu_send_impl(FTAG, dp, ds, &zb, is_clone, embedok,
-		    outfd, vp, off);
+		err = dmu_send_impl(FTAG, dp, ds, &zb, is_clone,
+		    embedok, large_block_ok, outfd, vp, off);
 	} else {
-		err = dmu_send_impl(FTAG, dp, ds, NULL, B_FALSE, embedok,
-		    outfd, vp, off);
+		err = dmu_send_impl(FTAG, dp, ds, NULL, B_FALSE,
+		    embedok, large_block_ok, outfd, vp, off);
 	}
 	dsl_dataset_rele(ds, FTAG);
 	return (err);
 }
 
 int
-dmu_send(const char *tosnap, const char *fromsnap, boolean_t embedok,
+dmu_send(const char *tosnap, const char *fromsnap,
+    boolean_t embedok, boolean_t large_block_ok,
     int outfd, vnode_t *vp, offset_t *off)
 {
 	dsl_pool_t *dp;
@@ -768,11 +794,11 @@
 			dsl_pool_rele(dp, FTAG);
 			return (err);
 		}
-		err = dmu_send_impl(FTAG, dp, ds, &zb, is_clone, embedok,
-		    outfd, vp, off);
+		err = dmu_send_impl(FTAG, dp, ds, &zb, is_clone,
+		    embedok, large_block_ok, outfd, vp, off);
 	} else {
-		err = dmu_send_impl(FTAG, dp, ds, NULL, B_FALSE, embedok,
-		    outfd, vp, off);
+		err = dmu_send_impl(FTAG, dp, ds, NULL, B_FALSE,
+		    embedok, large_block_ok, outfd, vp, off);
 	}
 	if (owned)
 		dsl_dataset_disown(ds, FTAG);
@@ -972,6 +998,15 @@
 	    !spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LZ4_COMPRESS))
 		return (SET_ERROR(ENOTSUP));
 
+	/*
+	 * The receiving code doesn't know how to translate large blocks
+	 * to smaller ones, so the pool must have the LARGE_BLOCKS
+	 * feature enabled if the stream has LARGE_BLOCKS.
+	 */
+	if ((featureflags & DMU_BACKUP_FEATURE_LARGE_BLOCKS) &&
+	    !spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS))
+		return (SET_ERROR(ENOTSUP));
+
 	error = dsl_dataset_hold(dp, tofs, FTAG, &ds);
 	if (error == 0) {
 		/* target fs already exists; recv into temp clone */
@@ -1097,6 +1132,13 @@
 	}
 	VERIFY0(dsl_dataset_own_obj(dp, dsobj, dmu_recv_tag, &newds));
 
+	if ((DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
+	    DMU_BACKUP_FEATURE_LARGE_BLOCKS) &&
+	    !newds->ds_large_blocks) {
+		dsl_dataset_activate_large_blocks_sync_impl(dsobj, tx);
+		newds->ds_large_blocks = B_TRUE;
+	}
+
 	dmu_buf_will_dirty(newds->ds_dbuf, tx);
 	newds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
 
@@ -1222,6 +1264,7 @@
 
 	/* some things will require 8-byte alignment, so everything must */
 	ASSERT0(len % 8);
+	ASSERT3U(len, <=, ra->bufsize);
 
 	while (done < len) {
 		ssize_t resid;
@@ -1361,7 +1404,7 @@
 	    drro->drr_compress >= ZIO_COMPRESS_FUNCTIONS ||
 	    P2PHASE(drro->drr_blksz, SPA_MINBLOCKSIZE) ||
 	    drro->drr_blksz < SPA_MINBLOCKSIZE ||
-	    drro->drr_blksz > SPA_MAXBLOCKSIZE ||
+	    drro->drr_blksz > spa_maxblocksize(dmu_objset_spa(os)) ||
 	    drro->drr_bonuslen > DN_MAX_BONUSLEN) {
 		return (SET_ERROR(EINVAL));
 	}
@@ -1634,7 +1677,7 @@
 	int err;
 
 	if (drrs->drr_length < SPA_MINBLOCKSIZE ||
-	    drrs->drr_length > SPA_MAXBLOCKSIZE)
+	    drrs->drr_length > spa_maxblocksize(dmu_objset_spa(os)))
 		return (SET_ERROR(EINVAL));
 
 	data = restore_read(ra, drrs->drr_length, NULL);
@@ -1721,7 +1764,7 @@
 	ra.cksum = drc->drc_cksum;
 	ra.vp = vp;
 	ra.voff = *voffp;
-	ra.bufsize = 1<<20;
+	ra.bufsize = SPA_MAXBLOCKSIZE;
 	ra.buf = kmem_alloc(ra.bufsize, KM_SLEEP);
 
 	/* these were verified in dmu_recv_begin */
--- a/usr/src/uts/common/fs/zfs/dmu_tx.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dmu_tx.c	Wed Nov 12 04:51:53 2014 -0800
@@ -224,7 +224,7 @@
 		return;
 
 	min_bs = SPA_MINBLOCKSHIFT;
-	max_bs = SPA_MAXBLOCKSHIFT;
+	max_bs = highbit64(txh->txh_tx->tx_objset->os_recordsize) - 1;
 	min_ibs = DN_MIN_INDBLKSHIFT;
 	max_ibs = DN_MAX_INDBLKSHIFT;
 
@@ -293,6 +293,14 @@
 			 */
 			ASSERT(dn->dn_datablkshift != 0);
 			min_bs = max_bs = dn->dn_datablkshift;
+		} else {
+			/*
+			 * The blocksize can increase up to the recordsize,
+			 * or if it is already more than the recordsize,
+			 * up to the next power of 2.
+			 */
+			min_bs = highbit64(dn->dn_datablksz - 1);
+			max_bs = MAX(max_bs, highbit64(dn->dn_datablksz - 1));
 		}
 
 		/*
@@ -750,11 +758,11 @@
 		bp = &dn->dn_phys->dn_blkptr[0];
 		if (dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset,
 		    bp, bp->blk_birth))
-			txh->txh_space_tooverwrite += SPA_MAXBLOCKSIZE;
+			txh->txh_space_tooverwrite += MZAP_MAX_BLKSZ;
 		else
-			txh->txh_space_towrite += SPA_MAXBLOCKSIZE;
+			txh->txh_space_towrite += MZAP_MAX_BLKSZ;
 		if (!BP_IS_HOLE(bp))
-			txh->txh_space_tounref += SPA_MAXBLOCKSIZE;
+			txh->txh_space_tounref += MZAP_MAX_BLKSZ;
 		return;
 	}
 
@@ -1543,18 +1551,18 @@
 
 	/* If blkptr doesn't exist then add space to towrite */
 	if (!(dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR)) {
-		txh->txh_space_towrite += SPA_MAXBLOCKSIZE;
+		txh->txh_space_towrite += SPA_OLD_MAXBLOCKSIZE;
 	} else {
 		blkptr_t *bp;
 
 		bp = &dn->dn_phys->dn_spill;
 		if (dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset,
 		    bp, bp->blk_birth))
-			txh->txh_space_tooverwrite += SPA_MAXBLOCKSIZE;
+			txh->txh_space_tooverwrite += SPA_OLD_MAXBLOCKSIZE;
 		else
-			txh->txh_space_towrite += SPA_MAXBLOCKSIZE;
+			txh->txh_space_towrite += SPA_OLD_MAXBLOCKSIZE;
 		if (!BP_IS_HOLE(bp))
-			txh->txh_space_tounref += SPA_MAXBLOCKSIZE;
+			txh->txh_space_tounref += SPA_OLD_MAXBLOCKSIZE;
 	}
 }
 
--- a/usr/src/uts/common/fs/zfs/dnode.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dnode.c	Wed Nov 12 04:51:53 2014 -0800
@@ -510,10 +510,10 @@
 {
 	int i;
 
+	ASSERT3U(blocksize, <=,
+	    spa_maxblocksize(dmu_objset_spa(dn->dn_objset)));
 	if (blocksize == 0)
 		blocksize = 1 << zfs_default_bs;
-	else if (blocksize > SPA_MAXBLOCKSIZE)
-		blocksize = SPA_MAXBLOCKSIZE;
 	else
 		blocksize = P2ROUNDUP(blocksize, SPA_MINBLOCKSIZE);
 
@@ -594,7 +594,8 @@
 	int nblkptr;
 
 	ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE);
-	ASSERT3U(blocksize, <=, SPA_MAXBLOCKSIZE);
+	ASSERT3U(blocksize, <=,
+	    spa_maxblocksize(dmu_objset_spa(dn->dn_objset)));
 	ASSERT0(blocksize % SPA_MINBLOCKSIZE);
 	ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT || dmu_tx_private_ok(tx));
 	ASSERT(tx->tx_txg != 0);
@@ -1347,10 +1348,9 @@
 	dmu_buf_impl_t *db;
 	int err;
 
+	ASSERT3U(size, <=, spa_maxblocksize(dmu_objset_spa(dn->dn_objset)));
 	if (size == 0)
 		size = SPA_MINBLOCKSIZE;
-	if (size > SPA_MAXBLOCKSIZE)
-		size = SPA_MAXBLOCKSIZE;
 	else
 		size = P2ROUNDUP(size, SPA_MINBLOCKSIZE);
 
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c	Wed Nov 12 04:51:53 2014 -0800
@@ -50,6 +50,17 @@
 #include <sys/dsl_userhold.h>
 #include <sys/dsl_bookmark.h>
 
+/*
+ * The SPA supports block sizes up to 16MB.  However, very large blocks
+ * can have an impact on i/o latency (e.g. tying up a spinning disk for
+ * ~300ms), and also potentially on the memory allocator.  Therefore,
+ * we do not allow the recordsize to be set larger than zfs_max_recordsize
+ * (default 1MB).  Larger blocks can be created by changing this tunable,
+ * and pools with larger blocks can always be imported and used, regardless
+ * of this setting.
+ */
+int zfs_max_recordsize = 1 * 1024 * 1024;
+
 #define	SWITCH64(x, y) \
 	{ \
 		uint64_t __tmp = (x); \
@@ -59,8 +70,6 @@
 
 #define	DS_REF_MAX	(1ULL << 62)
 
-#define	DSL_DEADLIST_BLOCKSIZE	SPA_MAXBLOCKSIZE
-
 /*
  * Figure out how much of this delta should be propogated to the dsl_dir
  * layer.  If there's a refreservation, that space has already been
@@ -110,6 +119,8 @@
 	ds->ds_phys->ds_compressed_bytes += compressed;
 	ds->ds_phys->ds_uncompressed_bytes += uncompressed;
 	ds->ds_phys->ds_unique_bytes += used;
+	if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE)
+		ds->ds_need_large_blocks = B_TRUE;
 	mutex_exit(&ds->ds_lock);
 	dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
 	    compressed, uncompressed, tx);
@@ -387,6 +398,14 @@
 		list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
 		    offsetof(dmu_sendarg_t, dsa_link));
 
+		if (doi.doi_type == DMU_OTN_ZAP_METADATA) {
+			err = zap_contains(mos, dsobj, DS_FIELD_LARGE_BLOCKS);
+			if (err == 0)
+				ds->ds_large_blocks = B_TRUE;
+			else
+				ASSERT3U(err, ==, ENOENT);
+		}
+
 		if (err == 0) {
 			err = dsl_dir_hold_obj(dp,
 			    ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir);
@@ -700,6 +719,9 @@
 		dsphys->ds_flags |= origin->ds_phys->ds_flags &
 		    (DS_FLAG_INCONSISTENT | DS_FLAG_CI_DATASET);
 
+		if (origin->ds_large_blocks)
+			dsl_dataset_activate_large_blocks_sync_impl(dsobj, tx);
+
 		dmu_buf_will_dirty(origin->ds_dbuf, tx);
 		origin->ds_phys->ds_num_children++;
 
@@ -1213,6 +1235,9 @@
 	dsphys->ds_bp = ds->ds_phys->ds_bp;
 	dmu_buf_rele(dbuf, FTAG);
 
+	if (ds->ds_large_blocks)
+		dsl_dataset_activate_large_blocks_sync_impl(dsobj, tx);
+
 	ASSERT3U(ds->ds_prev != 0, ==, ds->ds_phys->ds_prev_snap_obj != 0);
 	if (ds->ds_prev) {
 		uint64_t next_clones_obj =
@@ -1486,6 +1511,11 @@
 	ds->ds_phys->ds_fsid_guid = ds->ds_fsid_guid;
 
 	dmu_objset_sync(ds->ds_objset, zio, tx);
+
+	if (ds->ds_need_large_blocks && !ds->ds_large_blocks) {
+		dsl_dataset_activate_large_blocks_sync_impl(ds->ds_object, tx);
+		ds->ds_large_blocks = B_TRUE;
+	}
 }
 
 static void
@@ -3128,6 +3158,77 @@
 	return (err);
 }
 
+static int
+dsl_dataset_activate_large_blocks_check(void *arg, dmu_tx_t *tx)
+{
+	const char *dsname = arg;
+	dsl_dataset_t *ds;
+	dsl_pool_t *dp = dmu_tx_pool(tx);
+	int error = 0;
+
+	if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS))
+		return (SET_ERROR(ENOTSUP));
+
+	ASSERT(spa_feature_is_enabled(dp->dp_spa,
+	    SPA_FEATURE_EXTENSIBLE_DATASET));
+
+	error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
+	if (error != 0)
+		return (error);
+
+	if (ds->ds_large_blocks)
+		error = EALREADY;
+	dsl_dataset_rele(ds, FTAG);
+
+	return (error);
+}
+
+void
+dsl_dataset_activate_large_blocks_sync_impl(uint64_t dsobj, dmu_tx_t *tx)
+{
+	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
+	objset_t *mos = dmu_tx_pool(tx)->dp_meta_objset;
+	uint64_t zero = 0;
+
+	spa_feature_incr(spa, SPA_FEATURE_LARGE_BLOCKS, tx);
+	dmu_object_zapify(mos, dsobj, DMU_OT_DSL_DATASET, tx);
+
+	VERIFY0(zap_add(mos, dsobj, DS_FIELD_LARGE_BLOCKS,
+	    sizeof (zero), 1, &zero, tx));
+}
+
+static void
+dsl_dataset_activate_large_blocks_sync(void *arg, dmu_tx_t *tx)
+{
+	const char *dsname = arg;
+	dsl_dataset_t *ds;
+
+	VERIFY0(dsl_dataset_hold(dmu_tx_pool(tx), dsname, FTAG, &ds));
+
+	dsl_dataset_activate_large_blocks_sync_impl(ds->ds_object, tx);
+	ASSERT(!ds->ds_large_blocks);
+	ds->ds_large_blocks = B_TRUE;
+	dsl_dataset_rele(ds, FTAG);
+}
+
+int
+dsl_dataset_activate_large_blocks(const char *dsname)
+{
+	int error;
+
+	error = dsl_sync_task(dsname,
+	    dsl_dataset_activate_large_blocks_check,
+	    dsl_dataset_activate_large_blocks_sync, (void *)dsname,
+	    1, ZFS_SPACE_CHECK_RESERVED);
+
+	/*
+	 * EALREADY indicates that this dataset already supports large blocks.
+	 */
+	if (error == EALREADY)
+		error = 0;
+	return (error);
+}
+
 /*
  * Return TRUE if 'earlier' is an earlier snapshot in 'later's timeline.
  * For example, they could both be snapshots of the same filesystem, and
--- a/usr/src/uts/common/fs/zfs/dsl_deadlist.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dsl_deadlist.c	Wed Nov 12 04:51:53 2014 -0800
@@ -143,7 +143,7 @@
 dsl_deadlist_alloc(objset_t *os, dmu_tx_t *tx)
 {
 	if (spa_version(dmu_objset_spa(os)) < SPA_VERSION_DEADLISTS)
-		return (bpobj_alloc(os, SPA_MAXBLOCKSIZE, tx));
+		return (bpobj_alloc(os, SPA_OLD_MAXBLOCKSIZE, tx));
 	return (zap_create(os, DMU_OT_DEADLIST, DMU_OT_DEADLIST_HDR,
 	    sizeof (dsl_deadlist_phys_t), tx));
 }
@@ -180,7 +180,7 @@
 {
 	if (dle->dle_bpobj.bpo_object ==
 	    dmu_objset_pool(dl->dl_os)->dp_empty_bpobj) {
-		uint64_t obj = bpobj_alloc(dl->dl_os, SPA_MAXBLOCKSIZE, tx);
+		uint64_t obj = bpobj_alloc(dl->dl_os, SPA_OLD_MAXBLOCKSIZE, tx);
 		bpobj_close(&dle->dle_bpobj);
 		bpobj_decr_empty(dl->dl_os, tx);
 		VERIFY3U(0, ==, bpobj_open(&dle->dle_bpobj, dl->dl_os, obj));
@@ -254,7 +254,7 @@
 
 	dle = kmem_alloc(sizeof (*dle), KM_SLEEP);
 	dle->dle_mintxg = mintxg;
-	obj = bpobj_alloc_empty(dl->dl_os, SPA_MAXBLOCKSIZE, tx);
+	obj = bpobj_alloc_empty(dl->dl_os, SPA_OLD_MAXBLOCKSIZE, tx);
 	VERIFY3U(0, ==, bpobj_open(&dle->dle_bpobj, dl->dl_os, obj));
 	avl_add(&dl->dl_tree, dle);
 
@@ -338,7 +338,7 @@
 		if (dle->dle_mintxg >= maxtxg)
 			break;
 
-		obj = bpobj_alloc_empty(dl->dl_os, SPA_MAXBLOCKSIZE, tx);
+		obj = bpobj_alloc_empty(dl->dl_os, SPA_OLD_MAXBLOCKSIZE, tx);
 		VERIFY3U(0, ==, zap_add_int_key(dl->dl_os, newobj,
 		    dle->dle_mintxg, obj, tx));
 	}
--- a/usr/src/uts/common/fs/zfs/dsl_destroy.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dsl_destroy.c	Wed Nov 12 04:51:53 2014 -0800
@@ -264,6 +264,10 @@
 
 	obj = ds->ds_object;
 
+	if (ds->ds_large_blocks) {
+		ASSERT0(zap_contains(mos, obj, DS_FIELD_LARGE_BLOCKS));
+		spa_feature_decr(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS, tx);
+	}
 	if (ds->ds_phys->ds_prev_snap_obj != 0) {
 		ASSERT3P(ds->ds_prev, ==, NULL);
 		VERIFY0(dsl_dataset_hold_obj(dp,
@@ -720,6 +724,9 @@
 		ASSERT0(ds->ds_reserved);
 	}
 
+	if (ds->ds_large_blocks)
+		spa_feature_decr(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS, tx);
+
 	dsl_scan_ds_destroyed(ds, tx);
 
 	obj = ds->ds_object;
--- a/usr/src/uts/common/fs/zfs/dsl_pool.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/dsl_pool.c	Wed Nov 12 04:51:53 2014 -0800
@@ -367,7 +367,7 @@
 		    FREE_DIR_NAME, &dp->dp_free_dir));
 
 		/* create and open the free_bplist */
-		obj = bpobj_alloc(dp->dp_meta_objset, SPA_MAXBLOCKSIZE, tx);
+		obj = bpobj_alloc(dp->dp_meta_objset, SPA_OLD_MAXBLOCKSIZE, tx);
 		VERIFY(zap_add(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
 		    DMU_POOL_FREE_BPOBJ, sizeof (uint64_t), 1, &obj, tx) == 0);
 		VERIFY0(bpobj_open(&dp->dp_free_bpobj,
@@ -792,7 +792,7 @@
 	 * subobj support.  So call dmu_object_alloc() directly.
 	 */
 	obj = dmu_object_alloc(dp->dp_meta_objset, DMU_OT_BPOBJ,
-	    SPA_MAXBLOCKSIZE, DMU_OT_BPOBJ_HDR, sizeof (bpobj_phys_t), tx);
+	    SPA_OLD_MAXBLOCKSIZE, DMU_OT_BPOBJ_HDR, sizeof (bpobj_phys_t), tx);
 	VERIFY0(zap_add(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
 	    DMU_POOL_FREE_BPOBJ, sizeof (uint64_t), 1, &obj, tx));
 	VERIFY0(bpobj_open(&dp->dp_free_bpobj, dp->dp_meta_objset, obj));
--- a/usr/src/uts/common/fs/zfs/metaslab.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/metaslab.c	Wed Nov 12 04:51:53 2014 -0800
@@ -125,7 +125,7 @@
  * an allocation of this size then it switches to using more
  * aggressive strategy (i.e search by size rather than offset).
  */
-uint64_t metaslab_df_alloc_threshold = SPA_MAXBLOCKSIZE;
+uint64_t metaslab_df_alloc_threshold = SPA_OLD_MAXBLOCKSIZE;
 
 /*
  * The minimum free space, in percent, which must be available
--- a/usr/src/uts/common/fs/zfs/sa.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sa.c	Wed Nov 12 04:51:53 2014 -0800
@@ -500,7 +500,7 @@
 
 	if (size == 0) {
 		blocksize = SPA_MINBLOCKSIZE;
-	} else if (size > SPA_MAXBLOCKSIZE) {
+	} else if (size > SPA_OLD_MAXBLOCKSIZE) {
 		ASSERT(0);
 		return (SET_ERROR(EFBIG));
 	} else {
@@ -675,7 +675,7 @@
 	hdrsize = sa_find_sizes(sa, attr_desc, attr_count, hdl->sa_bonus,
 	    SA_BONUS, &i, &used, &spilling);
 
-	if (used > SPA_MAXBLOCKSIZE)
+	if (used > SPA_OLD_MAXBLOCKSIZE)
 		return (SET_ERROR(EFBIG));
 
 	VERIFY(0 == dmu_set_bonus(hdl->sa_bonus, spilling ?
@@ -699,7 +699,7 @@
 		    attr_count - i, hdl->sa_spill, SA_SPILL, &i,
 		    &spill_used, &dummy);
 
-		if (spill_used > SPA_MAXBLOCKSIZE)
+		if (spill_used > SPA_OLD_MAXBLOCKSIZE)
 			return (SET_ERROR(EFBIG));
 
 		buf_space = hdl->sa_spill->db_size - spillhdrsize;
--- a/usr/src/uts/common/fs/zfs/spa.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/spa.c	Wed Nov 12 04:51:53 2014 -0800
@@ -267,6 +267,14 @@
 		spa_prop_add_list(*nvp, ZPOOL_PROP_ALTROOT, spa->spa_root,
 		    0, ZPROP_SRC_LOCAL);
 
+	if (spa_feature_is_enabled(spa, SPA_FEATURE_LARGE_BLOCKS)) {
+		spa_prop_add_list(*nvp, ZPOOL_PROP_MAXBLOCKSIZE, NULL,
+		    MIN(zfs_max_recordsize, SPA_MAXBLOCKSIZE), ZPROP_SRC_NONE);
+	} else {
+		spa_prop_add_list(*nvp, ZPOOL_PROP_MAXBLOCKSIZE, NULL,
+		    SPA_OLD_MAXBLOCKSIZE, ZPROP_SRC_NONE);
+	}
+
 	if ((dp = list_head(&spa->spa_config_list)) != NULL) {
 		if (dp->scd_path == NULL) {
 			spa_prop_add_list(*nvp, ZPOOL_PROP_CACHEFILE,
@@ -481,7 +489,7 @@
 
 			if (!error) {
 				objset_t *os;
-				uint64_t compress;
+				uint64_t propval;
 
 				if (strval == NULL || strval[0] == '\0') {
 					objnum = zpool_prop_default_numeric(
@@ -492,15 +500,25 @@
 				if (error = dmu_objset_hold(strval, FTAG, &os))
 					break;
 
-				/* Must be ZPL and not gzip compressed. */
+				/*
+				 * Must be ZPL, and its property settings
+				 * must be supported by GRUB (compression
+				 * is not gzip, and large blocks are not used).
+				 */
 
 				if (dmu_objset_type(os) != DMU_OST_ZFS) {
 					error = SET_ERROR(ENOTSUP);
 				} else if ((error =
 				    dsl_prop_get_int_ds(dmu_objset_ds(os),
 				    zfs_prop_to_name(ZFS_PROP_COMPRESSION),
-				    &compress)) == 0 &&
-				    !BOOTFS_COMPRESS_VALID(compress)) {
+				    &propval)) == 0 &&
+				    !BOOTFS_COMPRESS_VALID(propval)) {
+					error = SET_ERROR(ENOTSUP);
+				} else if ((error =
+				    dsl_prop_get_int_ds(dmu_objset_ds(os),
+				    zfs_prop_to_name(ZFS_PROP_RECORDSIZE),
+				    &propval)) == 0 &&
+				    propval > SPA_OLD_MAXBLOCKSIZE) {
 					error = SET_ERROR(ENOTSUP);
 				} else {
 					objnum = dmu_objset_id(os);
--- a/usr/src/uts/common/fs/zfs/spa_history.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/spa_history.c	Wed Nov 12 04:51:53 2014 -0800
@@ -90,7 +90,7 @@
 
 	ASSERT(spa->spa_history == 0);
 	spa->spa_history = dmu_object_alloc(mos, DMU_OT_SPA_HISTORY,
-	    SPA_MAXBLOCKSIZE, DMU_OT_SPA_HISTORY_OFFSETS,
+	    SPA_OLD_MAXBLOCKSIZE, DMU_OT_SPA_HISTORY_OFFSETS,
 	    sizeof (spa_history_phys_t), tx);
 
 	VERIFY(zap_add(mos, DMU_POOL_DIRECTORY_OBJECT,
--- a/usr/src/uts/common/fs/zfs/spa_misc.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1963,3 +1963,12 @@
 {
 	return (spa->spa_debug);
 }
+
+int
+spa_maxblocksize(spa_t *spa)
+{
+	if (spa_feature_is_enabled(spa, SPA_FEATURE_LARGE_BLOCKS))
+		return (SPA_MAXBLOCKSIZE);
+	else
+		return (SPA_OLD_MAXBLOCKSIZE);
+}
--- a/usr/src/uts/common/fs/zfs/sys/dmu.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/dmu.h	Wed Nov 12 04:51:53 2014 -0800
@@ -249,7 +249,7 @@
  * The maximum number of bytes that can be accessed as part of one
  * operation, including metadata.
  */
-#define	DMU_MAX_ACCESS (10<<20) /* 10MB */
+#define	DMU_MAX_ACCESS (32 * 1024 * 1024) /* 32MB */
 #define	DMU_MAX_DELETEBLKCNT (20480) /* ~5MB of indirect blocks */
 
 #define	DMU_USERUSED_OBJECT	(-1ULL)
@@ -637,6 +637,7 @@
 void xuio_stat_wbuf_nocopy();
 
 extern int zfs_prefetch_disable;
+extern int zfs_max_recordsize;
 
 /*
  * Asynchronously try to read in the data.
--- a/usr/src/uts/common/fs/zfs/sys/dmu_objset.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/dmu_objset.h	Wed Nov 12 04:51:53 2014 -0800
@@ -95,6 +95,7 @@
 	zfs_cache_type_t os_secondary_cache;
 	zfs_sync_type_t os_sync;
 	zfs_redundant_metadata_type_t os_redundant_metadata;
+	int os_recordsize;
 
 	/* no lock needed: */
 	struct dmu_tx *os_synctx; /* XXX sketchy */
--- a/usr/src/uts/common/fs/zfs/sys/dmu_send.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/dmu_send.h	Wed Nov 12 04:51:53 2014 -0800
@@ -37,12 +37,14 @@
 struct drr_begin;
 struct avl_tree;
 
-int dmu_send(const char *tosnap, const char *fromsnap, boolean_t embedok,
+int dmu_send(const char *tosnap, const char *fromsnap,
+    boolean_t embedok, boolean_t large_block_ok,
     int outfd, struct vnode *vp, offset_t *off);
 int dmu_send_estimate(struct dsl_dataset *ds, struct dsl_dataset *fromds,
     uint64_t *sizep);
 int dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap,
-    boolean_t embedok, int outfd, vnode_t *vp, offset_t *off);
+    boolean_t embedok, boolean_t large_block_ok,
+    int outfd, struct vnode *vp, offset_t *off);
 
 typedef struct dmu_recv_cookie {
 	struct dsl_dataset *drc_ds;
--- a/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h	Wed Nov 12 04:51:53 2014 -0800
@@ -83,6 +83,13 @@
 #define	DS_FIELD_BOOKMARK_NAMES "com.delphix:bookmarks"
 
 /*
+ * This field is present (with value=0) if this dataset may contain large
+ * blocks (>128KB).  If it is present, then this dataset
+ * is counted in the refcount of the SPA_FEATURE_LARGE_BLOCKS feature.
+ */
+#define	DS_FIELD_LARGE_BLOCKS "org.open-zfs:large_blocks"
+
+/*
  * DS_FLAG_CI_DATASET is set if the dataset contains a file system whose
  * name lookups should be performed case-insensitively.
  */
@@ -135,6 +142,8 @@
 	/* only used in syncing context, only valid for non-snapshots: */
 	struct dsl_dataset *ds_prev;
 	uint64_t ds_bookmarks;  /* DMU_OTN_ZAP_METADATA */
+	boolean_t ds_large_blocks;
+	boolean_t ds_need_large_blocks;
 
 	/* has internal locking: */
 	dsl_deadlist_t ds_deadlist;
@@ -244,6 +253,8 @@
 int dsl_dataset_space_wouldfree(dsl_dataset_t *firstsnap, dsl_dataset_t *last,
     uint64_t *usedp, uint64_t *compp, uint64_t *uncompp);
 boolean_t dsl_dataset_is_dirty(dsl_dataset_t *ds);
+int dsl_dataset_activate_large_blocks(const char *dsname);
+void dsl_dataset_activate_large_blocks_sync_impl(uint64_t dsobj, dmu_tx_t *tx);
 
 int dsl_dsobj_to_dsname(char *pname, uint64_t obj, char *buf);
 
--- a/usr/src/uts/common/fs/zfs/sys/spa.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/spa.h	Wed Nov 12 04:51:53 2014 -0800
@@ -94,17 +94,26 @@
 _NOTE(CONSTCOND) } while (0)
 
 /*
- * We currently support nine block sizes, from 512 bytes to 128K.
- * We could go higher, but the benefits are near-zero and the cost
- * of COWing a giant block to modify one byte would become excessive.
+ * We currently support block sizes from 512 bytes to 16MB.
+ * The benefits of larger blocks, and thus larger IO, need to be weighed
+ * against the cost of COWing a giant block to modify one byte, and the
+ * large latency of reading or writing a large block.
+ *
+ * Note that although blocks up to 16MB are supported, the recordsize
+ * property can not be set larger than zfs_max_recordsize (default 1MB).
+ * See the comment near zfs_max_recordsize in dsl_dataset.c for details.
+ *
+ * Note that although the LSIZE field of the blkptr_t can store sizes up
+ * to 32MB, the dnode's dn_datablkszsec can only store sizes up to
+ * 32MB - 512 bytes.  Therefore, we limit SPA_MAXBLOCKSIZE to 16MB.
  */
 #define	SPA_MINBLOCKSHIFT	9
-#define	SPA_MAXBLOCKSHIFT	17
+#define	SPA_OLD_MAXBLOCKSHIFT	17
+#define	SPA_MAXBLOCKSHIFT	24
 #define	SPA_MINBLOCKSIZE	(1ULL << SPA_MINBLOCKSHIFT)
+#define	SPA_OLD_MAXBLOCKSIZE	(1ULL << SPA_OLD_MAXBLOCKSHIFT)
 #define	SPA_MAXBLOCKSIZE	(1ULL << SPA_MAXBLOCKSHIFT)
 
-#define	SPA_BLOCKSIZES		(SPA_MAXBLOCKSHIFT - SPA_MINBLOCKSHIFT + 1)
-
 /*
  * Size of block to hold the configuration data (a packed nvlist)
  */
@@ -781,6 +790,7 @@
 extern boolean_t spa_is_root(spa_t *spa);
 extern boolean_t spa_writeable(spa_t *spa);
 extern boolean_t spa_has_pending_synctask(spa_t *spa);
+extern int spa_maxblocksize(spa_t *spa);
 
 extern int spa_mode(spa_t *spa);
 extern uint64_t strtonum(const char *str, char **nptr);
--- a/usr/src/uts/common/fs/zfs/sys/zap_impl.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zap_impl.h	Wed Nov 12 04:51:53 2014 -0800
@@ -42,8 +42,7 @@
 
 #define	MZAP_ENT_LEN		64
 #define	MZAP_NAME_LEN		(MZAP_ENT_LEN - 8 - 4 - 2)
-#define	MZAP_MAX_BLKSHIFT	SPA_MAXBLOCKSHIFT
-#define	MZAP_MAX_BLKSZ		(1 << MZAP_MAX_BLKSHIFT)
+#define	MZAP_MAX_BLKSZ		SPA_OLD_MAXBLOCKSIZE
 
 #define	ZAP_NEED_CD		(-1U)
 
--- a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h	Wed Nov 12 04:51:53 2014 -0800
@@ -85,13 +85,16 @@
 /* flags #3 - #15 are reserved for incompatible closed-source implementations */
 #define	DMU_BACKUP_FEATURE_EMBED_DATA		(1<<16)
 #define	DMU_BACKUP_FEATURE_EMBED_DATA_LZ4	(1<<17)
+/* flag #18 is reserved for a Delphix feature */
+#define	DMU_BACKUP_FEATURE_LARGE_BLOCKS		(1<<19)
 
 /*
  * Mask of all supported backup features
  */
 #define	DMU_BACKUP_FEATURE_MASK	(DMU_BACKUP_FEATURE_DEDUP | \
     DMU_BACKUP_FEATURE_DEDUPPROPS | DMU_BACKUP_FEATURE_SA_SPILL | \
-    DMU_BACKUP_FEATURE_EMBED_DATA | DMU_BACKUP_FEATURE_EMBED_DATA_LZ4)
+    DMU_BACKUP_FEATURE_EMBED_DATA | DMU_BACKUP_FEATURE_EMBED_DATA_LZ4 | \
+    DMU_BACKUP_FEATURE_LARGE_BLOCKS)
 
 /* Are all features in the given flag word currently supported? */
 #define	DMU_STREAM_SUPPORTED(x)	(!((x) & ~DMU_BACKUP_FEATURE_MASK))
--- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h	Wed Nov 12 04:51:53 2014 -0800
@@ -136,8 +136,6 @@
 #define	ZFS_SHARES_DIR		"SHARES"
 #define	ZFS_SA_ATTRS		"SA_ATTRS"
 
-#define	ZFS_MAX_BLOCKSIZE	(SPA_MAXBLOCKSIZE)
-
 /*
  * Path component length
  *
--- a/usr/src/uts/common/fs/zfs/sys/zil.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zil.h	Wed Nov 12 04:51:53 2014 -0800
@@ -90,7 +90,6 @@
 } zil_chain_t;
 
 #define	ZIL_MIN_BLKSZ	4096ULL
-#define	ZIL_MAX_BLKSZ	SPA_MAXBLOCKSIZE
 
 /*
  * The words of a log block checksum.
--- a/usr/src/uts/common/fs/zfs/sys/zil_impl.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zil_impl.h	Wed Nov 12 04:51:53 2014 -0800
@@ -139,7 +139,7 @@
 	avl_node_t	zn_node;
 } zil_bp_node_t;
 
-#define	ZIL_MAX_LOG_DATA (SPA_MAXBLOCKSIZE - sizeof (zil_chain_t) - \
+#define	ZIL_MAX_LOG_DATA (SPA_OLD_MAXBLOCKSIZE - sizeof (zil_chain_t) - \
     sizeof (lr_write_t))
 
 #ifdef	__cplusplus
--- a/usr/src/uts/common/fs/zfs/vdev.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/vdev.c	Wed Nov 12 04:51:53 2014 -0800
@@ -828,9 +828,9 @@
 
 	/*
 	 * Compute the raidz-deflation ratio.  Note, we hard-code
-	 * in 128k (1 << 17) because it is the current "typical" blocksize.
-	 * Even if SPA_MAXBLOCKSIZE changes, this algorithm must never change,
-	 * or we will inconsistently account for existing bp's.
+	 * in 128k (1 << 17) because it is the "typical" blocksize.
+	 * Even though SPA_MAXBLOCKSIZE changed, this algorithm can not change,
+	 * otherwise it would inconsistently account for existing bp's.
 	 */
 	vd->vdev_deflate_ratio = (1 << 17) /
 	    (vdev_psize_to_asize(vd, 1 << 17) >> SPA_MINBLOCKSHIFT);
--- a/usr/src/uts/common/fs/zfs/vdev_queue.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/vdev_queue.c	Wed Nov 12 04:51:53 2014 -0800
@@ -162,7 +162,7 @@
  * we include spans of optional I/Os to aid aggregation at the disk even when
  * they aren't able to help us aggregate at this level.
  */
-int zfs_vdev_aggregation_limit = SPA_MAXBLOCKSIZE;
+int zfs_vdev_aggregation_limit = SPA_OLD_MAXBLOCKSIZE;
 int zfs_vdev_read_gap_limit = 32 << 10;
 int zfs_vdev_write_gap_limit = 4 << 10;
 
--- a/usr/src/uts/common/fs/zfs/vdev_raidz.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/vdev_raidz.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1604,7 +1604,7 @@
 	/*
 	 * Don't write past the end of the block
 	 */
-	VERIFY3U(offset + size, <=, origoffset + SPA_MAXBLOCKSIZE);
+	VERIFY3U(offset + size, <=, origoffset + SPA_OLD_MAXBLOCKSIZE);
 
 	start = offset;
 	end = start + size;
@@ -1619,8 +1619,8 @@
 	 * KB size.
 	 */
 	rm = vdev_raidz_map_alloc(data - (offset - origoffset),
-	    SPA_MAXBLOCKSIZE, origoffset, tvd->vdev_ashift, vd->vdev_children,
-	    vd->vdev_nparity);
+	    SPA_OLD_MAXBLOCKSIZE, origoffset, tvd->vdev_ashift,
+	    vd->vdev_children, vd->vdev_nparity);
 
 	coloffset = origoffset;
 
--- a/usr/src/uts/common/fs/zfs/zap_micro.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zap_micro.c	Wed Nov 12 04:51:53 2014 -0800
@@ -33,6 +33,7 @@
 #include <sys/zap_leaf.h>
 #include <sys/avl.h>
 #include <sys/arc.h>
+#include <sys/dmu_objset.h>
 
 #ifdef _KERNEL
 #include <sys/sunddi.h>
@@ -653,9 +654,9 @@
 	uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx);
 
 	ASSERT(leaf_blockshift >= SPA_MINBLOCKSHIFT &&
-	    leaf_blockshift <= SPA_MAXBLOCKSHIFT &&
+	    leaf_blockshift <= SPA_OLD_MAXBLOCKSHIFT &&
 	    indirect_blockshift >= SPA_MINBLOCKSHIFT &&
-	    indirect_blockshift <= SPA_MAXBLOCKSHIFT);
+	    indirect_blockshift <= SPA_OLD_MAXBLOCKSHIFT);
 
 	VERIFY(dmu_object_set_blocksize(os, obj,
 	    1ULL << leaf_blockshift, indirect_blockshift, tx) == 0);
@@ -1345,7 +1346,6 @@
 	zap_t *zap;
 	int err = 0;
 
-
 	/*
 	 * Since, we don't have a name, we cannot figure out which blocks will
 	 * be affected in this operation. So, account for the worst case :
@@ -1358,7 +1358,7 @@
 	 * large microzap results in a promotion to fatzap.
 	 */
 	if (name == NULL) {
-		*towrite += (3 + (add ? 4 : 0)) * SPA_MAXBLOCKSIZE;
+		*towrite += (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE;
 		return (err);
 	}
 
@@ -1382,7 +1382,7 @@
 			/*
 			 * We treat this case as similar to (name == NULL)
 			 */
-			*towrite += (3 + (add ? 4 : 0)) * SPA_MAXBLOCKSIZE;
+			*towrite += (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE;
 		}
 	} else {
 		/*
@@ -1401,12 +1401,12 @@
 		 *			ptrtbl blocks
 		 */
 		if (dmu_buf_freeable(zap->zap_dbuf))
-			*tooverwrite += SPA_MAXBLOCKSIZE;
+			*tooverwrite += MZAP_MAX_BLKSZ;
 		else
-			*towrite += SPA_MAXBLOCKSIZE;
+			*towrite += MZAP_MAX_BLKSZ;
 
 		if (add) {
-			*towrite += 4 * SPA_MAXBLOCKSIZE;
+			*towrite += 4 * MZAP_MAX_BLKSZ;
 		}
 	}
 
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Wed Nov 12 04:51:53 2014 -0800
@@ -2383,7 +2383,7 @@
 	const char *propname = nvpair_name(pair);
 	zfs_prop_t prop = zfs_name_to_prop(propname);
 	uint64_t intval;
-	int err;
+	int err = -1;
 
 	if (prop == ZPROP_INVAL) {
 		if (zfs_prop_userquota(propname))
@@ -3772,8 +3772,7 @@
 		 * the SPA supports it. We ignore any errors here since
 		 * we'll catch them later.
 		 */
-		if (nvpair_type(pair) == DATA_TYPE_UINT64 &&
-		    nvpair_value_uint64(pair, &intval) == 0) {
+		if (nvpair_value_uint64(pair, &intval) == 0) {
 			if (intval >= ZIO_COMPRESS_GZIP_1 &&
 			    intval <= ZIO_COMPRESS_GZIP_9 &&
 			    zfs_earlier_version(dsname,
@@ -3824,6 +3823,42 @@
 			return (SET_ERROR(ENOTSUP));
 		break;
 
+	case ZFS_PROP_RECORDSIZE:
+		/* Record sizes above 128k need the feature to be enabled */
+		if (nvpair_value_uint64(pair, &intval) == 0 &&
+		    intval > SPA_OLD_MAXBLOCKSIZE) {
+			spa_t *spa;
+
+			/*
+			 * If this is a bootable dataset then
+			 * the we don't allow large (>128K) blocks,
+			 * because GRUB doesn't support them.
+			 */
+			if (zfs_is_bootfs(dsname) &&
+			    intval > SPA_OLD_MAXBLOCKSIZE) {
+				return (SET_ERROR(EDOM));
+			}
+
+			/*
+			 * We don't allow setting the property above 1MB,
+			 * unless the tunable has been changed.
+			 */
+			if (intval > zfs_max_recordsize ||
+			    intval > SPA_MAXBLOCKSIZE)
+				return (SET_ERROR(EDOM));
+
+			if ((err = spa_open(dsname, &spa, FTAG)) != 0)
+				return (err);
+
+			if (!spa_feature_is_enabled(spa,
+			    SPA_FEATURE_LARGE_BLOCKS)) {
+				spa_close(spa, FTAG);
+				return (SET_ERROR(ENOTSUP));
+			}
+			spa_close(spa, FTAG);
+		}
+		break;
+
 	case ZFS_PROP_SHARESMB:
 		if (zpl_earlier_version(dsname, ZPL_VERSION_FUID))
 			return (SET_ERROR(ENOTSUP));
@@ -4245,7 +4280,7 @@
  * zc_fromobj	objsetid of incremental fromsnap (may be zero)
  * zc_guid	if set, estimate size of stream only.  zc_cookie is ignored.
  *		output size in zc_objset_type.
- * zc_flags	if =1, WRITE_EMBEDDED records are permitted
+ * zc_flags	lzc_send_flags
  *
  * outputs:
  * zc_objset_type	estimated size, if zc_guid is set
@@ -4257,6 +4292,7 @@
 	offset_t off;
 	boolean_t estimate = (zc->zc_guid != 0);
 	boolean_t embedok = (zc->zc_flags & 0x1);
+	boolean_t large_block_ok = (zc->zc_flags & 0x2);
 
 	if (zc->zc_obj != 0) {
 		dsl_pool_t *dp;
@@ -4317,7 +4353,8 @@
 
 		off = fp->f_offset;
 		error = dmu_send_obj(zc->zc_name, zc->zc_sendobj,
-		    zc->zc_fromobj, embedok, zc->zc_cookie, fp->f_vnode, &off);
+		    zc->zc_fromobj, embedok, large_block_ok,
+		    zc->zc_cookie, fp->f_vnode, &off);
 
 		if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
 			fp->f_offset = off;
@@ -5219,6 +5256,8 @@
  * innvl: {
  *     "fd" -> file descriptor to write stream to (int32)
  *     (optional) "fromsnap" -> full snap name to send an incremental from
+ *     (optional) "largeblockok" -> (value ignored)
+ *         indicates that blocks > 128KB are permitted
  *     (optional) "embedok" -> (value ignored)
  *         presence indicates DRR_WRITE_EMBEDDED records are permitted
  * }
@@ -5233,6 +5272,7 @@
 	offset_t off;
 	char *fromname = NULL;
 	int fd;
+	boolean_t largeblockok;
 	boolean_t embedok;
 
 	error = nvlist_lookup_int32(innvl, "fd", &fd);
@@ -5241,6 +5281,7 @@
 
 	(void) nvlist_lookup_string(innvl, "fromsnap", &fromname);
 
+	largeblockok = nvlist_exists(innvl, "largeblockok");
 	embedok = nvlist_exists(innvl, "embedok");
 
 	file_t *fp = getf(fd);
@@ -5248,7 +5289,8 @@
 		return (SET_ERROR(EBADF));
 
 	off = fp->f_offset;
-	error = dmu_send(snapname, fromname, embedok, fd, fp->f_vnode, &off);
+	error = dmu_send(snapname, fromname, embedok, largeblockok,
+	    fd, fp->f_vnode, &off);
 
 	if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
 		fp->f_offset = off;
--- a/usr/src/uts/common/fs/zfs/zfs_log.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_log.c	Wed Nov 12 04:51:53 2014 -0800
@@ -485,7 +485,7 @@
 		 * If the write would overflow the largest block then split it.
 		 */
 		if (write_state != WR_INDIRECT && resid > ZIL_MAX_LOG_DATA)
-			len = SPA_MAXBLOCKSIZE >> 1;
+			len = SPA_OLD_MAXBLOCKSIZE >> 1;
 		else
 			len = resid;
 
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c	Wed Nov 12 04:51:53 2014 -0800
@@ -272,10 +272,9 @@
 blksz_changed_cb(void *arg, uint64_t newval)
 {
 	zfsvfs_t *zfsvfs = arg;
-
-	if (newval < SPA_MINBLOCKSIZE ||
-	    newval > SPA_MAXBLOCKSIZE || !ISP2(newval))
-		newval = SPA_MAXBLOCKSIZE;
+	ASSERT3U(newval, <=, spa_maxblocksize(dmu_objset_spa(zfsvfs->z_os)));
+	ASSERT3U(newval, >=, SPA_MINBLOCKSIZE);
+	ASSERT(ISP2(newval));
 
 	zfsvfs->z_max_blksz = newval;
 	zfsvfs->z_vfs->vfs_bsize = newval;
@@ -906,7 +905,7 @@
 	 */
 	zfsvfs->z_vfs = NULL;
 	zfsvfs->z_parent = zfsvfs;
-	zfsvfs->z_max_blksz = SPA_MAXBLOCKSIZE;
+	zfsvfs->z_max_blksz = SPA_OLD_MAXBLOCKSIZE;
 	zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE;
 	zfsvfs->z_os = os;
 
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c	Wed Nov 12 04:51:53 2014 -0800
@@ -817,8 +817,14 @@
 			uint64_t new_blksz;
 
 			if (zp->z_blksz > max_blksz) {
+				/*
+				 * File's blocksize is already larger than the
+				 * "recordsize" property.  Only let it grow to
+				 * the next power of 2.
+				 */
 				ASSERT(!ISP2(zp->z_blksz));
-				new_blksz = MIN(end_size, SPA_MAXBLOCKSIZE);
+				new_blksz = MIN(end_size,
+				    1 << highbit64(zp->z_blksz));
 			} else {
 				new_blksz = MIN(end_size, max_blksz);
 			}
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c	Wed Nov 12 04:51:53 2014 -0800
@@ -58,6 +58,7 @@
 #endif /* _KERNEL */
 
 #include <sys/dmu.h>
+#include <sys/dmu_objset.h>
 #include <sys/refcount.h>
 #include <sys/stat.h>
 #include <sys/zap.h>
@@ -1474,8 +1475,13 @@
 		 * We are growing the file past the current block size.
 		 */
 		if (zp->z_blksz > zp->z_zfsvfs->z_max_blksz) {
+			/*
+			 * File's blocksize is already larger than the
+			 * "recordsize" property.  Only let it grow to
+			 * the next power of 2.
+			 */
 			ASSERT(!ISP2(zp->z_blksz));
-			newblksz = MIN(end, SPA_MAXBLOCKSIZE);
+			newblksz = MIN(end, 1 << highbit64(zp->z_blksz));
 		} else {
 			newblksz = MIN(end, zp->z_zfsvfs->z_max_blksz);
 		}
--- a/usr/src/uts/common/fs/zfs/zil.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zil.c	Wed Nov 12 04:51:53 2014 -0800
@@ -220,6 +220,7 @@
 			    sizeof (cksum)) || BP_IS_HOLE(&zilc->zc_next_blk)) {
 				error = SET_ERROR(ECKSUM);
 			} else {
+				ASSERT3U(len, <=, SPA_OLD_MAXBLOCKSIZE);
 				bcopy(lr, dst, len);
 				*end = (char *)dst + len;
 				*nbp = zilc->zc_next_blk;
@@ -234,6 +235,8 @@
 			    (zilc->zc_nused > (size - sizeof (*zilc)))) {
 				error = SET_ERROR(ECKSUM);
 			} else {
+				ASSERT3U(zilc->zc_nused, <=,
+				    SPA_OLD_MAXBLOCKSIZE);
 				bcopy(lr, dst, zilc->zc_nused);
 				*end = (char *)dst + zilc->zc_nused;
 				*nbp = zilc->zc_next_blk;
@@ -317,7 +320,7 @@
 	 * If the log has been claimed, stop if we encounter a sequence
 	 * number greater than the highest claimed sequence number.
 	 */
-	lrbuf = zio_buf_alloc(SPA_MAXBLOCKSIZE);
+	lrbuf = zio_buf_alloc(SPA_OLD_MAXBLOCKSIZE);
 	zil_bp_tree_init(zilog);
 
 	for (blk = zh->zh_log; !BP_IS_HOLE(&blk); blk = next_blk) {
@@ -364,7 +367,7 @@
 	    (max_blk_seq == claim_blk_seq && max_lr_seq == claim_lr_seq));
 
 	zil_bp_tree_fini(zilog);
-	zio_buf_free(lrbuf, SPA_MAXBLOCKSIZE);
+	zio_buf_free(lrbuf, SPA_OLD_MAXBLOCKSIZE);
 
 	return (error);
 }
@@ -896,7 +899,7 @@
  *
  * These must be a multiple of 4KB. Note only the amount used (again
  * aligned to 4KB) actually gets written. However, we can't always just
- * allocate SPA_MAXBLOCKSIZE as the slog space could be exhausted.
+ * allocate SPA_OLD_MAXBLOCKSIZE as the slog space could be exhausted.
  */
 uint64_t zil_block_buckets[] = {
     4096,		/* non TX_WRITE */
@@ -978,7 +981,7 @@
 		continue;
 	zil_blksz = zil_block_buckets[i];
 	if (zil_blksz == UINT64_MAX)
-		zil_blksz = SPA_MAXBLOCKSIZE;
+		zil_blksz = SPA_OLD_MAXBLOCKSIZE;
 	zilog->zl_prev_blks[zilog->zl_prev_rotor] = zil_blksz;
 	for (i = 0; i < ZIL_PREV_BLKS; i++)
 		zil_blksz = MAX(zil_blksz, zilog->zl_prev_blks[i]);
--- a/usr/src/uts/common/fs/zfs/zio.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zio.c	Wed Nov 12 04:51:53 2014 -0800
@@ -24,6 +24,7 @@
  * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/zfs_context.h>
 #include <sys/fm/fs/zfs.h>
 #include <sys/spa.h>
@@ -112,9 +113,8 @@
 
 	/*
 	 * For small buffers, we want a cache for each multiple of
-	 * SPA_MINBLOCKSIZE.  For medium-size buffers, we want a cache
-	 * for each quarter-power of 2.  For large buffers, we want
-	 * a cache for each multiple of PAGESIZE.
+	 * SPA_MINBLOCKSIZE.  For larger buffers, we want a cache
+	 * for each quarter-power of 2.
 	 */
 	for (c = 0; c < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT; c++) {
 		size_t size = (c + 1) << SPA_MINBLOCKSHIFT;
@@ -122,7 +122,7 @@
 		size_t align = 0;
 		size_t cflags = (size > zio_buf_debug_limit) ? KMC_NODEBUG : 0;
 
-		while (p2 & (p2 - 1))
+		while (!ISP2(p2))
 			p2 &= p2 - 1;
 
 #ifndef _KERNEL
@@ -137,10 +137,8 @@
 #endif
 		if (size <= 4 * SPA_MINBLOCKSIZE) {
 			align = SPA_MINBLOCKSIZE;
-		} else if (IS_P2ALIGNED(size, PAGESIZE)) {
-			align = PAGESIZE;
 		} else if (IS_P2ALIGNED(size, p2 >> 2)) {
-			align = p2 >> 2;
+			align = MIN(p2 >> 2, PAGESIZE);
 		}
 
 		if (align != 0) {
--- a/usr/src/uts/common/fs/zfs/zvol.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/fs/zfs/zvol.c	Wed Nov 12 04:51:53 2014 -0800
@@ -191,7 +191,7 @@
 zvol_check_volblocksize(uint64_t volblocksize)
 {
 	if (volblocksize < SPA_MINBLOCKSIZE ||
-	    volblocksize > SPA_MAXBLOCKSIZE ||
+	    volblocksize > SPA_OLD_MAXBLOCKSIZE ||
 	    !ISP2(volblocksize))
 		return (SET_ERROR(EDOM));
 
@@ -692,7 +692,7 @@
 
 	while (resid != 0) {
 		int error;
-		uint64_t bytes = MIN(resid, SPA_MAXBLOCKSIZE);
+		uint64_t bytes = MIN(resid, SPA_OLD_MAXBLOCKSIZE);
 
 		tx = dmu_tx_create(os);
 		dmu_tx_hold_write(tx, ZVOL_OBJ, off, bytes);
@@ -1661,7 +1661,8 @@
 		(void) strcpy(dki.dki_dname, "zvol");
 		dki.dki_ctype = DKC_UNKNOWN;
 		dki.dki_unit = getminor(dev);
-		dki.dki_maxtransfer = 1 << (SPA_MAXBLOCKSHIFT - zv->zv_min_bs);
+		dki.dki_maxtransfer =
+		    1 << (SPA_OLD_MAXBLOCKSHIFT - zv->zv_min_bs);
 		mutex_exit(&zfsdev_state_lock);
 		if (ddi_copyout(&dki, (void *)arg, sizeof (dki), flag))
 			error = SET_ERROR(EFAULT);
@@ -1978,14 +1979,14 @@
 		    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 8, 1,
 		    &vbs, tx);
 		error = error ? error : dmu_object_set_blocksize(
-		    os, ZVOL_OBJ, SPA_MAXBLOCKSIZE, 0, tx);
+		    os, ZVOL_OBJ, SPA_OLD_MAXBLOCKSIZE, 0, tx);
 		if (version >= SPA_VERSION_DEDUP) {
 			error = error ? error : zap_update(os, ZVOL_ZAP_OBJ,
 			    zfs_prop_to_name(ZFS_PROP_DEDUP), 8, 1,
 			    &dedup, tx);
 		}
 		if (error == 0)
-			zv->zv_volblocksize = SPA_MAXBLOCKSIZE;
+			zv->zv_volblocksize = SPA_OLD_MAXBLOCKSIZE;
 	}
 	dmu_tx_commit(tx);
 
--- a/usr/src/uts/common/inet/ilb/ilb.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/inet/ilb/ilb.c	Wed Nov 12 04:51:53 2014 -0800
@@ -24,6 +24,7 @@
  * Use is subject to license terms.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/kmem.h>
 #include <sys/ksynch.h>
 #include <sys/systm.h>
@@ -284,7 +285,7 @@
 	 * If ilbs->ilbs_rule_hash_size is not a power of 2, bump it up to
 	 * the next power of 2.
 	 */
-	if (ilbs->ilbs_rule_hash_size & (ilbs->ilbs_rule_hash_size - 1)) {
+	if (!ISP2(ilbs->ilbs_rule_hash_size)) {
 		for (i = 0; i < 31; i++) {
 			if (ilbs->ilbs_rule_hash_size < (1 << i))
 				break;
--- a/usr/src/uts/common/inet/ilb/ilb_conn.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/inet/ilb/ilb_conn.c	Wed Nov 12 04:51:53 2014 -0800
@@ -24,6 +24,7 @@
  * Use is subject to license terms.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/time.h>
@@ -300,7 +301,7 @@
 	 * If ilbs->ilbs_conn_hash_size is not a power of 2, bump it up to
 	 * the next power of 2.
 	 */
-	if (ilbs->ilbs_conn_hash_size & (ilbs->ilbs_conn_hash_size - 1)) {
+	if (!ISP2(ilbs->ilbs_conn_hash_size)) {
 		for (i = 0; i < 31; i++) {
 			if (ilbs->ilbs_conn_hash_size < (1 << i))
 				break;
@@ -1359,7 +1360,7 @@
 	char tq_name[TASKQ_NAMELEN];
 	ilb_timer_t *tm;
 
-	if (ilbs->ilbs_sticky_hash_size & (ilbs->ilbs_sticky_hash_size - 1)) {
+	if (!ISP2(ilbs->ilbs_sticky_hash_size)) {
 		for (i = 0; i < 31; i++) {
 			if (ilbs->ilbs_sticky_hash_size < (1 << i))
 				break;
--- a/usr/src/uts/common/inet/ip/ip.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/inet/ip/ip.c	Wed Nov 12 04:51:53 2014 -0800
@@ -12120,7 +12120,6 @@
 		    priority;
 	}
 	return (mp1);
-#undef rptr
 }
 
 /*
--- a/usr/src/uts/common/inet/sctp/sctp_hash.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/inet/sctp/sctp_hash.c	Wed Nov 12 04:51:53 2014 -0800
@@ -23,6 +23,7 @@
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/socket.h>
 #include <sys/ddi.h>
 #include <sys/sunddi.h>
@@ -66,7 +67,7 @@
 	/* Start with /etc/system value */
 	sctps->sctps_conn_hash_size = sctp_conn_hash_size;
 
-	if (sctps->sctps_conn_hash_size & (sctps->sctps_conn_hash_size - 1)) {
+	if (!ISP2(sctps->sctps_conn_hash_size)) {
 		/* Not a power of two. Round up to nearest power of two */
 		for (i = 0; i < 31; i++) {
 			if (sctps->sctps_conn_hash_size < (1 << i))
--- a/usr/src/uts/common/inet/udp/udp.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/inet/udp/udp.c	Wed Nov 12 04:51:53 2014 -0800
@@ -25,6 +25,7 @@
  */
 /* Copyright (c) 1990 Mentat Inc. */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/stropts.h>
@@ -4384,7 +4385,7 @@
 	us->us_bind_fanout_size = udp_bind_fanout_size;
 
 	/* Roundup variable that might have been modified in /etc/system */
-	if (us->us_bind_fanout_size & (us->us_bind_fanout_size - 1)) {
+	if (!ISP2(us->us_bind_fanout_size)) {
 		/* Not a power of two. Round up to nearest power of two */
 		for (i = 0; i < 31; i++) {
 			if (us->us_bind_fanout_size < (1 << i))
--- a/usr/src/uts/common/io/1394/t1394.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/1394/t1394.c	Wed Nov 12 04:51:53 2014 -0800
@@ -23,8 +23,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * t1394.c
  *    1394 Target Driver Interface
@@ -32,6 +30,7 @@
  *    by target drivers
  */
 
+#include <sys/sysmacros.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
 #include <sys/sunddi.h>
@@ -1909,7 +1908,7 @@
 	temp = props->cec_channel_mask;
 	if (props->cec_options & T1394_NO_IRM_ALLOC) {
 		/* If T1394_NO_IRM_ALLOC, then only one bit should be set */
-		if ((temp & (temp - 1)) != 0) {
+		if (!ISP2(temp)) {
 			TNF_PROBE_1(t1394_alloc_isoch_cec_error,
 			    S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
 			    "Invalid channel mask");
--- a/usr/src/uts/common/io/arn/arn_main.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/arn/arn_main.c	Wed Nov 12 04:51:53 2014 -0800
@@ -19,6 +19,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/signal.h>
@@ -2645,12 +2646,8 @@
 
 	/* set up supported mcs set */
 	(void) memset(&ht_info->rx_mcs_mask, 0, sizeof (ht_info->rx_mcs_mask));
-	tx_streams =
-	    !(sc->sc_ah->ah_caps.tx_chainmask &
-	    (sc->sc_ah->ah_caps.tx_chainmask - 1)) ? 1 : 2;
-	rx_streams =
-	    !(sc->sc_ah->ah_caps.rx_chainmask &
-	    (sc->sc_ah->ah_caps.rx_chainmask - 1)) ? 1 : 2;
+	tx_streams = ISP2(sc->sc_ah->ah_caps.tx_chainmask) ? 1 : 2;
+	rx_streams = ISP2(sc->sc_ah->ah_caps.rx_chainmask) ? 1 : 2;
 
 	ht_info->rx_mcs_mask[0] = 0xff;
 	if (rx_streams >= 2)
--- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c	Wed Nov 12 04:51:53 2014 -0800
@@ -25,6 +25,7 @@
  * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/conf.h>
 #include <sys/file.h>
 #include <sys/ddi.h>
@@ -1836,7 +1837,7 @@
 		sl->sl_flags |= SL_WRITE_PROTECTED;
 	}
 	if (slu->slu_blksize_valid) {
-		if ((slu->slu_blksize & (slu->slu_blksize - 1)) ||
+		if (!ISP2(slu->slu_blksize) ||
 		    (slu->slu_blksize > (32 * 1024)) ||
 		    (slu->slu_blksize == 0)) {
 			*err_ret = SBD_RET_INVALID_BLKSIZE;
--- a/usr/src/uts/common/io/comstar/port/fct/discovery.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/comstar/port/fct/discovery.c	Wed Nov 12 04:51:53 2014 -0800
@@ -22,6 +22,7 @@
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/conf.h>
 #include <sys/file.h>
 #include <sys/ddi.h>
@@ -219,7 +220,7 @@
 		(void) strcpy(topology, topologies[li->port_topology]);
 	}
 
-	if ((s == 0) || ((s & 0xf00) != 0) || ((s & (s - 1)) != 0)) {
+	if ((s == 0) || ((s & 0xf00) != 0) || !ISP2(s)) {
 		speed[0] = '?';
 	} else if (s == PORT_SPEED_10G) {
 		speed[0] = '1';
--- a/usr/src/uts/common/io/drm/drmP.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/drm/drmP.h	Wed Nov 12 04:51:53 2014 -0800
@@ -41,6 +41,7 @@
 #ifndef	_DRMP_H
 #define	_DRMP_H
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/modctl.h>
@@ -326,9 +327,6 @@
 
 #define	__OS_HAS_AGP	1
 
-#define	__offsetof(type, field) ((size_t)(&((type *)0)->field))
-#define	offsetof(type, field)   __offsetof(type, field)
-
 typedef struct drm_pci_id_list
 {
 	int vendor;
--- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_cfg.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_cfg.c	Wed Nov 12 04:51:53 2014 -0800
@@ -31,6 +31,7 @@
  *    down the list of Hermon configuration information.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
@@ -437,7 +438,7 @@
 	 */
 	max_size = (HERMON_QP_WQE_MLX_QP1_HDRS + (max_sgl << 4));
 	log2 = highbit(max_size);
-	if ((max_size & (max_size - 1)) == 0) {
+	if (ISP2(max_size)) {
 		log2 = log2 - 1;
 	}
 	max_size = (1 << log2);
--- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_qp.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_qp.c	Wed Nov 12 04:51:53 2014 -0800
@@ -404,13 +404,12 @@
 	 */
 	log_qp_sq_size = highbit(attr_p->qp_sizes.cs_sq + qp->qp_sq_hdrmwqes);
 	/* if the total is a power of two, reduce it */
-	if (((attr_p->qp_sizes.cs_sq + qp->qp_sq_hdrmwqes)  &
-	    (attr_p->qp_sizes.cs_sq + qp->qp_sq_hdrmwqes - 1)) == 0)	{
+	if (ISP2(attr_p->qp_sizes.cs_sq + qp->qp_sq_hdrmwqes))	{
 		log_qp_sq_size = log_qp_sq_size - 1;
 	}
 
 	log_qp_rq_size = highbit(attr_p->qp_sizes.cs_rq);
-	if ((attr_p->qp_sizes.cs_rq & (attr_p->qp_sizes.cs_rq - 1)) == 0) {
+	if (ISP2(attr_p->qp_sizes.cs_rq)) {
 		log_qp_rq_size = log_qp_rq_size - 1;
 	}
 
@@ -921,11 +920,11 @@
 	attr_p->qp_sizes.cs_rq =
 	    max(attr_p->qp_sizes.cs_rq, HERMON_QP_MIN_SIZE);
 	log_qp_sq_size = highbit(attr_p->qp_sizes.cs_sq);
-	if ((attr_p->qp_sizes.cs_sq & (attr_p->qp_sizes.cs_sq - 1)) == 0) {
+	if (ISP2(attr_p->qp_sizes.cs_sq)) {
 		log_qp_sq_size = log_qp_sq_size - 1;
 	}
 	log_qp_rq_size = highbit(attr_p->qp_sizes.cs_rq);
-	if ((attr_p->qp_sizes.cs_rq & (attr_p->qp_sizes.cs_rq - 1)) == 0) {
+	if (ISP2(attr_p->qp_sizes.cs_rq)) {
 		log_qp_rq_size = log_qp_rq_size - 1;
 	}
 
@@ -1521,13 +1520,12 @@
 	 */
 	log_qp_sq_size = highbit(attr_p->qp_sizes.cs_sq + qp->qp_sq_hdrmwqes);
 	/* if the total is a power of two, reduce it */
-	if (((attr_p->qp_sizes.cs_sq + qp->qp_sq_hdrmwqes)  &
-	    (attr_p->qp_sizes.cs_sq + qp->qp_sq_hdrmwqes - 1)) == 0)	{
+	if (ISP2(attr_p->qp_sizes.cs_sq + qp->qp_sq_hdrmwqes))	{
 		log_qp_sq_size = log_qp_sq_size - 1;
 	}
 
 	log_qp_rq_size = highbit(attr_p->qp_sizes.cs_rq);
-	if ((attr_p->qp_sizes.cs_rq & (attr_p->qp_sizes.cs_rq - 1)) == 0) {
+	if (ISP2(attr_p->qp_sizes.cs_rq)) {
 		log_qp_rq_size = log_qp_rq_size - 1;
 	}
 
@@ -2831,7 +2829,7 @@
 		 */
 		max_size = (HERMON_QP_WQE_MLX_SND_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
@@ -2851,7 +2849,7 @@
 		 */
 		max_size = (HERMON_QP_WQE_MLX_SND_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
@@ -2868,7 +2866,7 @@
 		 */
 		max_size = (HERMON_QP_WQE_MLX_RCV_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
@@ -2888,7 +2886,7 @@
 		 */
 		max_size = (HERMON_QP_WQE_MLX_QP0_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
@@ -2910,7 +2908,7 @@
 		 */
 		max_size = (HERMON_QP_WQE_MLX_QP1_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
--- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_qpmod.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_qpmod.c	Wed Nov 12 04:51:53 2014 -0800
@@ -33,6 +33,7 @@
  *    and Error.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
@@ -3375,7 +3376,7 @@
 	if (rdma_ra_in == 0) {
 		rdma_ra_in = 1;
 	}
-	if ((rdma_ra_in & (rdma_ra_in - 1)) == 0) {
+	if (ISP2(rdma_ra_in)) {
 		*rra_max = highbit(rdma_ra_in) - 1;
 	} else {
 		*rra_max = highbit(rdma_ra_in);
@@ -3411,7 +3412,7 @@
 	if (rdma_ra_out == 0) {
 		rdma_ra_out = 1;
 	}
-	if ((rdma_ra_out & (rdma_ra_out - 1)) == 0) {
+	if (ISP2(rdma_ra_out)) {
 		*sra_max = highbit(rdma_ra_out) - 1;
 	} else {
 		*sra_max = highbit(rdma_ra_out);
--- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_rsrc.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_rsrc.c	Wed Nov 12 04:51:53 2014 -0800
@@ -32,6 +32,7 @@
  *    by Hermon hardware or which live in Hermon's direct attached DDR memory.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
@@ -2666,7 +2667,7 @@
 	 */
 	num_qp_per_mcg = state->hs_cfg_profile->cp_num_qp_per_mcg + 8;
 	log2 = highbit(num_qp_per_mcg);
-	if ((num_qp_per_mcg & (num_qp_per_mcg - 1)) == 0) {
+	if (ISP2(num_qp_per_mcg)) {
 		log2 = log2 - 1;
 	}
 	state->hs_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
--- a/usr/src/uts/common/io/ib/adapters/hermon/hermon_srq.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/hermon/hermon_srq.c	Wed Nov 12 04:51:53 2014 -0800
@@ -31,6 +31,7 @@
  *    modifying and posting shared receive queues.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
@@ -174,7 +175,7 @@
 	 */
 	srq_wr_sz = max(sizes->srq_wr_sz + 1, HERMON_SRQ_MIN_SIZE);
 	log_srq_size = highbit(srq_wr_sz);
-	if ((srq_wr_sz & (srq_wr_sz - 1)) == 0) {
+	if (ISP2(srq_wr_sz)) {
 		log_srq_size = log_srq_size - 1;
 	}
 
@@ -623,7 +624,7 @@
 	 */
 	size = max(size, HERMON_SRQ_MIN_SIZE);
 	log_srq_size = highbit(size);
-	if ((size & (size - 1)) == 0) {
+	if (ISP2(size)) {
 		log_srq_size = log_srq_size - 1;
 	}
 
@@ -974,7 +975,7 @@
 		 */
 		max_size = (HERMON_QP_WQE_MLX_SRQ_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
--- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_cfg.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_cfg.c	Wed Nov 12 04:51:53 2014 -0800
@@ -32,6 +32,7 @@
  *    down the list of Tavor configuration information.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
@@ -657,7 +658,7 @@
 	 */
 	max_size = (TAVOR_QP_WQE_MLX_QP1_HDRS + (max_sgl << 4));
 	log2 = highbit(max_size);
-	if ((max_size & (max_size - 1)) == 0) {
+	if (ISP2(max_size)) {
 		log2 = log2 - 1;
 	}
 	max_size = (1 << log2);
--- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_qp.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_qp.c	Wed Nov 12 04:51:53 2014 -0800
@@ -317,11 +317,11 @@
 	attr_p->qp_sizes.cs_sq = max(attr_p->qp_sizes.cs_sq, TAVOR_QP_MIN_SIZE);
 	attr_p->qp_sizes.cs_rq = max(attr_p->qp_sizes.cs_rq, TAVOR_QP_MIN_SIZE);
 	log_qp_sq_size = highbit(attr_p->qp_sizes.cs_sq);
-	if ((attr_p->qp_sizes.cs_sq & (attr_p->qp_sizes.cs_sq - 1)) == 0) {
+	if (ISP2(attr_p->qp_sizes.cs_sq)) {
 		log_qp_sq_size = log_qp_sq_size - 1;
 	}
 	log_qp_rq_size = highbit(attr_p->qp_sizes.cs_rq);
-	if ((attr_p->qp_sizes.cs_rq & (attr_p->qp_sizes.cs_rq - 1)) == 0) {
+	if (ISP2(attr_p->qp_sizes.cs_rq)) {
 		log_qp_rq_size = log_qp_rq_size - 1;
 	}
 
@@ -803,11 +803,11 @@
 	attr_p->qp_sizes.cs_sq = max(attr_p->qp_sizes.cs_sq, TAVOR_QP_MIN_SIZE);
 	attr_p->qp_sizes.cs_rq = max(attr_p->qp_sizes.cs_rq, TAVOR_QP_MIN_SIZE);
 	log_qp_sq_size = highbit(attr_p->qp_sizes.cs_sq);
-	if ((attr_p->qp_sizes.cs_sq & (attr_p->qp_sizes.cs_sq - 1)) == 0) {
+	if (ISP2(attr_p->qp_sizes.cs_sq)) {
 		log_qp_sq_size = log_qp_sq_size - 1;
 	}
 	log_qp_rq_size = highbit(attr_p->qp_sizes.cs_rq);
-	if ((attr_p->qp_sizes.cs_rq & (attr_p->qp_sizes.cs_rq - 1)) == 0) {
+	if (ISP2(attr_p->qp_sizes.cs_rq)) {
 		log_qp_rq_size = log_qp_rq_size - 1;
 	}
 
@@ -1991,7 +1991,7 @@
 		 */
 		max_size = (TAVOR_QP_WQE_MLX_SND_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
@@ -2008,7 +2008,7 @@
 		 */
 		max_size = (TAVOR_QP_WQE_MLX_RCV_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
@@ -2028,7 +2028,7 @@
 		 */
 		max_size = (TAVOR_QP_WQE_MLX_QP0_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
@@ -2050,7 +2050,7 @@
 		 */
 		max_size = (TAVOR_QP_WQE_MLX_QP1_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
--- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_qpmod.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_qpmod.c	Wed Nov 12 04:51:53 2014 -0800
@@ -33,6 +33,7 @@
  *    and from Reset, Init, RTR, RTS, SQD, SQErr, and Error.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
@@ -3438,7 +3439,7 @@
 	if (rdma_ra_in == 0) {
 		rdma_ra_in = 1;
 	}
-	if ((rdma_ra_in & (rdma_ra_in - 1)) == 0) {
+	if (ISP2(rdma_ra_in)) {
 		*rra_max = highbit(rdma_ra_in) - 1;
 	} else {
 		*rra_max = highbit(rdma_ra_in);
@@ -3474,7 +3475,7 @@
 	if (rdma_ra_out == 0) {
 		rdma_ra_out = 1;
 	}
-	if ((rdma_ra_out & (rdma_ra_out - 1)) == 0) {
+	if (ISP2(rdma_ra_out)) {
 		*sra_max = highbit(rdma_ra_out) - 1;
 	} else {
 		*sra_max = highbit(rdma_ra_out);
--- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_rsrc.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_rsrc.c	Wed Nov 12 04:51:53 2014 -0800
@@ -33,6 +33,7 @@
  *    by Tavor hardware or which live in Tavor's direct attached DDR memory.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
@@ -2885,7 +2886,7 @@
 	 */
 	num_qp_per_mcg = state->ts_cfg_profile->cp_num_qp_per_mcg + 8;
 	log2 = highbit(num_qp_per_mcg);
-	if ((num_qp_per_mcg & (num_qp_per_mcg - 1)) == 0) {
+	if (ISP2(num_qp_per_mcg)) {
 		log2 = log2 - 1;
 	}
 	state->ts_cfg_profile->cp_num_qp_per_mcg = (1 << log2) - 8;
--- a/usr/src/uts/common/io/ib/adapters/tavor/tavor_srq.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/adapters/tavor/tavor_srq.c	Wed Nov 12 04:51:53 2014 -0800
@@ -32,6 +32,7 @@
  *    modifying and posting shared receive queues.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/ddi.h>
@@ -172,7 +173,7 @@
 	 */
 	sizes->srq_wr_sz = max(sizes->srq_wr_sz, TAVOR_SRQ_MIN_SIZE);
 	log_srq_size = highbit(sizes->srq_wr_sz);
-	if ((sizes->srq_wr_sz & (sizes->srq_wr_sz - 1)) == 0) {
+	if (ISP2(sizes->srq_wr_sz)) {
 		log_srq_size = log_srq_size - 1;
 	}
 
@@ -686,7 +687,7 @@
 	 */
 	size = max(size, TAVOR_SRQ_MIN_SIZE);
 	log_srq_size = highbit(size);
-	if ((size & (size - 1)) == 0) {
+	if (ISP2(size)) {
 		log_srq_size = log_srq_size - 1;
 	}
 
@@ -1099,7 +1100,7 @@
 		 */
 		max_size = (TAVOR_QP_WQE_MLX_RCV_HDRS + (num_sgl << 4));
 		log2 = highbit(max_size);
-		if ((max_size & (max_size - 1)) == 0) {
+		if (ISP2(max_size)) {
 			log2 = log2 - 1;
 		}
 
--- a/usr/src/uts/common/io/ib/clients/rds/rdssubr.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ib/clients/rds/rdssubr.c	Wed Nov 12 04:51:53 2014 -0800
@@ -23,6 +23,7 @@
  * Use is subject to license terms.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/ib/clients/rds/rds.h>
 #include <sys/ib/clients/rds/rds_kstat.h>
 
@@ -149,7 +150,7 @@
 {
 	int i;
 
-	if (rds_bind_fanout_size & (rds_bind_fanout_size - 1)) {
+	if (!ISP2(rds_bind_fanout_size)) {
 		/* Not a power of two. Round up to nearest power of two */
 		for (i = 0; i < UINT_32_BITS; i++) {
 			if (rds_bind_fanout_size < (1 << i))
--- a/usr/src/uts/common/io/myri10ge/drv/myri10ge.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/myri10ge/drv/myri10ge.c	Wed Nov 12 04:51:53 2014 -0800
@@ -2138,7 +2138,7 @@
 	 * buffer/pkt, and the mtu will prevent overruns
 	 */
 	big_pow2 = myri10ge_mtu + MXGEFW_PAD;
-	while ((big_pow2 & (big_pow2 - 1)) != 0)
+	while (!ISP2(big_pow2))
 		big_pow2++;
 
 	/* now give firmware buffers sizes, and MTU */
@@ -5437,7 +5437,7 @@
 	 */
 	while (mgp->num_slices > 1) {
 		/* make sure it is a power of two */
-		while (mgp->num_slices & (mgp->num_slices - 1))
+		while (!ISP2(mgp->num_slices))
 			mgp->num_slices--;
 		if (mgp->num_slices == 1)
 			return (0);
--- a/usr/src/uts/common/io/ntxn/unm_gem.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/io/ntxn/unm_gem.c	Wed Nov 12 04:51:53 2014 -0800
@@ -725,8 +725,7 @@
 
 	tx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 	    txringsize_propname, MAX_CMD_DESCRIPTORS_HOST);
-	if (tx_desc >= 256 && tx_desc <= MAX_CMD_DESCRIPTORS &&
-	    !(tx_desc & (tx_desc - 1))) {
+	if (tx_desc >= 256 && tx_desc <= MAX_CMD_DESCRIPTORS && ISP2(tx_desc)) {
 		adapter->MaxTxDescCount = tx_desc;
 	} else {
 		cmn_err(CE_WARN, "%s%d: TxRingSize defaulting to %d, since "
@@ -739,8 +738,7 @@
 	rx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 	    rxringsize_propname, maxrx);
 	if (rx_desc >= NX_MIN_DRIVER_RDS_SIZE &&
-	    rx_desc <= NX_MAX_SUPPORTED_RDS_SIZE &&
-	    !(rx_desc & (rx_desc - 1))) {
+	    rx_desc <= NX_MAX_SUPPORTED_RDS_SIZE && ISP2(rx_desc)) {
 		adapter->MaxRxDescCount = rx_desc;
 	} else {
 		cmn_err(CE_WARN, "%s%d: RxRingSize defaulting to %d, since "
@@ -753,8 +751,7 @@
 	rx_jdesc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 	    jumborxringsize_propname, MAX_JUMBO_RCV_DESCRIPTORS);
 	if (rx_jdesc >= NX_MIN_DRIVER_RDS_SIZE &&
-	    rx_jdesc <= NX_MAX_SUPPORTED_JUMBO_RDS_SIZE &&
-	    !(rx_jdesc & (rx_jdesc - 1))) {
+	    rx_jdesc <= NX_MAX_SUPPORTED_JUMBO_RDS_SIZE && ISP2(rx_jdesc)) {
 		adapter->MaxJumboRxDescCount = rx_jdesc;
 	} else {
 		cmn_err(CE_WARN, "%s%d: JumboRingSize defaulting to %d, since "
--- a/usr/src/uts/common/krtld/kobj.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/krtld/kobj.c	Wed Nov 12 04:51:53 2014 -0800
@@ -3787,7 +3787,7 @@
 	hdr = kobj_comphdr(file);
 	if (hdr->ch_magic != CH_MAGIC_ZLIB || hdr->ch_version != CH_VERSION ||
 	    hdr->ch_algorithm != CH_ALG_ZLIB || hdr->ch_fsize == 0 ||
-	    (hdr->ch_blksize & (hdr->ch_blksize - 1)) != 0) {
+	    !ISP2(hdr->ch_blksize)) {
 		kobj_free(file->_dbuf, cip->fsize);
 		return (-1);
 	}
--- a/usr/src/uts/common/os/cpu.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/cpu.c	Wed Nov 12 04:51:53 2014 -0800
@@ -167,13 +167,12 @@
 	int		cp_count;	/* # of CPUs to pause */
 	ksema_t		cp_sem;		/* synch pause_cpus & cpu_pause */
 	kthread_id_t	cp_paused;
+	void		*(*cp_func)(void *);
 } cpu_pause_info;
 
 static kmutex_t pause_free_mutex;
 static kcondvar_t pause_free_cv;
 
-void *(*cpu_pause_func)(void *) = NULL;
-
 
 static struct cpu_sys_stats_ks_data {
 	kstat_named_t cpu_ticks_idle;
@@ -792,15 +791,15 @@
 		 */
 		s = splhigh();
 		/*
-		 * if cpu_pause_func() has been set then call it using
-		 * index as the argument, currently only used by
-		 * cpr_suspend_cpus().  This function is used as the
-		 * code to execute on the "paused" cpu's when a machine
-		 * comes out of a sleep state and CPU's were powered off.
-		 * (could also be used for hotplugging CPU's).
+		 * if cp_func has been set then call it using index as the
+		 * argument, currently only used by cpr_suspend_cpus().
+		 * This function is used as the code to execute on the
+		 * "paused" cpu's when a machine comes out of a sleep state
+		 * and CPU's were powered off.  (could also be used for
+		 * hotplugging CPU's).
 		 */
-		if (cpu_pause_func != NULL)
-			(*cpu_pause_func)((void *)lindex);
+		if (cpi->cp_func != NULL)
+			(*cpi->cp_func)((void *)lindex);
 
 		mach_cpu_pause(safe);
 
@@ -988,7 +987,7 @@
  * context.
  */
 void
-pause_cpus(cpu_t *off_cp)
+pause_cpus(cpu_t *off_cp, void *(*func)(void *))
 {
 	processorid_t	cpu_id;
 	int		i;
@@ -1002,6 +1001,8 @@
 		safe_list[i] = PAUSE_IDLE;
 	kpreempt_disable();
 
+	cpi->cp_func = func;
+
 	/*
 	 * If running on the cpu that is going offline, get off it.
 	 * This is so that it won't be necessary to rechoose a CPU
@@ -1206,7 +1207,7 @@
 	error = mp_cpu_start(cp);	/* arch-dep hook */
 	if (error == 0) {
 		pg_cpupart_in(cp, cp->cpu_part);
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 		cpu_add_active_internal(cp);
 		if (cp->cpu_flags & CPU_FAULTED) {
 			cp->cpu_flags &= ~CPU_FAULTED;
@@ -1405,7 +1406,7 @@
 		 * Put all the cpus into a known safe place.
 		 * No mutexes can be entered while CPUs are paused.
 		 */
-		pause_cpus(cp);
+		pause_cpus(cp, NULL);
 		/*
 		 * Repeat the operation, if necessary, to make sure that
 		 * all outstanding low-level interrupts run to completion
@@ -1758,7 +1759,7 @@
 	 * adding the cpu to the list.
 	 */
 	cp->cpu_part = &cp_default;
-	(void) pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	cp->cpu_next = cpu_list;
 	cp->cpu_prev = cpu_list->cpu_prev;
 	cpu_list->cpu_prev->cpu_next = cp;
@@ -1853,7 +1854,7 @@
 	 * has been updated so that we don't waste time
 	 * trying to pause the cpu we're trying to delete.
 	 */
-	(void) pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 
 	cpnext = cp->cpu_next;
 	cp->cpu_prev->cpu_next = cp->cpu_next;
@@ -1925,7 +1926,7 @@
 {
 	pg_cpupart_in(cp, cp->cpu_part);
 
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	cpu_add_active_internal(cp);
 	start_cpus();
 
--- a/usr/src/uts/common/os/cpu_event.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/cpu_event.c	Wed Nov 12 04:51:53 2014 -0800
@@ -396,7 +396,7 @@
 	 * after pause_cpus().
 	 */
 	if (!cpus_paused()) {
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 		unpause = 1;
 	}
 
@@ -462,7 +462,7 @@
 	 * after pause_cpus().
 	 */
 	if (!cpus_paused()) {
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 		unpause = 1;
 	}
 
--- a/usr/src/uts/common/os/cpu_pm.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/cpu_pm.c	Wed Nov 12 04:51:53 2014 -0800
@@ -188,7 +188,7 @@
 	 */
 	switch (new_policy) {
 	case CPUPM_POLICY_DISABLED:
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 		cpupm_policy = CPUPM_POLICY_DISABLED;
 		start_cpus();
 
@@ -228,7 +228,7 @@
 			gov_init = 1;
 		}
 
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 		cpupm_policy = CPUPM_POLICY_ELASTIC;
 		start_cpus();
 
--- a/usr/src/uts/common/os/group.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/group.c	Wed Nov 12 04:51:53 2014 -0800
@@ -23,6 +23,7 @@
  * Use is subject to license terms.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/systm.h>
 #include <sys/param.h>
 #include <sys/debug.h>
@@ -131,8 +132,7 @@
 	g->grp_size--;
 
 	if ((gflag & GRP_RESIZE) &&
-	    g->grp_size > GRP_SET_SIZE_DEFAULT &&
-	    ((g->grp_size - 1) & g->grp_size) == 0)
+	    g->grp_size > GRP_SET_SIZE_DEFAULT && ISP2(g->grp_size))
 		group_shrink_set(g);
 
 	return (0);
--- a/usr/src/uts/common/os/kmem.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/kmem.c	Wed Nov 12 04:51:53 2014 -0800
@@ -3766,7 +3766,7 @@
 	if (align < KMEM_ALIGN)
 		cflags |= KMC_NOTOUCH;
 
-	if ((align & (align - 1)) != 0 || align > vmp->vm_quantum)
+	if (!ISP2(align) || align > vmp->vm_quantum)
 		panic("kmem_cache_create: bad alignment %lu", align);
 
 	mutex_enter(&kmem_flags_lock);
--- a/usr/src/uts/common/os/lgrp.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/lgrp.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1297,7 +1297,7 @@
 		klgrpset_add(my_lgrp->lgrp_set[LGRP_RSRC_MEM], lgrpid);
 
 		if (need_synch)
-			pause_cpus(NULL);
+			pause_cpus(NULL, NULL);
 		count = lgrp_leaf_add(my_lgrp, lgrp_table, lgrp_alloc_max + 1,
 		    &changed);
 		if (need_synch)
@@ -1316,7 +1316,7 @@
 		    lgrpid))
 			klgrpset_add(my_lgrp->lgrp_set[LGRP_RSRC_MEM], lgrpid);
 		if (need_synch)
-			pause_cpus(NULL);
+			pause_cpus(NULL, NULL);
 		count = lgrp_leaf_add(my_lgrp, lgrp_table, lgrp_alloc_max + 1,
 		    &changed);
 		if (need_synch)
@@ -1477,7 +1477,7 @@
 		 * Delete lgroup when no more resources
 		 */
 		if (need_synch)
-			pause_cpus(NULL);
+			pause_cpus(NULL, NULL);
 		count = lgrp_leaf_delete(my_lgrp, lgrp_table,
 		    lgrp_alloc_max + 1, &changed);
 		ASSERT(count > 0);
--- a/usr/src/uts/common/os/lgrp_topo.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/lgrp_topo.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1480,7 +1480,7 @@
 	}
 
 	mutex_enter(&cpu_lock);
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 
 	/*
 	 * Look for any leaf lgroup without its latency set, finish adding it
--- a/usr/src/uts/common/os/mem_config.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/mem_config.c	Wed Nov 12 04:51:53 2014 -0800
@@ -3302,7 +3302,7 @@
 	vm_cpu_data_t *vc;
 
 	mutex_enter(&cpu_lock);
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 
 	cp = cpu_list;
 	do {
--- a/usr/src/uts/common/os/vmem.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/os/vmem.c	Wed Nov 12 04:51:53 2014 -0800
@@ -920,7 +920,7 @@
 	int flist = 0;
 	ASSERT(MUTEX_HELD(&vmp->vm_lock));
 
-	if ((size & (size - 1)) == 0)
+	if (ISP2(size))
 		flist = lowbit(P2ALIGN(vmp->vm_freemap, size));
 	else if ((hb = highbit(size)) < VMEM_FREELISTS)
 		flist = lowbit(P2ALIGN(vmp->vm_freemap, 1UL << hb));
@@ -959,8 +959,7 @@
 		    (void *)vmp, size, align_arg, phase, nocross,
 		    minaddr, maxaddr, vmflag);
 
-	if (phase >= align || (align & (align - 1)) != 0 ||
-	    (nocross & (nocross - 1)) != 0)
+	if (phase >= align || !ISP2(align) || !ISP2(nocross))
 		panic("vmem_xalloc(%p, %lu, %lu, %lu, %lu, %p, %p, %x): "
 		    "parameters inconsistent or invalid",
 		    (void *)vmp, size, align_arg, phase, nocross,
@@ -994,7 +993,7 @@
 		 *
 		 * (4)	We're doing a best-fit or first-fit allocation.
 		 */
-		if ((size & (size - 1)) == 0) {
+		if (ISP2(size)) {
 			flist = lowbit(P2ALIGN(vmp->vm_freemap, size));
 		} else {
 			hb = highbit(size);
@@ -1290,7 +1289,7 @@
 	mutex_enter(&vmp->vm_lock);
 
 	if (vmp->vm_nsegfree >= VMEM_MINFREE || vmem_populate(vmp, vmflag)) {
-		if ((size & (size - 1)) == 0)
+		if (ISP2(size))
 			flist = lowbit(P2ALIGN(vmp->vm_freemap, size));
 		else if ((hb = highbit(size)) < VMEM_FREELISTS)
 			flist = lowbit(P2ALIGN(vmp->vm_freemap, 1UL << hb));
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h	Wed Nov 12 04:51:53 2014 -0800
@@ -882,6 +882,8 @@
 #define	SMB_SESSION_VALID(p)	\
     ASSERT(((p) != NULL) && ((p)->s_magic == SMB_SESSION_MAGIC))
 
+#define	SMB_CHALLENGE_SZ	8
+
 typedef enum {
 	SMB_SESSION_STATE_INITIALIZED = 0,
 	SMB_SESSION_STATE_DISCONNECTED,
@@ -939,7 +941,7 @@
 	uint16_t		secmode;
 	uint32_t		sesskey;
 	uint32_t		challenge_len;
-	unsigned char		challenge_key[8];
+	unsigned char		challenge_key[SMB_CHALLENGE_SZ];
 	unsigned char		MAC_key[44];
 	int64_t			activity_timestamp;
 	/*
--- a/usr/src/uts/common/sys/cpuvar.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/sys/cpuvar.h	Wed Nov 12 04:51:53 2014 -0800
@@ -652,7 +652,7 @@
 
 void	mach_cpu_pause(volatile char *);
 
-void	pause_cpus(cpu_t *off_cp);
+void	pause_cpus(cpu_t *off_cp, void *(*func)(void *));
 void	start_cpus(void);
 int	cpus_paused(void);
 
--- a/usr/src/uts/common/sys/fs/zfs.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/sys/fs/zfs.h	Wed Nov 12 04:51:53 2014 -0800
@@ -192,6 +192,7 @@
 	ZPOOL_PROP_FREEING,
 	ZPOOL_PROP_FRAGMENTATION,
 	ZPOOL_PROP_LEAKED,
+	ZPOOL_PROP_MAXBLOCKSIZE,
 	ZPOOL_NUM_PROPS
 } zpool_prop_t;
 
--- a/usr/src/uts/common/vm/seg_kmem.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/vm/seg_kmem.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1288,10 +1288,10 @@
 			 * backoff at trying large pages and reaping
 			 */
 			if (lpthrt > segkmem_lpthrottle_start &&
-			    (lpthrt & (lpthrt - 1))) {
+			    !ISP2(lpthrt)) {
 				lpcb->allocs_throttled++;
 				lpthrt--;
-				if ((lpthrt & (lpthrt - 1)) == 0)
+				if (ISP2(lpthrt))
 					kmem_reap();
 				return (segkmem_alloc(vmp, size, vmflag));
 			}
@@ -1475,15 +1475,13 @@
 	}
 
 	/* set heap_lp quantum if necessary */
-	if (segkmem_heaplp_quantum == 0 ||
-	    (segkmem_heaplp_quantum & (segkmem_heaplp_quantum - 1)) ||
+	if (segkmem_heaplp_quantum == 0 || !ISP2(segkmem_heaplp_quantum) ||
 	    P2PHASE(segkmem_heaplp_quantum, segkmem_lpsize)) {
 		segkmem_heaplp_quantum = segkmem_lpsize;
 	}
 
 	/* set kmem_lp quantum if necessary */
-	if (segkmem_kmemlp_quantum == 0 ||
-	    (segkmem_kmemlp_quantum & (segkmem_kmemlp_quantum - 1)) ||
+	if (segkmem_kmemlp_quantum == 0 || !ISP2(segkmem_kmemlp_quantum) ||
 	    segkmem_kmemlp_quantum > segkmem_heaplp_quantum) {
 		segkmem_kmemlp_quantum = segkmem_heaplp_quantum;
 	}
--- a/usr/src/uts/common/vm/seg_map.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/vm/seg_map.c	Wed Nov 12 04:51:53 2014 -0800
@@ -337,7 +337,7 @@
 		"%d, using %d", nfreelist, max_ncpus);
 		nfreelist = max_ncpus;
 	}
-	if (nfreelist & (nfreelist - 1)) {
+	if (!ISP2(nfreelist)) {
 		/* round up nfreelist to the next power of two. */
 		nfreelist = 1 << (highbit(nfreelist));
 	}
--- a/usr/src/uts/common/vm/vpm.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/common/vm/vpm.c	Wed Nov 12 04:51:53 2014 -0800
@@ -205,7 +205,7 @@
 	/*
 	 * Round it up to the next power of 2
 	 */
-	if (vpm_nfreelist & (vpm_nfreelist - 1)) {
+	if (!ISP2(vpm_nfreelist)) {
 		vpm_nfreelist = 1 << (highbit(vpm_nfreelist));
 	}
 	vpmd_freemsk = vpm_nfreelist - 1;
--- a/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c	Wed Nov 12 04:51:53 2014 -0800
@@ -472,7 +472,7 @@
 	kpreempt_disable();
 
 	if (ncpus > 1)
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 	/*
 	 * We can grab the ec_lock as it's a spinlock with a high SPL. Hence
 	 * any holder would have dropped it to get through pause_cpus().
--- a/usr/src/uts/i86pc/io/acpi/drmach_acpi/drmach_acpi.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/io/acpi/drmach_acpi/drmach_acpi.c	Wed Nov 12 04:51:53 2014 -0800
@@ -895,7 +895,7 @@
 		    "(%d) physical processors on one board.",
 		    MAX_CMP_UNITS_PER_BOARD);
 		return (ENXIO);
-	} else if (MAX_CORES_PER_CMP & (MAX_CORES_PER_CMP - 1)) {
+	} else if (!ISP2(MAX_CORES_PER_CMP)) {
 		cmn_err(CE_WARN, "!drmach_init: number of logical CPUs (%d) in "
 		    "physical processor is not power of 2.",
 		    MAX_CORES_PER_CMP);
--- a/usr/src/uts/i86pc/io/dr/dr_quiesce.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/io/dr/dr_quiesce.c	Wed Nov 12 04:51:53 2014 -0800
@@ -872,7 +872,7 @@
 	srh->sr_suspend_state = DR_SRSTATE_FULL;
 
 	mutex_enter(&cpu_lock);
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	dr_stop_intr();
 
 	return (rc);
--- a/usr/src/uts/i86pc/io/pci/pci_tools.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/io/pci/pci_tools.c	Wed Nov 12 04:51:53 2014 -0800
@@ -22,6 +22,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/mkdev.h>
 #include <sys/stat.h>
@@ -588,7 +589,7 @@
 	pci_cfgacc_req_t req;
 	uint32_t max_offset;
 
-	if ((size <= 0) || (size > 8) || ((size & (size - 1)) != 0)) {
+	if ((size <= 0) || (size > 8) || !ISP2(size)) {
 		prg->status = PCITOOL_INVALID_SIZE;
 		return (ENOTSUP);
 	}
--- a/usr/src/uts/i86pc/io/ppm/acpisleep.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/io/ppm/acpisleep.c	Wed Nov 12 04:51:53 2014 -0800
@@ -70,8 +70,6 @@
 extern int tsc_gethrtime_enable;
 
 extern cpuset_t cpu_ready_set;
-extern void *(*cpu_pause_func)(void *);
-
 
 
 /*
--- a/usr/src/uts/i86pc/io/rootnex.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/io/rootnex.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1811,7 +1811,7 @@
 	 * granularity may or may not be a power of two. If it isn't, we can't
 	 * use a simple mask.
 	 */
-	if (attr->dma_attr_granular & (attr->dma_attr_granular - 1)) {
+	if (!ISP2(attr->dma_attr_granular)) {
 		dma->dp_granularity_power_2 = B_FALSE;
 	} else {
 		dma->dp_granularity_power_2 = B_TRUE;
@@ -3869,7 +3869,7 @@
 #endif /* __amd64 */
 
 		/* figure out if the copybuf size is a power of 2 */
-		if (dma->dp_copybuf_size & (dma->dp_copybuf_size - 1)) {
+		if (!ISP2(dma->dp_copybuf_size)) {
 			copybuf_sz_power_2 = B_FALSE;
 		} else {
 			copybuf_sz_power_2 = B_TRUE;
--- a/usr/src/uts/i86pc/os/cpr_impl.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/os/cpr_impl.c	Wed Nov 12 04:51:53 2014 -0800
@@ -737,7 +737,7 @@
 		mutex_exit(&cpu_lock);
 		return;
 	}
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	cpu_are_paused = 1;
 
 	mutex_exit(&cpu_lock);
--- a/usr/src/uts/i86pc/os/ddi_impl.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/os/ddi_impl.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1536,7 +1536,7 @@
 	 * the attributes leads to a failure.
 	 */
 	uint_t cache_attr = IOMEM_CACHE_ATTR(flags);
-	if ((cache_attr != 0) && ((cache_attr & (cache_attr - 1)) != 0))
+	if ((cache_attr != 0) && !ISP2(cache_attr))
 		return (B_FALSE);
 
 	/* All cache attributes are supported on X86/X64 */
@@ -1627,9 +1627,8 @@
 	}
 
 	if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 ||
-	    (attr->dma_attr_align & (attr->dma_attr_align - 1)) ||
-	    (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) {
-			return (DDI_FAILURE);
+	    !ISP2(attr->dma_attr_align) || !ISP2(attr->dma_attr_minxfer)) {
+		return (DDI_FAILURE);
 	}
 
 	/*
--- a/usr/src/uts/i86pc/os/machdep.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/os/machdep.c	Wed Nov 12 04:51:53 2014 -0800
@@ -283,7 +283,7 @@
 	(void) spl6();
 	if (!panicstr) {
 		mutex_enter(&cpu_lock);
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 		mutex_exit(&cpu_lock);
 	}
 
--- a/usr/src/uts/i86pc/os/mp_pc.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/os/mp_pc.c	Wed Nov 12 04:51:53 2014 -0800
@@ -63,7 +63,6 @@
 extern void real_mode_stop_cpu_stage1_end(void);
 extern void real_mode_stop_cpu_stage2(void);
 extern void real_mode_stop_cpu_stage2_end(void);
-extern void *(*cpu_pause_func)(void *);
 
 void rmp_gdt_init(rm_platter_t *);
 
--- a/usr/src/uts/i86pc/os/x_call.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86pc/os/x_call.c	Wed Nov 12 04:51:53 2014 -0800
@@ -281,7 +281,7 @@
 	 * This is used to work around a race condition window in xc_common()
 	 * between checking CPU_READY flag and increasing working item count.
 	 */
-	pause_cpus(cpup);
+	pause_cpus(cpup, NULL);
 	start_cpus();
 
 	for (i = 0; i < XC_FLUSH_MAX_WAITS; i++) {
--- a/usr/src/uts/i86xpv/os/mp_xen.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/i86xpv/os/mp_xen.c	Wed Nov 12 04:51:53 2014 -0800
@@ -586,7 +586,7 @@
 
 	ASSERT(MUTEX_HELD(&cpu_lock));
 
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 
 	while (!done) {
 		done = 1;
--- a/usr/src/uts/intel/asm/bitmap.h	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/intel/asm/bitmap.h	Wed Nov 12 04:51:53 2014 -0800
@@ -22,6 +22,7 @@
 /*
  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _ASM_BITMAP_H
@@ -36,79 +37,60 @@
 
 #if !defined(__lint) && defined(__GNUC__)
 
+#if defined(__amd64)
+#define	__SUF	"q"
+#elif defined(__i386)
+#define	__SUF	"l"
+#else
+#error "port me"
+#endif
+
 extern __GNU_INLINE int
 highbit(ulong_t i)
 {
-	long __value = -1l;
+	long value = -1l;
 
-#if defined(__amd64)
 	__asm__(
-	    "bsrq	%1,%0"
-	    : "+r" (__value)
+	    "bsr" __SUF " %1,%0"
+	    : "+r" (value)
 	    : "r" (i)
 	    : "cc");
-#elif defined(__i386)
-	__asm__(
-	    "bsrl	%1,%0"
-	    : "+r" (__value)
-	    : "r" (i)
-	    : "cc");
-#else
-#error	"port me"
-#endif
-	return ((int)(__value + 1));
+
+	return ((int)(value + 1));
 }
 
 extern __GNU_INLINE int
 lowbit(ulong_t i)
 {
-	long __value = -1l;
+	long value = -1l;
 
-#if defined(__amd64)
 	__asm__(
-	    "bsfq	%1,%0"
-	    : "+r" (__value)
+	    "bsf" __SUF " %1,%0"
+	    : "+r" (value)
 	    : "r" (i)
 	    : "cc");
-#elif defined(__i386)
-	__asm__(
-	    "bsfl	%1,%0"
-	    : "+r" (__value)
-	    : "r" (i)
-	    : "cc");
-#else
-#error	"port me"
-#endif
-	return ((int)(__value + 1));
+
+	return ((int)(value + 1));
 }
 
 extern __GNU_INLINE uint_t
 atomic_btr32(uint32_t *memory, uint_t bitnum)
 {
-	uint8_t __value;
+	uint8_t value;
 
-#if defined(__amd64)
 	__asm__ __volatile__(
 	    "lock;"
-	    "btrl %2, (%0);"
+	    "btrl %2,%0;"
 	    "setc %1"
-	    : "+r" (memory), "+r" (__value)
+	    : "+m" (*memory), "=r" (value)
 	    : "ir" (bitnum)
 	    : "cc");
-#elif defined(__i386)
-	__asm__ __volatile__(
-	    "lock;"
-	    "btrl %2, (%0);"
-	    "setc %1"
-	    : "+r" (memory), "=r" (__value)
-	    : "ir" (bitnum)
-	    : "cc");
-#else
-#error	"port me"
-#endif
-	return ((uint_t)__value);
+
+	return ((uint_t)value);
 }
 
+#undef __SUF
+
 #endif	/* !__lint && __GNUC__ */
 
 #ifdef	__cplusplus
--- a/usr/src/uts/intel/io/drm/i915_gem_tiling.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/intel/io/drm/i915_gem_tiling.c	Wed Nov 12 04:51:53 2014 -0800
@@ -33,6 +33,7 @@
  * Use is subject to license terms.
  */
 
+#include <sys/sysmacros.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
@@ -246,7 +247,7 @@
 	if (stride < tile_width)
 		return 0;
 
-	if (stride & (stride - 1))
+	if (!ISP2(stride))
 		return 0;
 
 	/* We don't handle the aperture area covered by the fence being bigger
--- a/usr/src/uts/sun4/io/px/px_debug.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4/io/px/px_debug.c	Wed Nov 12 04:51:53 2014 -0800
@@ -23,11 +23,10 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * PCI nexus driver general debug support
  */
+#include <sys/sysmacros.h>
 #include <sys/async.h>
 #include <sys/sunddi.h>		/* dev_info_t */
 #include <sys/ddi_impldefs.h>
@@ -256,7 +255,11 @@
 		int size = px_dbg_msg_size;
 
 		/* Check if px_dbg_msg_size is ^2 */
-		size = (size & (size - 1)) ? ((size | ~size) + 1) : size;
+		/*
+		 * WARNING: The bellow statement makes no sense.  If size is
+		 * not a power of 2, it will set size to zero.
+		 */
+		size = !ISP2(size) ? ((size | ~size) + 1) : size;
 		px_dbg_msg_size = size;
 		px_dbg_qmask = size - 1;
 		px_dbg_msgq = kmem_zalloc(sizeof (px_dbg_msg_t) * size,
--- a/usr/src/uts/sun4/os/ddi_impl.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4/os/ddi_impl.c	Wed Nov 12 04:51:53 2014 -0800
@@ -1001,7 +1001,7 @@
 	 * the attributes leads to a failure.
 	 */
 	uint_t cache_attr = IOMEM_CACHE_ATTR(flags);
-	if ((cache_attr != 0) && ((cache_attr & (cache_attr - 1)) != 0))
+	if ((cache_attr != 0) && !ISP2(cache_attr))
 		return (B_FALSE);
 
 	/*
@@ -1143,14 +1143,14 @@
 	/*
 	 * Make sure that the initial value is sane
 	 */
-	if (i & (i - 1))
+	if (!ISP2(i))
 		return (0);
 	if (i == 0)
 		i = (stream) ? 4 : 1;
 
 	r = ddi_ctlops(a, a,
 	    DDI_CTLOPS_IOMIN, (void *)(uintptr_t)stream, (void *)&i);
-	if (r != DDI_SUCCESS || (i & (i - 1)))
+	if (r != DDI_SUCCESS || !ISP2(i))
 		return (0);
 	return (i);
 }
@@ -1177,8 +1177,7 @@
 	}
 
 	if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 ||
-	    (attr->dma_attr_align & (attr->dma_attr_align - 1)) ||
-	    (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) {
+	    !ISP2(attr->dma_attr_align) || !ISP2(attr->dma_attr_minxfer)) {
 		return (DDI_FAILURE);
 	}
 
--- a/usr/src/uts/sun4/os/mp_states.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4/os/mp_states.c	Wed Nov 12 04:51:53 2014 -0800
@@ -200,7 +200,7 @@
 	if (ncpus > 1)
 		intr_redist_all_cpus_shutdown();
 
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	cpu_are_paused = 1;
 
 	mutex_exit(&cpu_lock);
--- a/usr/src/uts/sun4/os/prom_subr.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4/os/prom_subr.c	Wed Nov 12 04:51:53 2014 -0800
@@ -408,7 +408,7 @@
 void
 promsafe_pause_cpus(void)
 {
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 
 	/* If some other cpu is entering or is in the prom, spin */
 	while (prom_cpu || mutex_owner(&prom_mutex)) {
@@ -421,7 +421,7 @@
 			cv_wait(&prom_cv, &prom_mutex);
 
 		mutex_exit(&prom_mutex);
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 	}
 
 	/* At this point all cpus are paused and none are in the prom */
--- a/usr/src/uts/sun4u/io/mem_cache.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4u/io/mem_cache.c	Wed Nov 12 04:51:53 2014 -0800
@@ -815,7 +815,7 @@
 			    << PN_CACHE_LINE_SHIFT);
 			mutex_enter(&cpu_lock);
 			affinity_set(cache_info->cpu_id);
-			(void) pause_cpus(NULL);
+			pause_cpus(NULL, NULL);
 			mutex_exit(&cpu_lock);
 			/*
 			 * We bind ourself to a CPU and send cross trap to
--- a/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c	Wed Nov 12 04:51:53 2014 -0800
@@ -935,7 +935,7 @@
 	CPU_SIGNATURE(OS_SIG, SIGST_QUIESCED, SIGSUBST_NULL, CPU->cpu_id);
 
 	mutex_enter(&cpu_lock);
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	dr_stop_intr();
 
 	return (rc);
--- a/usr/src/uts/sun4u/os/cpr_impl.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4u/os/cpr_impl.c	Wed Nov 12 04:51:53 2014 -0800
@@ -269,7 +269,7 @@
 		for (cp = CPU->cpu_next; cp != CPU; cp = cp->cpu_next)
 			restart_other_cpu(cp->cpu_id);
 
-		pause_cpus(NULL);
+		pause_cpus(NULL, NULL);
 		mutex_exit(&cpu_lock);
 
 		i_cpr_xcall(i_cpr_clear_entries);
--- a/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c	Wed Nov 12 04:51:53 2014 -0800
@@ -844,7 +844,7 @@
 	}
 
 	mutex_enter(&cpu_lock);
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	sbdp_stop_intr();
 
 	/*
--- a/usr/src/uts/sun4v/io/ds_pri.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4v/io/ds_pri.c	Wed Nov 12 04:51:53 2014 -0800
@@ -910,7 +910,7 @@
 	 * contig_mem_alloc requires size to be a power of 2.
 	 * Increase size to next power of 2 if necessary.
 	 */
-	if ((pri_size & (pri_size - 1)) != 0)
+	if (!ISP2(pri_size))
 		buf_size = 1 << highbit(pri_size);
 	DS_PRI_DBG("ds_get_hv_pri: buf_size = 0x%lx\n", buf_size);
 
--- a/usr/src/uts/sun4v/os/fillsysinfo.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4v/os/fillsysinfo.c	Wed Nov 12 04:51:53 2014 -0800
@@ -465,7 +465,7 @@
 
 	ASSERT(ra_limit != 0);
 
-	kpm_size_shift = (ra_limit & (ra_limit - 1)) != 0 ?
+	kpm_size_shift = !ISP2(ra_limit) ?
 	    highbit(ra_limit) : highbit(ra_limit) - 1;
 
 	/*
@@ -850,7 +850,7 @@
 
 	entries = MIN(entries, max_entries);
 	/* If not a power of 2, truncate to a power of 2. */
-	if ((entries & (entries - 1)) != 0) {
+	if (!ISP2(entries)) {
 		entries = 1 << (highbit(entries) - 1);
 	}
 
--- a/usr/src/uts/sun4v/os/intrq.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4v/os/intrq.c	Wed Nov 12 04:51:53 2014 -0800
@@ -23,6 +23,7 @@
  * Use is subject to license terms.
  */
 
+#include <sys/sysmacros.h>
 #include <sys/machsystm.h>
 #include <sys/cpu.h>
 #include <sys/intreg.h>
@@ -98,7 +99,7 @@
 	 * contig_mem_alloc() requires size to be a power of 2.
 	 * Increase size to a power of 2 if necessary.
 	 */
-	if ((size & (size - 1)) != 0) {
+	if (!ISP2(size)) {
 		size = 1 << highbit(size);
 	}
 
@@ -208,7 +209,7 @@
 	 * contig_mem_alloc() requires size to be a power of 2.
 	 * Increase size to a power of 2 if necessary.
 	 */
-	if ((cpu_list_size & (cpu_list_size - 1)) != 0) {
+	if (!ISP2(cpu_list_size)) {
 		cpu_list_size = 1 << highbit(cpu_list_size);
 	}
 
--- a/usr/src/uts/sun4v/os/mpo.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4v/os/mpo.c	Wed Nov 12 04:51:53 2014 -0800
@@ -220,7 +220,7 @@
 mpo_wr_lock()
 {
 	mutex_enter(&cpu_lock);
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	mutex_exit(&cpu_lock);
 }
 
--- a/usr/src/uts/sun4v/os/suspend.c	Thu Nov 06 07:49:31 2014 -0800
+++ b/usr/src/uts/sun4v/os/suspend.c	Wed Nov 12 04:51:53 2014 -0800
@@ -389,7 +389,7 @@
 	 * inactive in their PGs and shouldn't be reactivated, so we must
 	 * not call pg_cpu_inactive or pg_cpu_active for those CPUs.
 	 */
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	for (id = 0; id < NCPU; id++) {
 		if ((cp = cpu_get(id)) == NULL)
 			continue;
@@ -430,7 +430,7 @@
 	 * system, replace the bootstrapped PG structure with the
 	 * initialized PG structure and call pg_cpu_active for each CPU.
 	 */
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	for (id = 0; id < NCPU; id++) {
 		if ((cp = cpu_get(id)) == NULL)
 			continue;
@@ -615,7 +615,7 @@
 	mutex_exit(&tod_lock);
 
 	/* Pause all other CPUs */
-	pause_cpus(NULL);
+	pause_cpus(NULL, NULL);
 	DBG_PROM("suspend: CPUs paused\n");
 
 	/* Suspend cyclics */