From owner-svn-src-projects@freebsd.org Tue Apr 12 17:00:16 2016 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B81AFB0CE69 for ; Tue, 12 Apr 2016 17:00:16 +0000 (UTC) (envelope-from gjb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 811FC1AB0; Tue, 12 Apr 2016 17:00:16 +0000 (UTC) (envelope-from gjb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u3CH0FCN065883; Tue, 12 Apr 2016 17:00:15 GMT (envelope-from gjb@FreeBSD.org) Received: (from gjb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u3CH0DJ0065863; Tue, 12 Apr 2016 17:00:13 GMT (envelope-from gjb@FreeBSD.org) Message-Id: <201604121700.u3CH0DJ0065863@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gjb set sender to gjb@FreeBSD.org using -f From: Glen Barber Date: Tue, 12 Apr 2016 17:00:13 +0000 (UTC) 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/... X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Apr 2016 17:00:16 -0000 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 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 #include + +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 ***