Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Apr 2016 17:00:13 +0000 (UTC)
From:      Glen Barber <gjb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r297861 - in projects/release-pkg: bin/rcp cddl/contrib/opensolaris/lib/libdtrace/common gnu/lib/csu gnu/lib/libgcc gnu/lib/libgcov lib/libc/net lib/libc/rpc lib/libthr/thread lib/msun/...
Message-ID:  <201604121700.u3CH0DJ0065863@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gjb
Date: Tue Apr 12 17:00:13 2016
New Revision: 297861
URL: https://svnweb.freebsd.org/changeset/base/297861

Log:
  MFH
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/release-pkg/bin/rcp/rcp.c
  projects/release-pkg/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
  projects/release-pkg/gnu/lib/csu/Makefile
  projects/release-pkg/gnu/lib/libgcc/Makefile
  projects/release-pkg/gnu/lib/libgcov/Makefile
  projects/release-pkg/lib/libc/net/getservent.c
  projects/release-pkg/lib/libc/rpc/clnt_bcast.c
  projects/release-pkg/lib/libc/rpc/clnt_generic.c
  projects/release-pkg/lib/libthr/thread/thr_mutex.c
  projects/release-pkg/lib/msun/tests/Makefile
  projects/release-pkg/sbin/devd/tests/client_test.c
  projects/release-pkg/share/man/man5/src.conf.5
  projects/release-pkg/share/mk/local.sys.mk
  projects/release-pkg/sys/amd64/amd64/exception.S
  projects/release-pkg/sys/amd64/amd64/mp_machdep.c
  projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
  projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
  projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
  projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c
  projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_zfetch.h
  projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
  projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
  projects/release-pkg/sys/dev/hyperv/vmbus/hv_hv.c
  projects/release-pkg/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
  projects/release-pkg/sys/dev/isp/isp.c
  projects/release-pkg/sys/dev/isp/isp_freebsd.c
  projects/release-pkg/sys/dev/isp/isp_freebsd.h
  projects/release-pkg/sys/dev/isp/isp_pci.c
  projects/release-pkg/sys/dev/isp/ispvar.h
  projects/release-pkg/sys/fs/nfs/nfsport.h
  projects/release-pkg/sys/fs/nfsclient/nfs_clrpcops.c
  projects/release-pkg/sys/i386/i386/mp_machdep.c
  projects/release-pkg/sys/mips/include/resource.h
  projects/release-pkg/sys/mips/mediatek/mtk_pcie.c
  projects/release-pkg/sys/mips/mediatek/mtk_pcie.h
  projects/release-pkg/sys/netinet/sctp_usrreq.c
  projects/release-pkg/sys/netinet/sctp_var.h
  projects/release-pkg/sys/x86/include/specialreg.h
  projects/release-pkg/sys/x86/include/x86_var.h
  projects/release-pkg/sys/x86/x86/identcpu.c
  projects/release-pkg/tools/build/options/WITH_DIRDEPS_BUILD
  projects/release-pkg/tools/build/options/WITH_META_MODE
  projects/release-pkg/usr.sbin/ctld/ctld.c
Directory Properties:
  projects/release-pkg/   (props changed)
  projects/release-pkg/cddl/   (props changed)
  projects/release-pkg/cddl/contrib/opensolaris/   (props changed)
  projects/release-pkg/gnu/lib/   (props changed)
  projects/release-pkg/lib/libc/   (props changed)
  projects/release-pkg/sbin/   (props changed)
  projects/release-pkg/share/   (props changed)
  projects/release-pkg/sys/   (props changed)
  projects/release-pkg/sys/cddl/contrib/opensolaris/   (props changed)
  projects/release-pkg/sys/dev/hyperv/   (props changed)

Modified: projects/release-pkg/bin/rcp/rcp.c
==============================================================================
--- projects/release-pkg/bin/rcp/rcp.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/bin/rcp/rcp.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -447,7 +447,7 @@ rsource(char *name, struct stat *statp)
 		return;
 	}
 	last = strrchr(name, '/');
-	if (last == 0)
+	if (last == NULL)
 		last = name;
 	else
 		last++;

Modified: projects/release-pkg/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
==============================================================================
--- projects/release-pkg/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -711,6 +711,7 @@ dt_module_load_proc(dtrace_hdl_t *dtp, d
 	arg.dpa_count = 0;
 	if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) {
 		dt_dprintf("failed to iterate objects\n");
+		dt_proc_unlock(dtp, p);
 		dt_proc_release(dtp, p);
 		return (dt_set_errno(dtp, EDT_CANTLOAD));
 	}

Modified: projects/release-pkg/gnu/lib/csu/Makefile
==============================================================================
--- projects/release-pkg/gnu/lib/csu/Makefile	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/gnu/lib/csu/Makefile	Tue Apr 12 17:00:13 2016	(r297861)
@@ -71,7 +71,7 @@ crtendS.o:	${ENDSRC}
 		-c -o ${.TARGET} ${.ALLSRC:N*.h}
 
 CLEANFILES+=	tm.h tconfig.h options.h optionlist cs-tconfig.h cs-tm.h
-tm.h tconfig.h options.h: ${CCDIR}/cc_tools/Makefile
+tm.h tconfig.h options.h: ${CCDIR}/cc_tools/Makefile .PHONY
 	(cd ${.CURDIR}; ${MAKE} -f ${.ALLSRC} MFILE=${.ALLSRC} GCCDIR=${GCCDIR} ${.TARGET})
 
 .include <bsd.lib.mk>

Modified: projects/release-pkg/gnu/lib/libgcc/Makefile
==============================================================================
--- projects/release-pkg/gnu/lib/libgcc/Makefile	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/gnu/lib/libgcc/Makefile	Tue Apr 12 17:00:13 2016	(r297861)
@@ -344,7 +344,7 @@ ${_src:R:S/$/.So/}: ${_src} ${COMMONHDRS
 #
 # Generated headers
 #
-${COMMONHDRS}: ${.CURDIR}/../../usr.bin/cc/cc_tools/Makefile
+${COMMONHDRS}: ${.CURDIR}/../../usr.bin/cc/cc_tools/Makefile .PHONY
 	(cd ${.CURDIR}; ${MAKE} -f ${.ALLSRC} MFILE=${.ALLSRC} GCCDIR=${GCCDIR} ${.TARGET})
 
 CLEANFILES += ${COMMONHDRS}

Modified: projects/release-pkg/gnu/lib/libgcov/Makefile
==============================================================================
--- projects/release-pkg/gnu/lib/libgcov/Makefile	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/gnu/lib/libgcov/Makefile	Tue Apr 12 17:00:13 2016	(r297861)
@@ -45,7 +45,7 @@ CC_S =	${CC} -c ${CFLAGS} ${PICFLAG} -DS
 COMMONHDRS=	tm.h tconfig.h gcov-iov.h options.h
 CLEANFILES+=	${COMMONHDRS} cs-tm.h cs-tconfig.h options.h optionlist
 
-${COMMONHDRS}: ${.CURDIR}/../../usr.bin/cc/cc_tools/Makefile
+${COMMONHDRS}: ${.CURDIR}/../../usr.bin/cc/cc_tools/Makefile .PHONY
 	(cd ${.CURDIR}; ${MAKE} -f ${.ALLSRC} MFILE=${.ALLSRC} GCCDIR=${GCCDIR} ${.TARGET})
 
 ${OBJS} beforedepend: ${COMMONHDRS}

Modified: projects/release-pkg/lib/libc/net/getservent.c
==============================================================================
--- projects/release-pkg/lib/libc/net/getservent.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/lib/libc/net/getservent.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -321,7 +321,7 @@ files_servent(void *retval, void *mdata,
 		break;
 	default:
 		return NS_NOTFOUND;
-	};
+	}
 
 	serv = va_arg(ap, struct servent *);
 	buffer  = va_arg(ap, char *);
@@ -463,7 +463,7 @@ files_setservent(void *retval, void *mda
 		break;
 	default:
 		break;
-	};
+	}
 
 	st->compat_mode_active = 0;
 	return (NS_UNAVAIL);
@@ -522,7 +522,7 @@ db_servent(void *retval, void *mdata, va
 		break;
 	default:
 		return NS_NOTFOUND;
-	};
+	}
 
 	serv = va_arg(ap, struct servent *);
 	buffer  = va_arg(ap, char *);
@@ -641,7 +641,7 @@ db_setservent(void *retval, void *mdata,
 		break;
 	default:
 		break;
-	};
+	}
 
 	return (NS_UNAVAIL);
 }
@@ -694,7 +694,7 @@ nis_servent(void *retval, void *mdata, v
 		break;
 	default:
 		return NS_NOTFOUND;
-	};
+	}
 
 	serv = va_arg(ap, struct servent *);
 	buffer  = va_arg(ap, char *);
@@ -781,7 +781,7 @@ nis_servent(void *retval, void *mdata, v
 				}
 			}
 			break;
-		};
+		}
 
 		rv = parse_result(serv, buffer, bufsize, resultbuf,
 		    resultbuflen, errnop);
@@ -815,7 +815,7 @@ nis_setservent(void *result, void *mdata
 		break;
 	default:
 		break;
-	};
+	}
 
 	return (NS_UNAVAIL);
 }

Modified: projects/release-pkg/lib/libc/rpc/clnt_bcast.c
==============================================================================
--- projects/release-pkg/lib/libc/rpc/clnt_bcast.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/lib/libc/rpc/clnt_bcast.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -469,7 +469,7 @@ rpc_broadcast_exp(rpcprog_t prog, rpcver
 						      "broadcast packet");
 						stat = RPC_CANTSEND;
 						continue;
-					};
+					}
 #ifdef RPC_DEBUG
 				if (!__rpc_lowvers)
 					fprintf(stderr, "Broadcast packet sent "

Modified: projects/release-pkg/lib/libc/rpc/clnt_generic.c
==============================================================================
--- projects/release-pkg/lib/libc/rpc/clnt_generic.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/lib/libc/rpc/clnt_generic.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -402,7 +402,7 @@ clnt_tli_create(int fd, const struct net
 	if (madefd) {
 		(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
 /*		(void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL);  */
-	};
+	}
 
 	return (cl);
 

Modified: projects/release-pkg/lib/libthr/thread/thr_mutex.c
==============================================================================
--- projects/release-pkg/lib/libthr/thread/thr_mutex.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/lib/libthr/thread/thr_mutex.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -476,7 +476,8 @@ check_and_init_mutex(pthread_mutex_t *mu
 		*m = __thr_pshared_offpage(mutex, 0);
 		if (*m == NULL)
 			ret = EINVAL;
-		shared_mutex_init(*m, NULL);
+		else
+			shared_mutex_init(*m, NULL);
 	} else if (__predict_false(*m <= THR_MUTEX_DESTROYED)) {
 		if (*m == THR_MUTEX_DESTROYED) {
 			ret = EINVAL;

Modified: projects/release-pkg/lib/msun/tests/Makefile
==============================================================================
--- projects/release-pkg/lib/msun/tests/Makefile	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/lib/msun/tests/Makefile	Tue Apr 12 17:00:13 2016	(r297861)
@@ -65,9 +65,9 @@ TAP_TESTS_C+=	next_test
 TAP_TESTS_C+=	rem_test
 TAP_TESTS_C+=	trig_test
 
-.for t in ${TAP_TESTS_C}
-CFLAGS.$t+=	-O0
-.endfor
+.if !empty(PROG) && !empty(TAP_TESTS_C:M${PROG})
+CFLAGS+=	-O0
+.endif
 
 CSTD=		c99
 

Modified: projects/release-pkg/sbin/devd/tests/client_test.c
==============================================================================
--- projects/release-pkg/sbin/devd/tests/client_test.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/sbin/devd/tests/client_test.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -34,6 +34,10 @@ __FBSDID("$FreeBSD$");
 #include <sys/un.h>
 
 #include <atf-c.h>
+
+const char create_pat[] = "!system=DEVFS subsystem=CDEV type=CREATE cdev=md";
+const char destroy_pat[] = "!system=DEVFS subsystem=CDEV type=DESTROY cdev=md";
+
 /* Helper functions*/
 
 /*
@@ -63,6 +67,24 @@ create_two_events(void)
 	ATF_REQUIRE_EQ(0, pclose(destroy_stdout));
 }
 
+/* Setup and return an open client socket */
+static int
+common_setup(int socktype, const char* sockpath) {
+	struct sockaddr_un devd_addr;
+	int s, error;
+
+	memset(&devd_addr, 0, sizeof(devd_addr));
+	devd_addr.sun_family = PF_LOCAL;
+	strlcpy(devd_addr.sun_path, sockpath, sizeof(devd_addr.sun_path));
+	s = socket(PF_LOCAL, socktype, 0);
+	ATF_REQUIRE(s >= 0);
+	error = connect(s, (struct sockaddr*)&devd_addr, SUN_LEN(&devd_addr));
+	ATF_REQUIRE_EQ(0, error);
+
+	create_two_events();
+	return (s);
+}
+
 /*
  * Test Cases
  */
@@ -75,27 +97,10 @@ ATF_TC_WITHOUT_HEAD(seqpacket);
 ATF_TC_BODY(seqpacket, tc)
 {
 	int s;
-	int error;
-	struct sockaddr_un devd_addr;
 	bool got_create_event = false;
 	bool got_destroy_event = false;
-	const char create_pat[] =
-		"!system=DEVFS subsystem=CDEV type=CREATE cdev=md";
-	const char destroy_pat[] =
-		"!system=DEVFS subsystem=CDEV type=DESTROY cdev=md";
-
-	memset(&devd_addr, 0, sizeof(devd_addr));
-	devd_addr.sun_family = PF_LOCAL;
-	strlcpy(devd_addr.sun_path, "/var/run/devd.seqpacket.pipe",
-			sizeof(devd_addr.sun_path));
-
-	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
-	ATF_REQUIRE(s >= 0);
-	error = connect(s, (struct sockaddr*)&devd_addr, SUN_LEN(&devd_addr));
-	ATF_REQUIRE_EQ(0, error);
-
-	create_two_events();
 
+	s = common_setup(SOCK_SEQPACKET, "/var/run/devd.seqpacket.pipe");
 	/*
 	 * Loop until both events are detected on _different_ reads
 	 * There may be extra events due to unrelated system activity
@@ -132,31 +137,14 @@ ATF_TC_WITHOUT_HEAD(stream);
 ATF_TC_BODY(stream, tc)
 {
 	int s;
-	int error;
-	struct sockaddr_un devd_addr;
 	bool got_create_event = false;
 	bool got_destroy_event = false;
-	const char create_pat[] =
-		"!system=DEVFS subsystem=CDEV type=CREATE cdev=md";
-	const char destroy_pat[] =
-		"!system=DEVFS subsystem=CDEV type=DESTROY cdev=md";
 	ssize_t len = 0;
 
-	memset(&devd_addr, 0, sizeof(devd_addr));
-	devd_addr.sun_family = PF_LOCAL;
-	strlcpy(devd_addr.sun_path, "/var/run/devd.pipe",
-			sizeof(devd_addr.sun_path));
-
-	s = socket(PF_LOCAL, SOCK_STREAM, 0);
-	ATF_REQUIRE(s >= 0);
-	error = connect(s, (struct sockaddr*)&devd_addr, SUN_LEN(&devd_addr));
-	ATF_REQUIRE_EQ(0, error);
-
-	create_two_events();
-
+	s = common_setup(SOCK_STREAM, "/var/run/devd.pipe");
 	/*
-	 * Loop until both events are detected on _different_ reads
-	 * There may be extra events due to unrelated system activity
+	 * Loop until both events are detected on the same or different reads.
+	 * There may be extra events due to unrelated system activity.
 	 * If we never get both events, then the test will timeout.
 	 */
 	while (!(got_create_event && got_destroy_event)) {
@@ -169,7 +157,7 @@ ATF_TC_BODY(stream, tc)
 		ATF_REQUIRE(newlen != -1);
 		len += newlen;
 		/* NULL terminate the result */
-		event[newlen] = '\0';
+		event[len] = '\0';
 		printf("%s", event);
 
 		create_pos = strstr(event, create_pat);

Modified: projects/release-pkg/share/man/man5/src.conf.5
==============================================================================
--- projects/release-pkg/share/man/man5/src.conf.5	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/share/man/man5/src.conf.5	Tue Apr 12 17:00:13 2016	(r297861)
@@ -1,7 +1,7 @@
 .\" DO NOT EDIT-- this file is automatically generated.
 .\" from FreeBSD: head/tools/build/options/makeman 292283 2015-12-15 18:42:30Z bdrewery
 .\" $FreeBSD$
-.Dd March 30, 2016
+.Dd April 11, 2016
 .Dt SRC.CONF 5
 .Os
 .Sh NAME
@@ -473,7 +473,7 @@ executable binary and shared library.
 .\" from FreeBSD: head/tools/build/options/WITHOUT_DICT 156932 2006-03-21 07:50:50Z ru
 Set to not build the Webster dictionary files.
 .It Va WITH_DIRDEPS_BUILD
-.\" from FreeBSD: head/tools/build/options/WITH_DIRDEPS_BUILD 290816 2015-11-14 03:24:48Z sjg
+.\" from FreeBSD: head/tools/build/options/WITH_DIRDEPS_BUILD 297843 2016-04-12 03:37:42Z bdrewery
 Enable building in meta mode.
 This is an experimental build feature.
 For details see
@@ -494,7 +494,9 @@ computing a graph of tree dependencies f
 Setting
 .Va NO_DIRDEPS
 will skip checking dirdep dependencies and will only build in the current
-directory.
+and child directories.
+.Va NO_DIRDEPS_BELOW
+will skip building any dirdeps and only build the current directory.
 .Pp
 As each target is made
 .Xr make 1
@@ -1057,9 +1059,18 @@ Set to not build utilities for manual pa
 .Xr manctl 8 ,
 and related support files.
 .It Va WITH_META_MODE
-.\" from FreeBSD: head/tools/build/options/WITH_META_MODE 290816 2015-11-14 03:24:48Z sjg
+.\" from FreeBSD: head/tools/build/options/WITH_META_MODE 297844 2016-04-12 03:40:13Z bdrewery
 Create meta files when not doing DIRDEPS_BUILD.
-The meta files can be useful for debugging.
+When the
+.Xr filemon 4
+module is loaded, dependencies will be tracked for all commands.
+If any command, its dependencies, or files it generates are missing then
+the target will be considered out-of-date and rebuilt.
+The meta files can also be useful for debugging.
+.Pp
+The build will hide commands ran unless
+.Va NO_SILENT
+is defined.
 .Pp
 This must be set in the environment, make command line, or
 .Pa /etc/src-env.conf ,

Modified: projects/release-pkg/share/mk/local.sys.mk
==============================================================================
--- projects/release-pkg/share/mk/local.sys.mk	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/share/mk/local.sys.mk	Tue Apr 12 17:00:13 2016	(r297861)
@@ -33,7 +33,8 @@ OBJTOP?= ${.OBJDIR:S,${.CURDIR},,}${SRCT
 # we can afford to use cookies to prevent some targets
 # re-running needlessly but only when using filemon.
 .if ${.MAKE.MODE:Mnofilemon} == ""
-META_COOKIE=		${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET}}
+META_COOKIE_COND=	empty(.TARGET:M${.OBJDIR})
+META_COOKIE=		${COOKIE.${.TARGET}:U${${META_COOKIE_COND}:?${.OBJDIR}/${.TARGET}:${.TARGET}}}
 META_COOKIE_RM=		@rm -f ${META_COOKIE}
 META_COOKIE_TOUCH=	@touch ${META_COOKIE}
 CLEANFILES+=		${META_TARGETS}

Modified: projects/release-pkg/sys/amd64/amd64/exception.S
==============================================================================
--- projects/release-pkg/sys/amd64/amd64/exception.S	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/sys/amd64/amd64/exception.S	Tue Apr 12 17:00:13 2016	(r297861)
@@ -211,6 +211,8 @@ alltraps_pushregs_no_rdi:
 	 * interrupt. For all other trap types, just handle them in
 	 * the usual way.
 	 */
+	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
+	jnz	calltrap		/* ignore userland traps */
 	cmpl	$T_BPTFLT,TF_TRAPNO(%rsp)
 	jne	calltrap
 

Modified: projects/release-pkg/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- projects/release-pkg/sys/amd64/amd64/mp_machdep.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/sys/amd64/amd64/mp_machdep.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -247,7 +247,7 @@ init_secondary(void)
 	wrmsr(MSR_FSBASE, 0);		/* User value */
 	wrmsr(MSR_GSBASE, (u_int64_t)pc);
 	wrmsr(MSR_KGSBASE, (u_int64_t)pc);	/* XXX User value while we're in the kernel */
-	intel_fix_cpuid();
+	fix_cpuid();
 
 	lidt(&r_idt);
 

Modified: projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
==============================================================================
--- projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -563,6 +563,7 @@ typedef struct arc_stats {
 	kstat_named_t arcstat_l2_compress_successes;
 	kstat_named_t arcstat_l2_compress_zeros;
 	kstat_named_t arcstat_l2_compress_failures;
+	kstat_named_t arcstat_l2_padding_needed;
 	kstat_named_t arcstat_l2_write_trylock_fail;
 	kstat_named_t arcstat_l2_write_passed_headroom;
 	kstat_named_t arcstat_l2_write_spa_mismatch;
@@ -664,6 +665,7 @@ static arc_stats_t arc_stats = {
 	{ "l2_compress_successes",	KSTAT_DATA_UINT64 },
 	{ "l2_compress_zeros",		KSTAT_DATA_UINT64 },
 	{ "l2_compress_failures",	KSTAT_DATA_UINT64 },
+	{ "l2_padding_needed",		KSTAT_DATA_UINT64 },
 	{ "l2_write_trylock_fail",	KSTAT_DATA_UINT64 },
 	{ "l2_write_passed_headroom",	KSTAT_DATA_UINT64 },
 	{ "l2_write_spa_mismatch",	KSTAT_DATA_UINT64 },
@@ -837,7 +839,7 @@ typedef struct l1arc_buf_hdr {
 	refcount_t		b_refcnt;
 
 	arc_callback_t		*b_acb;
-	/* temporary buffer holder for in-flight compressed data */
+	/* temporary buffer holder for in-flight compressed or padded data */
 	void			*b_tmp_cdata;
 } l1arc_buf_hdr_t;
 
@@ -1098,6 +1100,7 @@ typedef struct l2arc_read_callback {
 	zbookmark_phys_t	l2rcb_zb;		/* original bookmark */
 	int			l2rcb_flags;		/* original flags */
 	enum zio_compress	l2rcb_compress;		/* applied compress */
+	void			*l2rcb_data;		/* temporary buffer */
 } l2arc_read_callback_t;
 
 typedef struct l2arc_write_callback {
@@ -1128,7 +1131,7 @@ static uint32_t arc_bufc_to_flags(arc_bu
 static boolean_t l2arc_write_eligible(uint64_t, arc_buf_hdr_t *);
 static void l2arc_read_done(zio_t *);
 
-static boolean_t l2arc_compress_buf(arc_buf_hdr_t *);
+static boolean_t l2arc_transform_buf(arc_buf_hdr_t *, boolean_t);
 static void l2arc_decompress_zio(zio_t *, arc_buf_hdr_t *, enum zio_compress);
 static void l2arc_release_cdata_buf(arc_buf_hdr_t *);
 
@@ -2215,6 +2218,8 @@ arc_buf_data_free(arc_buf_t *buf, void (
 static void
 arc_buf_l2_cdata_free(arc_buf_hdr_t *hdr)
 {
+	size_t align, asize, len;
+
 	ASSERT(HDR_HAS_L2HDR(hdr));
 	ASSERT(MUTEX_HELD(&hdr->b_l2hdr.b_dev->l2ad_mtx));
 
@@ -2236,16 +2241,15 @@ arc_buf_l2_cdata_free(arc_buf_hdr_t *hdr
 	}
 
 	/*
-	 * The header does not have compression enabled. This can be due
-	 * to the buffer not being compressible, or because we're
-	 * freeing the buffer before the second phase of
-	 * l2arc_write_buffer() has started (which does the compression
-	 * step). In either case, b_tmp_cdata does not point to a
-	 * separately compressed buffer, so there's nothing to free (it
-	 * points to the same buffer as the arc_buf_t's b_data field).
-	 */
-	if (hdr->b_l2hdr.b_compress == ZIO_COMPRESS_OFF) {
-		hdr->b_l1hdr.b_tmp_cdata = NULL;
+	 * The bufer has been chosen for writing to L2ARC, but it's
+	 * not being written just yet.  In other words,
+	 * b_tmp_cdata points to exactly the same buffer as b_data,
+	 * l2arc_transform_buf hasn't been called.
+	 */
+	if (hdr->b_l2hdr.b_daddr == L2ARC_ADDR_UNSET) {
+		ASSERT3P(hdr->b_l1hdr.b_tmp_cdata, ==,
+		    hdr->b_l1hdr.b_buf->b_data);
+		ASSERT3U(hdr->b_l2hdr.b_compress, ==, ZIO_COMPRESS_OFF);
 		return;
 	}
 
@@ -2258,12 +2262,18 @@ arc_buf_l2_cdata_free(arc_buf_hdr_t *hdr
 		return;
 	}
 
-	ASSERT(L2ARC_IS_VALID_COMPRESS(hdr->b_l2hdr.b_compress));
-
-	arc_buf_free_on_write(hdr->b_l1hdr.b_tmp_cdata,
-	    hdr->b_size, zio_data_buf_free);
+	/*
+	 * Nothing to do if the temporary buffer was not required.
+	 */
+	if (hdr->b_l1hdr.b_tmp_cdata == NULL)
+		return;
 
 	ARCSTAT_BUMP(arcstat_l2_cdata_free_on_write);
+	len = hdr->b_size;
+	align = (size_t)1 << hdr->b_l2hdr.b_dev->l2ad_vdev->vdev_ashift;
+	asize = P2ROUNDUP(len, align);
+	arc_buf_free_on_write(hdr->b_l1hdr.b_tmp_cdata, asize,
+	    zio_data_buf_free);
 	hdr->b_l1hdr.b_tmp_cdata = NULL;
 }
 
@@ -4534,6 +4544,7 @@ top:
 			    !HDR_L2_WRITING(hdr) && !HDR_L2_EVICTED(hdr) &&
 			    !(l2arc_noprefetch && HDR_PREFETCH(hdr))) {
 				l2arc_read_callback_t *cb;
+				void* b_data;
 
 				DTRACE_PROBE1(l2arc__hit, arc_buf_hdr_t *, hdr);
 				ARCSTAT_BUMP(arcstat_l2_hits);
@@ -4546,6 +4557,14 @@ top:
 				cb->l2rcb_zb = *zb;
 				cb->l2rcb_flags = zio_flags;
 				cb->l2rcb_compress = b_compress;
+				if (b_asize > hdr->b_size) {
+					ASSERT3U(b_compress, ==,
+					    ZIO_COMPRESS_OFF);
+					b_data = zio_data_buf_alloc(b_asize);
+					cb->l2rcb_data = b_data;
+				} else {
+					b_data = buf->b_data;
+				}
 
 				ASSERT(addr >= VDEV_LABEL_START_SIZE &&
 				    addr + size < vd->vdev_psize -
@@ -4558,6 +4577,7 @@ top:
 				 * was squashed to zero size by compression.
 				 */
 				if (b_compress == ZIO_COMPRESS_EMPTY) {
+					ASSERT3U(b_asize, ==, 0);
 					rzio = zio_null(pio, spa, vd,
 					    l2arc_read_done, cb,
 					    zio_flags | ZIO_FLAG_DONT_CACHE |
@@ -4566,7 +4586,7 @@ top:
 					    ZIO_FLAG_DONT_RETRY);
 				} else {
 					rzio = zio_read_phys(pio, vd, addr,
-					    b_asize, buf->b_data,
+					    b_asize, b_data,
 					    ZIO_CHECKSUM_OFF,
 					    l2arc_read_done, cb, priority,
 					    zio_flags | ZIO_FLAG_DONT_CACHE |
@@ -6051,6 +6071,32 @@ l2arc_read_done(zio_t *zio)
 	ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
 
 	/*
+	 * If the data was read into a temporary buffer,
+	 * move it and free the buffer.
+	 */
+	if (cb->l2rcb_data != NULL) {
+		ASSERT3U(hdr->b_size, <, zio->io_size);
+		ASSERT3U(cb->l2rcb_compress, ==, ZIO_COMPRESS_OFF);
+		if (zio->io_error == 0)
+			bcopy(cb->l2rcb_data, buf->b_data, hdr->b_size);
+
+		/*
+		 * The following must be done regardless of whether
+		 * there was an error:
+		 * - free the temporary buffer
+		 * - point zio to the real ARC buffer
+		 * - set zio size accordingly
+		 * These are required because zio is either re-used for
+		 * an I/O of the block in the case of the error
+		 * or the zio is passed to arc_read_done() and it
+		 * needs real data.
+		 */
+		zio_data_buf_free(cb->l2rcb_data, zio->io_size);
+		zio->io_size = zio->io_orig_size = hdr->b_size;
+		zio->io_data = zio->io_orig_data = buf->b_data;
+	}
+
+	/*
 	 * If the buffer was compressed, decompress it first.
 	 */
 	if (cb->l2rcb_compress != ZIO_COMPRESS_OFF)
@@ -6334,6 +6380,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
 			kmutex_t *hash_lock;
 			uint64_t buf_sz;
 			uint64_t buf_a_sz;
+			size_t align;
 
 			if (arc_warm == B_FALSE)
 				hdr_prev = multilist_sublist_next(mls, hdr);
@@ -6371,7 +6418,8 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
 			 * disk block size.
 			 */
 			buf_sz = hdr->b_size;
-			buf_a_sz = vdev_psize_to_asize(dev->l2ad_vdev, buf_sz);
+			align = (size_t)1 << dev->l2ad_vdev->vdev_ashift;
+			buf_a_sz = P2ROUNDUP(buf_sz, align);
 
 			if ((write_asize + buf_a_sz) > target_sz) {
 				full = B_TRUE;
@@ -6475,26 +6523,15 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
 	mutex_enter(&dev->l2ad_mtx);
 
 	/*
-	 * Note that elsewhere in this file arcstat_l2_asize
-	 * and the used space on l2ad_vdev are updated using b_asize,
-	 * which is not necessarily rounded up to the device block size.
-	 * Too keep accounting consistent we do the same here as well:
-	 * stats_size accumulates the sum of b_asize of the written buffers,
-	 * while write_asize accumulates the sum of b_asize rounded up
-	 * to the device block size.
-	 * The latter sum is used only to validate the corectness of the code.
-	 */
-	uint64_t stats_size = 0;
-	write_asize = 0;
-
-	/*
 	 * Now start writing the buffers. We're starting at the write head
 	 * and work backwards, retracing the course of the buffer selector
 	 * loop above.
 	 */
+	write_asize = 0;
 	for (hdr = list_prev(&dev->l2ad_buflist, head); hdr;
 	    hdr = list_prev(&dev->l2ad_buflist, hdr)) {
 		uint64_t buf_sz;
+		boolean_t compress;
 
 		/*
 		 * We rely on the L1 portion of the header below, so
@@ -6513,22 +6550,26 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
 		 */
 		hdr->b_l2hdr.b_daddr = dev->l2ad_hand;
 
-		if ((HDR_L2COMPRESS(hdr)) &&
-		    hdr->b_l2hdr.b_asize >= buf_compress_minsz) {
-			if (l2arc_compress_buf(hdr)) {
-				/*
-				 * If compression succeeded, enable headroom
-				 * boost on the next scan cycle.
-				 */
-				*headroom_boost = B_TRUE;
-			}
+		/*
+		 * Save a pointer to the original buffer data we had previously
+		 * stashed away.
+		 */
+		buf_data = hdr->b_l1hdr.b_tmp_cdata;
+
+		compress = HDR_L2COMPRESS(hdr) &&
+		    hdr->b_l2hdr.b_asize >= buf_compress_minsz;
+		if (l2arc_transform_buf(hdr, compress)) {
+			/*
+			 * If compression succeeded, enable headroom
+			 * boost on the next scan cycle.
+			 */
+			*headroom_boost = B_TRUE;
 		}
 
 		/*
-		 * Pick up the buffer data we had previously stashed away
-		 * (and now potentially also compressed).
+		 * Get the new buffer size that accounts for compression
+		 * and padding.
 		 */
-		buf_data = hdr->b_l1hdr.b_tmp_cdata;
 		buf_sz = hdr->b_l2hdr.b_asize;
 
 		/*
@@ -6540,8 +6581,12 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
 
 		/* Compression may have squashed the buffer to zero length. */
 		if (buf_sz != 0) {
-			uint64_t buf_a_sz;
-
+			/*
+			 * If the data was padded or compressed, then it
+			 * it is in a new buffer.
+			 */
+			if (hdr->b_l1hdr.b_tmp_cdata != NULL)
+				buf_data = hdr->b_l1hdr.b_tmp_cdata;
 			wzio = zio_write_phys(pio, dev->l2ad_vdev,
 			    dev->l2ad_hand, buf_sz, buf_data, ZIO_CHECKSUM_OFF,
 			    NULL, NULL, ZIO_PRIORITY_ASYNC_WRITE,
@@ -6551,14 +6596,8 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
 			    zio_t *, wzio);
 			(void) zio_nowait(wzio);
 
-			stats_size += buf_sz;
-
-			/*
-			 * Keep the clock hand suitably device-aligned.
-			 */
-			buf_a_sz = vdev_psize_to_asize(dev->l2ad_vdev, buf_sz);
-			write_asize += buf_a_sz;
-			dev->l2ad_hand += buf_a_sz;
+			write_asize += buf_sz;
+			dev->l2ad_hand += buf_sz;
 		}
 	}
 
@@ -6568,8 +6607,8 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
 	ARCSTAT_BUMP(arcstat_l2_writes_sent);
 	ARCSTAT_INCR(arcstat_l2_write_bytes, write_asize);
 	ARCSTAT_INCR(arcstat_l2_size, write_sz);
-	ARCSTAT_INCR(arcstat_l2_asize, stats_size);
-	vdev_space_update(dev->l2ad_vdev, stats_size, 0, 0);
+	ARCSTAT_INCR(arcstat_l2_asize, write_asize);
+	vdev_space_update(dev->l2ad_vdev, write_asize, 0, 0);
 
 	/*
 	 * Bump device hand to the device start if it is approaching the end.
@@ -6588,12 +6627,18 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
 }
 
 /*
- * Compresses an L2ARC buffer.
+ * Transforms, possibly compresses and pads, an L2ARC buffer.
  * The data to be compressed must be prefilled in l1hdr.b_tmp_cdata and its
  * size in l2hdr->b_asize. This routine tries to compress the data and
  * depending on the compression result there are three possible outcomes:
- * *) The buffer was incompressible. The original l2hdr contents were left
- *    untouched and are ready for writing to an L2 device.
+ * *) The buffer was incompressible. The buffer size was already ashift aligned.
+ *    The original hdr contents were left untouched except for b_tmp_cdata,
+ *    which is reset to NULL. The caller must keep a pointer to the original
+ *    data.
+ * *) The buffer was incompressible. The buffer size was not ashift aligned.
+ *    b_tmp_cdata was replaced with a temporary data buffer which holds a padded
+ *    (aligned) copy of the data. Once writing is done, invoke
+ *    l2arc_release_cdata_buf on this hdr to free the temporary buffer.
  * *) The buffer was all-zeros, so there is no need to write it to an L2
  *    device. To indicate this situation b_tmp_cdata is NULL'ed, b_asize is
  *    set to zero and b_compress is set to ZIO_COMPRESS_EMPTY.
@@ -6607,10 +6652,11 @@ l2arc_write_buffers(spa_t *spa, l2arc_de
  * buffer was incompressible).
  */
 static boolean_t
-l2arc_compress_buf(arc_buf_hdr_t *hdr)
+l2arc_transform_buf(arc_buf_hdr_t *hdr, boolean_t compress)
 {
 	void *cdata;
-	size_t csize, len, rounded;
+	size_t align, asize, csize, len, rounded;
+
 	ASSERT(HDR_HAS_L2HDR(hdr));
 	l2arc_buf_hdr_t *l2hdr = &hdr->b_l2hdr;
 
@@ -6619,14 +6665,19 @@ l2arc_compress_buf(arc_buf_hdr_t *hdr)
 	ASSERT(hdr->b_l1hdr.b_tmp_cdata != NULL);
 
 	len = l2hdr->b_asize;
-	cdata = zio_data_buf_alloc(len);
+	align = (size_t)1 << l2hdr->b_dev->l2ad_vdev->vdev_ashift;
+	asize = P2ROUNDUP(len, align);
+	cdata = zio_data_buf_alloc(asize);
 	ASSERT3P(cdata, !=, NULL);
-	csize = zio_compress_data(ZIO_COMPRESS_LZ4, hdr->b_l1hdr.b_tmp_cdata,
-	    cdata, l2hdr->b_asize);
+	if (compress)
+		csize = zio_compress_data(ZIO_COMPRESS_LZ4,
+		    hdr->b_l1hdr.b_tmp_cdata, cdata, len);
+	else
+		csize = len;
 
 	if (csize == 0) {
 		/* zero block, indicate that there's nothing to write */
-		zio_data_buf_free(cdata, len);
+		zio_data_buf_free(cdata, asize);
 		l2hdr->b_compress = ZIO_COMPRESS_EMPTY;
 		l2hdr->b_asize = 0;
 		hdr->b_l1hdr.b_tmp_cdata = NULL;
@@ -6634,8 +6685,8 @@ l2arc_compress_buf(arc_buf_hdr_t *hdr)
 		return (B_TRUE);
 	}
 
-	rounded = P2ROUNDUP(csize,
-	    (size_t)1 << l2hdr->b_dev->l2ad_vdev->vdev_ashift);
+	rounded = P2ROUNDUP(csize, align);
+	ASSERT3U(rounded, <=, asize);
 	if (rounded < len) {
 		/*
 		 * Compression succeeded, we'll keep the cdata around for
@@ -6652,11 +6703,32 @@ l2arc_compress_buf(arc_buf_hdr_t *hdr)
 		return (B_TRUE);
 	} else {
 		/*
-		 * Compression failed, release the compressed buffer.
-		 * l2hdr will be left unmodified.
+		 * Compression did not save space.
 		 */
-		zio_data_buf_free(cdata, len);
-		ARCSTAT_BUMP(arcstat_l2_compress_failures);
+		if (P2PHASE(len, align) != 0) {
+			/*
+			 * Use compression buffer for a copy of data padded to
+			 * the proper size.  Compression algorithm remains set
+			 * to ZIO_COMPRESS_OFF.
+			 */
+			ASSERT3U(len, <, asize);
+			bcopy(hdr->b_l1hdr.b_tmp_cdata, cdata, len);
+			bzero((char *)cdata + len, asize - len);
+			l2hdr->b_asize = asize;
+			hdr->b_l1hdr.b_tmp_cdata = cdata;
+			ARCSTAT_BUMP(arcstat_l2_padding_needed);
+		} else {
+			ASSERT3U(len, ==, asize);
+			/*
+			 * The original buffer is good as is,
+			 * release the compressed buffer.
+			 * l2hdr will be left unmodified except for b_tmp_cdata.
+			 */
+			zio_data_buf_free(cdata, asize);
+			hdr->b_l1hdr.b_tmp_cdata = NULL;
+		}
+		if (compress)
+			ARCSTAT_BUMP(arcstat_l2_compress_failures);
 		return (B_FALSE);
 	}
 }
@@ -6725,44 +6797,30 @@ l2arc_decompress_zio(zio_t *zio, arc_buf
 
 /*
  * Releases the temporary b_tmp_cdata buffer in an l2arc header structure.
- * This buffer serves as a temporary holder of compressed data while
+ * This buffer serves as a temporary holder of compressed or padded data while
  * the buffer entry is being written to an l2arc device. Once that is
  * done, we can dispose of it.
  */
 static void
 l2arc_release_cdata_buf(arc_buf_hdr_t *hdr)
 {
-	ASSERT(HDR_HAS_L2HDR(hdr));
+	size_t align, asize, len;
 	enum zio_compress comp = hdr->b_l2hdr.b_compress;
 
+	ASSERT(HDR_HAS_L2HDR(hdr));
 	ASSERT(HDR_HAS_L1HDR(hdr));
 	ASSERT(comp == ZIO_COMPRESS_OFF || L2ARC_IS_VALID_COMPRESS(comp));
 
-	if (comp == ZIO_COMPRESS_OFF) {
-		/*
-		 * In this case, b_tmp_cdata points to the same buffer
-		 * as the arc_buf_t's b_data field. We don't want to
-		 * free it, since the arc_buf_t will handle that.
-		 */
+	if (hdr->b_l1hdr.b_tmp_cdata != NULL) {
+		ASSERT(comp != ZIO_COMPRESS_EMPTY);
+		len = hdr->b_size;
+		align = (size_t)1 << hdr->b_l2hdr.b_dev->l2ad_vdev->vdev_ashift;
+		asize = P2ROUNDUP(len, align);
+		zio_data_buf_free(hdr->b_l1hdr.b_tmp_cdata, asize);
 		hdr->b_l1hdr.b_tmp_cdata = NULL;
-	} else if (comp == ZIO_COMPRESS_EMPTY) {
-		/*
-		 * In this case, b_tmp_cdata was compressed to an empty
-		 * buffer, thus there's nothing to free and b_tmp_cdata
-		 * should have been set to NULL in l2arc_write_buffers().
-		 */
-		ASSERT3P(hdr->b_l1hdr.b_tmp_cdata, ==, NULL);
 	} else {
-		/*
-		 * If the data was compressed, then we've allocated a
-		 * temporary buffer for it, so now we need to release it.
-		 */
-		ASSERT(hdr->b_l1hdr.b_tmp_cdata != NULL);
-		zio_data_buf_free(hdr->b_l1hdr.b_tmp_cdata,
-		    hdr->b_size);
-		hdr->b_l1hdr.b_tmp_cdata = NULL;
+		ASSERT(comp == ZIO_COMPRESS_OFF || comp == ZIO_COMPRESS_EMPTY);
 	}
-
 }
 
 /*

Modified: projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
==============================================================================
--- projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -721,7 +721,7 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio
 	if (db->db_state == DB_CACHED) {
 		mutex_exit(&db->db_mtx);
 		if (prefetch)
-			dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1);
+			dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1, B_TRUE);
 		if ((flags & DB_RF_HAVESTRUCT) == 0)
 			rw_exit(&dn->dn_struct_rwlock);
 		DB_DNODE_EXIT(db);
@@ -735,7 +735,7 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio
 		/* dbuf_read_impl has dropped db_mtx for us */
 
 		if (prefetch)
-			dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1);
+			dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1, B_TRUE);
 
 		if ((flags & DB_RF_HAVESTRUCT) == 0)
 			rw_exit(&dn->dn_struct_rwlock);
@@ -754,7 +754,7 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio
 		 */
 		mutex_exit(&db->db_mtx);
 		if (prefetch)
-			dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1);
+			dmu_zfetch(&dn->dn_zfetch, db->db_blkid, 1, B_TRUE);
 		if ((flags & DB_RF_HAVESTRUCT) == 0)
 			rw_exit(&dn->dn_struct_rwlock);
 		DB_DNODE_EXIT(db);

Modified: projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
==============================================================================
--- projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -458,9 +458,10 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn,
 		dbp[i] = &db->db;
 	}
 
-	if ((flags & DMU_READ_NO_PREFETCH) == 0 && read &&
-	    length <= zfetch_array_rd_sz) {
-		dmu_zfetch(&dn->dn_zfetch, blkid, nblks);
+	if ((flags & DMU_READ_NO_PREFETCH) == 0 &&
+	    DNODE_META_IS_CACHEABLE(dn) && length <= zfetch_array_rd_sz) {
+		dmu_zfetch(&dn->dn_zfetch, blkid, nblks,
+		    read && DNODE_IS_CACHEABLE(dn));
 	}
 	rw_exit(&dn->dn_struct_rwlock);
 

Modified: projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c
==============================================================================
--- projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c	Tue Apr 12 16:07:41 2016	(r297860)
+++ projects/release-pkg/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c	Tue Apr 12 17:00:13 2016	(r297861)
@@ -49,6 +49,8 @@ uint32_t	zfetch_max_streams = 8;
 uint32_t	zfetch_min_sec_reap = 2;
 /* max bytes to prefetch per stream (default 8MB) */
 uint32_t	zfetch_max_distance = 8 * 1024 * 1024;
+/* max bytes to prefetch indirects for per stream (default 64MB) */
+uint32_t	zfetch_max_idistance = 64 * 1024 * 1024;
 /* max number of bytes in an array_read in which we allow prefetching (1MB) */
 uint64_t	zfetch_array_rd_sz = 1024 * 1024;
 
@@ -200,6 +202,7 @@ dmu_zfetch_stream_create(zfetch_t *zf, u
 	zstream_t *zs = kmem_zalloc(sizeof (*zs), KM_SLEEP);
 	zs->zs_blkid = blkid;
 	zs->zs_pf_blkid = blkid;
+	zs->zs_ipf_blkid = blkid;
 	zs->zs_atime = gethrtime();
 	mutex_init(&zs->zs_lock, NULL, MUTEX_DEFAULT, NULL);
 
@@ -207,13 +210,21 @@ dmu_zfetch_stream_create(zfetch_t *zf, u
 }
 
 /*
- * This is the prefetch entry point.  It calls all of the other dmu_zfetch
- * routines to create, delete, find, or operate upon prefetch streams.
+ * This is the predictive prefetch entry point.  It associates dnode access
+ * specified with blkid and nblks arguments with prefetch stream, predicts
+ * further accesses based on that stats and initiates speculative prefetch.
+ * fetch_data argument specifies whether actual data blocks should be fetched:
+ *   FALSE -- prefetch only indirect blocks for predicted data blocks;
+ *   TRUE -- prefetch predicted data blocks plus following indirect blocks.
  */
 void
-dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks)
+dmu_zfetch(zfetch_t *zf, uint64_t blkid, uint64_t nblks, boolean_t fetch_data)
 {
 	zstream_t *zs;
+	int64_t pf_start, ipf_start, ipf_istart, ipf_iend;
+	int64_t pf_ahead_blks, max_blks;
+	int epbs, max_dist_blks, pf_nblks, ipf_nblks;
+	uint64_t end_of_access_blkid = blkid + nblks;
 
 	if (zfs_prefetch_disable)
 		return;
@@ -250,7 +261,7 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid,
 		 */
 		ZFETCHSTAT_BUMP(zfetchstat_misses);
 		if (rw_tryupgrade(&zf->zf_rwlock))
-			dmu_zfetch_stream_create(zf, blkid + nblks);
+			dmu_zfetch_stream_create(zf, end_of_access_blkid);
 		rw_exit(&zf->zf_rwlock);
 		return;
 	}
@@ -262,35 +273,74 @@ dmu_zfetch(zfetch_t *zf, uint64_t blkid,
 	 * Normally, we start prefetching where we stopped
 	 * prefetching last (zs_pf_blkid).  But when we get our first
 	 * hit on this stream, zs_pf_blkid == zs_blkid, we don't
-	 * want to prefetch to block we just accessed.  In this case,
+	 * want to prefetch the block we just accessed.  In this case,
 	 * start just after the block we just accessed.
 	 */
-	int64_t pf_start = MAX(zs->zs_pf_blkid, blkid + nblks);
+	pf_start = MAX(zs->zs_pf_blkid, end_of_access_blkid);
 
 	/*
 	 * Double our amount of prefetched data, but don't let the
 	 * prefetch get further ahead than zfetch_max_distance.
 	 */
-	int pf_nblks =
-	    MIN((int64_t)zs->zs_pf_blkid - zs->zs_blkid + nblks,
-	    zs->zs_blkid + nblks +
-	    (zfetch_max_distance >> zf->zf_dnode->dn_datablkshift) - pf_start);
+	if (fetch_data) {
+		max_dist_blks =
+		    zfetch_max_distance >> zf->zf_dnode->dn_datablkshift;
+		/*
+		 * Previously, we were (zs_pf_blkid - blkid) ahead.  We
+		 * want to now be double that, so read that amount again,
+		 * plus the amount we are catching up by (i.e. the amount
+		 * read just now).
+		 */
+		pf_ahead_blks = zs->zs_pf_blkid - blkid + nblks;
+		max_blks = max_dist_blks - (pf_start - end_of_access_blkid);
+		pf_nblks = MIN(pf_ahead_blks, max_blks);
+	} else {
+		pf_nblks = 0;
+	}
 
 	zs->zs_pf_blkid = pf_start + pf_nblks;
-	zs->zs_atime = gethrtime();
-	zs->zs_blkid = blkid + nblks;
 
 	/*
-	 * dbuf_prefetch() issues the prefetch i/o
-	 * asynchronously, but it may need to wait for an
-	 * indirect block to be read from disk.  Therefore
-	 * we do not want to hold any locks while we call it.
+	 * Do the same for indirects, starting from where we stopped last,
+	 * or where we will stop reading data blocks (and the indirects
+	 * that point to them).
 	 */
+	ipf_start = MAX(zs->zs_ipf_blkid, zs->zs_pf_blkid);
+	max_dist_blks = zfetch_max_idistance >> zf->zf_dnode->dn_datablkshift;
+	/*
+	 * We want to double our distance ahead of the data prefetch
+	 * (or reader, if we are not prefetching data).  Previously, we
+	 * were (zs_ipf_blkid - blkid) ahead.  To double that, we read
+	 * that amount again, plus the amount we are catching up by
+	 * (i.e. the amount read now + the amount of data prefetched now).
+	 */
+	pf_ahead_blks = zs->zs_ipf_blkid - blkid + nblks + pf_nblks;
+	max_blks = max_dist_blks - (ipf_start - end_of_access_blkid);
+	ipf_nblks = MIN(pf_ahead_blks, max_blks);
+	zs->zs_ipf_blkid = ipf_start + ipf_nblks;
+
+	epbs = zf->zf_dnode->dn_indblkshift - SPA_BLKPTRSHIFT;
+	ipf_istart = P2ROUNDUP(ipf_start, 1 << epbs) >> epbs;
+	ipf_iend = P2ROUNDUP(zs->zs_ipf_blkid, 1 << epbs) >> epbs;
+
+	zs->zs_atime = gethrtime();
+	zs->zs_blkid = end_of_access_blkid;
 	mutex_exit(&zs->zs_lock);
 	rw_exit(&zf->zf_rwlock);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604121700.u3CH0DJ0065863>