Merge head

This commit is contained in:
Simon J. Gerraty 2014-04-27 08:13:43 +00:00
commit 9d2ab4a62d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/bmake/; revision=265006
830 changed files with 19444 additions and 49419 deletions

View File

@ -15,7 +15,7 @@
# -DNO_PORTSUPDATE do not update ports in ${MAKE} update
# -DNO_ROOT install without using root privilege
# -DNO_DOCUPDATE do not update doc in ${MAKE} update
# -DNO_CTF do not run the DTrace CTF conversion tools on built objects
# -DWITHOUT_CTF do not run the DTrace CTF conversion tools on built objects
# LOCAL_DIRS="list of dirs" to add additional dirs to the SUBDIR list
# LOCAL_LIB_DIRS="list of dirs" to add additional dirs to libraries target
# LOCAL_MTREE="list of mtree files" to process to allow local directories
@ -58,6 +58,7 @@
# use that new version. And the new (dynamically-linked) /bin/sh
# will expect to find appropriate libraries in /lib and /libexec.
#
SRCDIR?= ${.CURDIR}
.if defined(SUBDIR_OVERRIDE)
SUBDIR= ${SUBDIR_OVERRIDE}
.else
@ -84,6 +85,9 @@ SUBDIR+=secure
SUBDIR+=share
.endif
SUBDIR+=sys usr.bin usr.sbin
.if ${MK_TESTS} != "no"
SUBDIR+= tests
.endif
.if ${MK_OFED} != "no"
SUBDIR+=contrib/ofed
.endif
@ -128,11 +132,14 @@ OSRELDATE= 0
.endif
.if !defined(VERSION)
VERSION!= uname -srp
VERSION+= ${OSRELDATE}
REVISION!= ${MAKE} -C ${SRCDIR}/release -V REVISION
BRANCH!= ${MAKE} -C ${SRCDIR}/release -V BRANCH
SRCRELDATE!= awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \
${SRCDIR}/sys/sys/param.h
VERSION= FreeBSD ${REVISION}-${BRANCH:C/-p[0-9]+$//} ${TARGET_ARCH} ${SRCRELDATE}
.endif
KNOWN_ARCHES?= amd64 arm armeb/arm armv6/arm i386 i386/pc98 ia64 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64
KNOWN_ARCHES?= amd64 arm armeb/arm armv6/arm armv6hf/arm i386 i386/pc98 ia64 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64
.if ${TARGET} == ${TARGET_ARCH}
_t= ${TARGET}
.else
@ -224,22 +231,24 @@ CROSSENV+= GROFF_BIN_PATH=${WORLDTMP}/legacy/usr/bin \
GROFF_FONT_PATH=${WORLDTMP}/legacy/usr/share/groff_font \
GROFF_TMAC_PATH=${WORLDTMP}/legacy/usr/share/tmac
.endif
.if defined(TARGET_CFLAGS)
CROSSENV+= ${TARGET_CFLAGS}
.endif
# bootstrap-tools stage
BMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${BPATH}:${PATH} \
WORLDTMP=${WORLDTMP} \
VERSION="${VERSION}" \
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \
COMPILER_TYPE=${COMPILER_TYPE}
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}"
BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \
${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
DESTDIR= \
BOOTSTRAPPING=${OSRELDATE} \
SSP_CFLAGS= \
-DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT -DWITHOUT_MAN \
-DNO_PIC -DNO_PROFILE -DNO_SHARED \
-DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF -DEARLY_BUILD
MK_HTML=no MK_INFO=no NO_LINT=yes MK_MAN=no \
-DNO_PIC MK_PROFILE=no -DNO_SHARED \
-DNO_CPU_CFLAGS -DNO_WARNS MK_CTF=no -DEARLY_BUILD MK_TESTS=no
# build-tools stage
TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \
@ -249,12 +258,26 @@ TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \
BOOTSTRAPPING=${OSRELDATE} \
SSP_CFLAGS= \
-DNO_LINT \
-DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF -DEARLY_BUILD
-DNO_CPU_CFLAGS -DNO_WARNS MK_CTF=no -DEARLY_BUILD MK_TESTS=no
# cross-tools stage
XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \
TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
-DWITHOUT_GDB
MK_GDB=no MK_TESTS=no
# kernel-tools stage
KTMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${BPATH}:${PATH} \
WORLDTMP=${WORLDTMP} \
VERSION="${VERSION}"
KTMAKE= TOOLS_PREFIX=${WORLDTMP} MAKEOBJDIRPREFIX=${WORLDTMP} \
${KTMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
DESTDIR= \
BOOTSTRAPPING=${OSRELDATE} \
SSP_CFLAGS= \
MK_HTML=no MK_INFO=no -DNO_LINT MK_MAN=no \
-DNO_PIC MK_PROFILE=no -DNO_SHARED \
-DNO_CPU_CFLAGS -DNO_WARNS MK_CTF=no -DEARLY_BUILD
# world stage
WMAKEENV= ${CROSSENV} \
@ -271,7 +294,7 @@ HMAKE+= PATH=${TMPPATH} METALOG=${METALOG} -DNO_ROOT
.endif
.if ${MK_CDDL} == "no"
WMAKEENV+= NO_CTF=1
WMAKEENV+= MK_CTF=no
.endif
.if defined(CROSS_TOOLCHAIN_PREFIX)
@ -299,17 +322,6 @@ WMAKEENV+= CC="${XCC} ${XFLAGS}" CXX="${XCXX} ${XFLAGS}" \
AS="${XAS}" AR="${XAR}" LD="${XLD}" NM=${XNM} \
OBJDUMP=${XOBJDUMP} RANLIB=${XRANLIB} STRINGS=${XSTRINGS}
.if ${XCC:T:Mgcc} == "gcc"
WMAKE_COMPILER_TYPE= gcc
.elif ${XCC:T:Mclang} == "clang"
WMAKE_COMPILER_TYPE= clang
.elif ${MK_CLANG_IS_CC} == "no"
WMAKE_COMPILER_TYPE= gcc
.else
WMAKE_COMPILER_TYPE= clang
.endif
IMAKE_COMPILER_TYPE= COMPILER_TYPE=${WMAKE_COMPILER_TYPE}
.if ${XCC:M/*}
XFLAGS= --sysroot=${WORLDTMP}
.if defined(CROSS_BINUTILS_PREFIX)
@ -322,19 +334,18 @@ XFLAGS+= -B${CROSS_BINUTILS_PREFIX}
.else
XFLAGS+= -B${WORLDTMP}/usr/bin
.endif
.if ${TARGET_ARCH} != ${MACHINE_ARCH} && ${WMAKE_COMPILER_TYPE} == "clang"
.if (${TARGET_ARCH} == "arm" || ${TARGET_ARCH} == "armv6") && \
${MK_ARM_EABI} != "no"
.if ${TARGET} == "arm" && ${MK_ARM_EABI} != "no"
.if ${TARGET_ARCH:M*eb*} == ""
TARGET_ABI= gnueabi
.else
TARGET_ABI= unknown
.elif ${TARGET_ARCH} == "armv6hf"
TARGET_ABI= gnueabihf
.endif
.endif
TARGET_ABI?= unknown
TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd11.0
XFLAGS+= -target ${TARGET_TRIPLE}
.endif
.endif
WMAKEENV+= COMPILER_TYPE=${WMAKE_COMPILER_TYPE}
WMAKE= ${WMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 DESTDIR=${WORLDTMP}
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
@ -382,27 +393,26 @@ LIB32WMAKEENV+= MAKEOBJDIRPREFIX=${OBJTREE}/lib32 \
PATH=${TMPPATH} \
LIBDIR=/usr/lib32 \
SHLIBDIR=/usr/lib32 \
LIBPRIVATEDIR=/usr/lib32/private \
COMPILER_TYPE=${WMAKE_COMPILER_TYPE}
LIB32WMAKEFLAGS+= \
CC="${XCC} ${LIB32FLAGS}" \
LIBPRIVATEDIR=/usr/lib32/private
LIB32WMAKEFLAGS+= CC="${XCC} ${LIB32FLAGS}" \
CXX="${XCXX} ${LIB32FLAGS}" \
DESTDIR=${LIB32TMP} \
-DCOMPAT_32BIT \
-DLIBRARIES_ONLY \
-DNO_CPU_CFLAGS \
-DNO_CTF \
-DNO_LINT
MK_CTF=no \
-DNO_LINT \
MK_TESTS=no
LIB32WMAKE= ${LIB32WMAKEENV} ${MAKE} ${LIB32WMAKEFLAGS} \
-DWITHOUT_MAN -DWITHOUT_INFO -DWITHOUT_HTML
LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} -DNO_INCS \
${IMAKE_INSTALL}
MK_MAN=no MK_INFO=no MK_HTML=no
LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} \
MK_TOOLCHAIN=no ${IMAKE_INSTALL}
.endif
IMAKEENV= ${CROSSENV:N_LDSCRIPTROOT=*}
IMAKE= ${IMAKEENV} ${MAKE} -f Makefile.inc1 \
${IMAKE_INSTALL} ${IMAKE_MTREE} ${IMAKE_COMPILER_TYPE}
${IMAKE_INSTALL} ${IMAKE_MTREE}
.if empty(.MAKEFLAGS:M-n)
IMAKEENV+= PATH=${STRICTTMPPATH}:${INSTALLTMP} \
LD_LIBRARY_PATH=${INSTALLTMP} \
@ -425,7 +435,7 @@ MTREEFLAGS+= -W
.endif
.if defined(DB_FROM_SRC) || defined(NO_ROOT)
IMAKE_INSTALL= INSTALL="install ${INSTALLFLAGS}"
IMAKE_MTREE= MTREE_CMD="nmtree ${MTREEFLAGS}"
IMAKE_MTREE= MTREE_CMD="mtree ${MTREEFLAGS}"
.endif
# kernel stage
@ -485,6 +495,10 @@ _worldtmp:
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
-p ${WORLDTMP}/usr/lib >/dev/null
.endif
.if ${MK_TESTS} != "no"
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
-p ${WORLDTMP}/usr >/dev/null
.endif
.for _mtree in ${LOCAL_MTREE}
mtree -deU -f ${.CURDIR}/${_mtree} -p ${WORLDTMP} > /dev/null
.endfor
@ -529,6 +543,7 @@ _cross-tools:
@echo ">>> stage 3: cross tools"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; ${XMAKE} cross-tools
${_+_}cd ${.CURDIR}; ${XMAKE} kernel-tools
_includes:
@echo
@echo "--------------------------------------------------------------"
@ -541,8 +556,8 @@ _libraries:
@echo ">>> stage 4.2: building libraries"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; \
${WMAKE} -DNO_FSCHG -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT \
-DWITHOUT_MAN -DNO_PROFILE libraries
${WMAKE} -DNO_FSCHG MK_HTML=no MK_INFO=no -DNO_LINT MK_MAN=no \
MK_PROFILE=no MK_TESTS=no libraries
_depend:
@echo
@echo "--------------------------------------------------------------"
@ -594,7 +609,7 @@ build32:
WORLDTMP=${WORLDTMP} \
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \
MAKEOBJDIRPREFIX=${OBJTREE}/lib32 ${MAKE} SSP_CFLAGS= DESTDIR= \
DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF \
DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS -DNO_WARNS MK_CTF=no \
-DEARLY_BUILD build-tools
.endfor
cd ${.CURDIR}; \
@ -737,14 +752,10 @@ _install-info= install-info
_zoneinfo= zic tzsetup
.endif
.if exists(/usr/sbin/nmtree)
_nmtree_itools= nmtree
.endif
ITOOLS= [ awk cap_mkdb cat chflags chmod chown \
date echo egrep find grep id install ${_install-info} \
ln lockf make mkdir mtree ${_nmtree_itools} mv pwd_mkdb \
rm sed sh sysctl test true uname wc ${_zoneinfo}
ln lockf make mkdir mtree mv pwd_mkdb \
rm sed services_mkdb sh sysctl test true uname wc ${_zoneinfo}
#
# distributeworld
@ -806,11 +817,11 @@ distributeworld installworld: _installcheck_world
-p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib >/dev/null
.endif
.if defined(NO_ROOT)
${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.root.dist | \
${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.root.dist | \
sed -e 's#^\./#./${dist}/#' >> ${METALOG}
${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.usr.dist | \
${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.usr.dist | \
sed -e 's#^\./#./${dist}/usr/#' >> ${METALOG}
${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.include.dist | \
${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.include.dist | \
sed -e 's#^\./#./${dist}/usr/include/#' >> ${METALOG}
.endif
.endfor
@ -963,6 +974,8 @@ INSTALLKERNEL= ${_kernel}
.endif
.endfor
buildkernel ${WMAKE_TGTS} ${.ALLTARGETS:M_*}: .MAKE
#
# buildkernel
#
@ -988,7 +1001,7 @@ buildkernel:
cd ${KRNLCONFDIR}; \
PATH=${TMPPATH} \
config ${CONFIGARGS} -d ${KRNLOBJDIR}/${_kernel} \
${KERNCONFDIR}/${_kernel}
-I ${KERNCONFDIR} ${KERNCONFDIR}/${_kernel}
.endif
.if !defined(NO_CLEAN) && !defined(NO_KERNELCLEAN)
@echo
@ -1008,20 +1021,7 @@ buildkernel:
@echo "--------------------------------------------------------------"
@echo ">>> stage 2.3: build tools"
@echo "--------------------------------------------------------------"
cd ${KRNLOBJDIR}/${_kernel}; \
PATH=${BPATH}:${PATH} \
MAKESRCPATH=${KERNSRCDIR}/dev/aic7xxx/aicasm \
${MAKE} SSP_CFLAGS= -DNO_CPU_CFLAGS -DNO_CTF -DEARLY_BUILD \
-f ${KERNSRCDIR}/dev/aic7xxx/aicasm/Makefile
# XXX - Gratuitously builds aicasm in the ``makeoptions NO_MODULES'' case.
.if !defined(MODULES_WITH_WORLD) && !defined(NO_MODULES) && exists(${KERNSRCDIR}/modules)
.for target in obj depend all
cd ${KERNSRCDIR}/modules/aic7xxx/aicasm; \
PATH=${BPATH}:${PATH} \
MAKEOBJDIRPREFIX=${KRNLOBJDIR}/${_kernel}/modules \
${MAKE} SSP_CFLAGS= -DNO_CPU_CFLAGS -DNO_CTF -DEARLY_BUILD ${target}
.endfor
.endif
${_+_}cd ${.CURDIR}; ${KTMAKE} kernel-tools
.if !defined(NO_KERNELDEPEND)
@echo
@echo "--------------------------------------------------------------"
@ -1159,8 +1159,8 @@ update:
# legacy: Build compatibility shims for the next three targets
#
legacy:
.if ${BOOTSTRAPPING} < 700055 && ${BOOTSTRAPPING} != 0
@echo "ERROR: Source upgrades from versions prior to 7.0 not supported."; \
.if ${BOOTSTRAPPING} < 800107 && ${BOOTSTRAPPING} != 0
@echo "ERROR: Source upgrades from versions prior to 8.0 not supported."; \
false
.endif
.for _tool in tools/build
@ -1188,14 +1188,6 @@ _gperf= gnu/usr.bin/gperf
_groff= gnu/usr.bin/groff
.endif
.if ${BOOTSTRAPPING} < 800022
_ar= usr.bin/ar
.endif
.if ${BOOTSTRAPPING} < 800013
_mklocale= usr.bin/mklocale
.endif
.if ${BOOTSTRAPPING} < 900002
_sed= usr.bin/sed
.endif
@ -1234,7 +1226,9 @@ _awk= usr.bin/awk
_gensnmptree= usr.sbin/bsnmpd/gensnmptree
.endif
.if ${MK_CLANG} != "no"
# We need to build tlbgen when we're building clang either as
# the bootstrap compiler, or as the part of the normal build.
.if ${MK_CLANG_BOOTSTRAP} != "no" || ${MK_CLANG} != "no"
_clang_tblgen= \
lib/clang/libllvmsupport \
lib/clang/libllvmtablegen \
@ -1251,7 +1245,7 @@ _dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf lib/libelf \
lib/libdwarf cddl/usr.bin/ctfconvert cddl/usr.bin/ctfmerge
.endif
# Default to building the BSDL DTC, but build the GPL one if users explicitly
# Default to building the GPL DTC, but build the BSDL one if users explicitly
# request it.
_dtc= usr.bin/dtc
.if ${MK_GPL_DTC} != "no"
@ -1279,13 +1273,11 @@ bootstrap-tools: .MAKE
${_strfile} \
${_gperf} \
${_groff} \
${_ar} \
${_dtc} \
${_awk} \
${_cat} \
usr.bin/lorder \
usr.bin/makewhatis \
${_mklocale} \
usr.bin/rpcgen \
${_sed} \
${_yacc} \
@ -1308,10 +1300,6 @@ bootstrap-tools: .MAKE
#
# build-tools: Build special purpose build tools
#
.if defined(MODULES_WITH_WORLD) && exists(${KERNSRCDIR}/modules)
_aicasm= sys/modules/aic7xxx/aicasm
.endif
.if !defined(NO_SHARE)
_share= share/syscons/scrnmaps
.endif
@ -1333,7 +1321,6 @@ build-tools: .MAKE
lib/ncurses/ncurses \
lib/ncurses/ncursesw \
${_share} \
${_aicasm} \
usr.bin/awk \
lib/libmagic \
usr.bin/mkesdb_static \
@ -1353,10 +1340,21 @@ build-tools: .MAKE
${MAKE} DIRPRFX=${_tool}/ all
.endfor
#
# kernel-tools: Build kernel-building tools
#
kernel-tools: .MAKE
mkdir -p ${MAKEOBJDIRPREFIX}/usr
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
-p ${MAKEOBJDIRPREFIX}/usr >/dev/null
#
# cross-tools: Build cross-building tools
#
.if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${BOOTSTRAPPING} < 800035
.if !defined(TARGET_ARCH) && defined(XDEV_ARCH)
TARGET_ARCH= ${XDEV_ARCH}
.endif
.if ${TARGET_ARCH} != ${MACHINE_ARCH}
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386"
_btxld= usr.sbin/btxld
.endif
@ -1370,19 +1368,19 @@ _kgzip= usr.sbin/kgzip
.endif
.endif
.if ${XAS:M/*} == "" && ${MK_BINUTILS} != "no"
# If we're given an XAS, don't build binutils.
.if ${XAS:M/*} == "" && ${MK_BINUTILS_BOOTSTRAP} != "no"
_binutils= gnu/usr.bin/binutils
.endif
# If an full path to an external cross compiler is given, don't build
# a cross compiler.
.if ${XCC:M/*} == "" && ${MK_CROSS_COMPILER} != "no"
.if ${MK_CLANG} != "no" && (${MK_CLANG_IS_CC} != "no" || ${CC:T:Mclang} == "clang")
.if ${MK_CLANG_BOOTSTRAP} != "no"
_clang= usr.bin/clang
_clang_libs= lib/clang
.endif
.if ${MK_GCC} != "no" && (${MK_CLANG_IS_CC} == "no" || ${TARGET} == "pc98")
.if ${MK_GCC_BOOTSTRAP} != "no"
_cc= gnu/usr.bin/cc
.endif
.endif
@ -1446,11 +1444,13 @@ _startup_libs+= lib/csu/${MACHINE_CPUARCH}
_startup_libs+= gnu/lib/libgcc
_startup_libs+= lib/libcompiler_rt
_startup_libs+= lib/libc
_startup_libs+= lib/libc_nonshared
.if ${MK_LIBCPLUSPLUS} != "no"
_startup_libs+= lib/libcxxrt
.endif
gnu/lib/libgcc__L: lib/libc__L
gnu/lib/libgcc__L: lib/libc_nonshared__L
.if ${MK_LIBCPLUSPLUS} != "no"
lib/libcxxrt__L: gnu/lib/libgcc__L
.endif
@ -1464,22 +1464,31 @@ _prebuild_libs= ${_kerberos5_lib_libasn1} \
${_kerberos5_lib_libhx509} ${_kerberos5_lib_libkrb5} \
${_kerberos5_lib_libroken} \
${_kerberos5_lib_libwind} \
${_lib_atf_libatf_c} \
${_lib_atf} \
lib/libbz2 ${_libcom_err} lib/libcrypt \
lib/libelf lib/libexpat \
${_lib_libgssapi} ${_lib_libipx} \
lib/libkiconv lib/libkvm lib/liblzma lib/libmd \
${_lib_libgssapi} \
lib/libkiconv lib/libkvm lib/liblzma lib/libmd lib/libnv \
${_lib_libcapsicum} \
lib/ncurses/ncurses lib/ncurses/ncursesw \
lib/libopie lib/libpam ${_lib_libthr} \
lib/libradius lib/libsbuf lib/libtacplus \
${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \
${_cddl_lib_libzfs_core} \
lib/libutil ${_lib_libypclnt} lib/libz lib/msun \
lib/libutil lib/libpjdlog ${_lib_libypclnt} lib/libz lib/msun \
${_secure_lib_libcrypto} ${_lib_libldns} \
${_secure_lib_libssh} ${_secure_lib_libssl}
.if ${MK_GNUCXX} != "no" && ${MK_CXX} != "no"
_prebuild_libs+= gnu/lib/libstdc++ gnu/lib/libsupc++
.endif
.if ${MK_ATF} != "no"
_lib_atf_libatf_c= lib/atf/libatf-c
.if defined(WITH_ATF) || ${MK_TESTS} != "no"
.if !defined(WITH_ATF)
# Ensure that the ATF libraries will be built during make libraries, even
# though they will have WITHOUT_TESTS
MAKE+= -DWITH_ATF
.endif
_lib_atf= lib/atf
.endif
.if ${MK_LIBTHR} != "no"
@ -1490,6 +1499,13 @@ _lib_libthr= lib/libthr
_ofed_lib= contrib/ofed/usr.lib/
.endif
.if ${MK_CASPER} != "no"
_lib_libcapsicum=lib/libcapsicum
.endif
lib/libcapsicum__L: lib/libnv__L
lib/libpjdlog__L: lib/libutil__L
_generic_libs= ${_cddl_lib} gnu/lib ${_kerberos5_lib} lib ${_secure_lib} usr.bin/lex/lib ${_ofed_lib}
.for _DIR in ${LOCAL_LIB_DIRS}
.if exists(${.CURDIR}/${_DIR}/Makefile)
@ -1556,10 +1572,6 @@ kerberos5/lib/libheimsqlite__L: lib/libthr__L
_lib_libgssapi= lib/libgssapi
.endif
.if ${MK_IPX} != "no"
_lib_libipx= lib/libipx
.endif
.if ${MK_KERBEROS} != "no"
_kerberos5_lib= kerberos5/lib
_kerberos5_lib_libasn1= kerberos5/lib/libasn1
@ -1588,10 +1600,12 @@ ${_lib}__PL: .PHONY .MAKE
.if exists(${.CURDIR}/${_lib})
${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \
cd ${.CURDIR}/${_lib} && \
${MAKE} DIRPRFX=${_lib}/ obj && \
${MAKE} DIRPRFX=${_lib}/ depend && \
${MAKE} -DNO_PROFILE -DNO_PIC DIRPRFX=${_lib}/ all && \
${MAKE} -DNO_PROFILE -DNO_PIC DIRPRFX=${_lib}/ install
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj && \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ depend && \
${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \
DIRPRFX=${_lib}/ all && \
${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \
DIRPRFX=${_lib}/ install
.endif
.endfor
@ -1600,10 +1614,10 @@ ${_lib}__L: .PHONY .MAKE
.if exists(${.CURDIR}/${_lib})
${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \
cd ${.CURDIR}/${_lib} && \
${MAKE} DIRPRFX=${_lib}/ obj && \
${MAKE} DIRPRFX=${_lib}/ depend && \
${MAKE} DIRPRFX=${_lib}/ all && \
${MAKE} DIRPRFX=${_lib}/ install
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj && \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ depend && \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ all && \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ install
.endif
.endfor
@ -1613,10 +1627,12 @@ ${_lib}__L: .PHONY .MAKE
lib/libpam__L: .PHONY .MAKE
${_+_}@${ECHODIR} "===> lib/libpam (obj,depend,all,install)"; \
cd ${.CURDIR}/lib/libpam && \
${MAKE} DIRPRFX=lib/libpam/ obj && \
${MAKE} DIRPRFX=lib/libpam/ depend && \
${MAKE} DIRPRFX=lib/libpam/ -D_NO_LIBPAM_SO_YET all && \
${MAKE} DIRPRFX=lib/libpam/ -D_NO_LIBPAM_SO_YET install
${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ obj && \
${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ depend && \
${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ \
-D_NO_LIBPAM_SO_YET all && \
${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ \
-D_NO_LIBPAM_SO_YET install
_prereq_libs: ${_prereq_libs:S/$/__PL/}
_startup_libs: ${_startup_libs:S/$/__L/}
@ -1672,6 +1688,7 @@ delete-old-files:
# argument list will get too long. Using .for/.endfor make "loops" will make
# the Makefile parser segfault.
@exec 3<&0; \
cd ${.CURDIR}; \
${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
-V OLD_FILES -V "OLD_FILES:Musr/share/*.gz:R" | xargs -n1 | \
while read file; do \
@ -1694,7 +1711,8 @@ delete-old-files:
check-old-files:
@echo ">>> Checking for old files"
@${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
@cd ${.CURDIR}; \
${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
-V OLD_FILES -V "OLD_FILES:Musr/share/*.gz:R" | xargs -n1 | \
while read file; do \
if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \
@ -1715,6 +1733,7 @@ delete-old-libs:
@echo ">>> Removing old libraries"
@echo "${OLD_LIBS_MESSAGE}" | fmt
@exec 3<&0; \
cd ${.CURDIR}; \
${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
-V OLD_LIBS | xargs -n1 | \
while read file; do \
@ -1722,22 +1741,36 @@ delete-old-libs:
chflags noschg "${DESTDIR}/$${file}" 2>/dev/null || true; \
rm ${RM_I} "${DESTDIR}/$${file}" <&3; \
fi; \
for ext in debug symbols; do \
if ! [ -e "${DESTDIR}/$${file}" ] && [ -f \
"${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \
rm ${RM_I} "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" \
<&3; \
fi; \
done; \
done
@echo ">>> Old libraries removed"
check-old-libs:
@echo ">>> Checking for old libraries"
@${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
@cd ${.CURDIR}; \
${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
-V OLD_LIBS | xargs -n1 | \
while read file; do \
if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \
echo "${DESTDIR}/$${file}"; \
fi; \
for ext in debug symbols; do \
if [ -f "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \
echo "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}"; \
fi; \
done; \
done
delete-old-dirs:
@echo ">>> Removing old directories"
@${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
@cd ${.CURDIR}; \
${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
-V OLD_DIRS | xargs -n1 | sort -r | \
while read dir; do \
if [ -d "${DESTDIR}/$${dir}" ]; then \
@ -1750,7 +1783,8 @@ delete-old-dirs:
check-old-dirs:
@echo ">>> Checking for old directories"
@${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
@cd ${.CURDIR}; \
${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
-V OLD_DIRS | xargs -n1 | \
while read dir; do \
if [ -d "${DESTDIR}/$${dir}" ]; then \
@ -1799,7 +1833,7 @@ builddtb:
echo "ERROR: FDT_DTS_FILE must be specified!"; \
exit 1; \
fi; \
if [ ! -f ${.CURDIR}/sys/boot/fdt/dts/${FDT_DTS_FILE} ]; then \
if [ ! -f ${.CURDIR}/sys/boot/fdt/dts/${MACHINE}/${FDT_DTS_FILE} ]; then \
echo "ERROR: Specified DTS file (${FDT_DTS_FILE}) does not \
exist!"; \
exit 1; \
@ -1809,9 +1843,9 @@ builddtb:
directory"; \
fi
@PATH=${TMPPATH} \
dtc -O dtb -o \
${DTBOUTPUTPATH}/`echo ${FDT_DTS_FILE} | cut -d. -f1`.dtb -b 0 \
-p 1024 ${.CURDIR}/sys/boot/fdt/dts/${FDT_DTS_FILE}
${.CURDIR}/sys/tools/fdt/make_dtb.sh ${.CURDIR}/sys \
${FDT_DTS_FILE} \
${DTBOUTPUTPATH}/`basename ${FDT_DTS_FILE} .dts`
###############
@ -1823,28 +1857,34 @@ XDEV_CPUTYPE?=${CPUTYPE}
XDEV_CPUTYPE?=${TARGET_CPUTYPE}
.endif
NOFUN=-DNO_FSCHG -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT \
-DWITHOUT_MAN -DWITHOUT_NLS -DNO_PROFILE \
-DWITHOUT_KERBEROS -DWITHOUT_RESCUE -DNO_WARNS \
NOFUN=-DNO_FSCHG MK_HTML=no MK_INFO=no -DNO_LINT \
MK_MAN=no MK_NLS=no MK_PROFILE=no \
MK_KERBEROS=no MK_RESCUE=no MK_TESTS=no -DNO_WARNS \
TARGET=${XDEV} TARGET_ARCH=${XDEV_ARCH} \
CPUTYPE=${XDEV_CPUTYPE}
XDDIR=${XDEV_ARCH}-freebsd
XDTP=/usr/${XDDIR}
XDTP?=/usr/${XDDIR}
.if ${XDTP:N/*}
.error XDTP variable should be an absolute path
.endif
CDBENV=MAKEOBJDIRPREFIX=${MAKEOBJDIRPREFIX}/${XDDIR} \
INSTALL="sh ${.CURDIR}/tools/install.sh"
CDENV= ${CDBENV} \
_SHLIBDIRPREFIX=${XDDESTDIR} \
TOOLS_PREFIX=${XDDESTDIR}
TOOLS_PREFIX=${XDTP}
CD2CFLAGS=-isystem ${XDDESTDIR}/usr/include -L${XDDESTDIR}/usr/lib \
-B${XDDESTDIR}/usr/lib
CD2ENV=${CDENV} CC="${CC} ${CD2CFLAGS}" \
--sysroot=${XDDESTDIR}/ -B${XDDESTDIR}/usr/libexec \
-B${XDDESTDIR}/usr/bin -B${XDDESTDIR}/usr/lib
CD2ENV=${CDENV} CC="${CC} ${CD2CFLAGS}" CXX="${CXX} ${CD2CFLAGS}" \
CPP="${CPP} ${CD2CFLAGS}" \
MACHINE=${XDEV} MACHINE_ARCH=${XDEV_ARCH}
CDTMP= ${MAKEOBJDIRPREFIX}/${XDDIR}/${.CURDIR}/tmp
CDMAKE=${CDENV} PATH=${CDTMP}/usr/bin:${PATH} ${MAKE} ${NOFUN}
CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDTP}/usr/bin:${PATH} ${MAKE} ${NOFUN}
XDDESTDIR=${DESTDIR}${XDTP}
CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDDESTDIR}/usr/bin:${PATH} ${MAKE} ${NOFUN}
XDDESTDIR=${DESTDIR}/${XDTP}
.if !defined(OSREL)
OSREL!= uname -r | sed -e 's/[-(].*//'
.endif
@ -1877,11 +1917,11 @@ _xb-build-tools:
_xb-cross-tools:
.for _tool in \
gnu/usr.bin/binutils \
gnu/usr.bin/cc \
${_binutils} \
usr.bin/ar \
${_clang_libs} \
${_clang}
${_clang} \
${_cc}
${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,depend,all)"; \
cd ${.CURDIR}/${_tool} && \
${CDMAKE} DIRPRFX=${_tool}/ obj && \
@ -1905,10 +1945,11 @@ xdev-install: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries _x
_xi-cross-tools:
@echo "_xi-cross-tools"
.for _tool in \
gnu/usr.bin/binutils \
gnu/usr.bin/cc \
${_binutils} \
usr.bin/ar \
${_clang}
${_clang_libs} \
${_clang} \
${_cc}
${_+_}@${ECHODIR} "===> xdev ${_tool} (install)"; \
cd ${.CURDIR}/${_tool}; \
${CDMAKE} DIRPRFX=${_tool}/ install DESTDIR=${XDDESTDIR}
@ -1924,6 +1965,7 @@ _xi-libraries:
_xi-links:
${_+_}cd ${XDDESTDIR}/usr/bin; \
mkdir -p ../../../../usr/bin; \
for i in *; do \
ln -sf ../../${XDTP}/usr/bin/$$i \
../../../../usr/bin/${XDDIR}-$$i; \
@ -1934,5 +1976,3 @@ _xi-links:
xdev xdev-build xdev-install:
@echo "*** Error: Both XDEV and XDEV_ARCH must be defined for \"${.TARGET}\" target"
.endif
buildkernel ${WMAKE_TGTS} ${.ALLTARGETS:M_*}: .MAKE

View File

@ -1,5 +1,11 @@
# $FreeBSD$
.include <bsd.own.mk>
SUBDIR= lib sbin usr.bin usr.sbin
.if ${MK_TESTS} != "no"
SUBDIR+=tests
.endif
.include <bsd.subdir.mk>

View File

@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ASSERTION:
* Checks that setting "bufresize" to "auto" will cause buffer
@ -34,14 +32,8 @@
* SECTION: Buffers and Buffering/Buffer Resizing Policy;
* Options and Tunables/bufsize;
* Options and Tunables/bufresize
*
* NOTES:
* We use the undocumented "preallocate" option to make sure dtrace(1M)
* has enough space in its heap to allocate a buffer as large as the
* kernel's trace buffer.
*/
#pragma D option preallocate=100t
#pragma D option bufresize=auto
#pragma D option bufsize=100t

View File

@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ASSERTION:
* Checks that setting "bufresize" to "auto" will cause buffer
@ -34,14 +32,8 @@
* SECTION: Buffers and Buffering/Buffer Resizing Policy;
* Options and Tunables/aggsize;
* Options and Tunables/bufresize
*
* NOTES:
* We use the undocumented "preallocate" option to make sure dtrace(1M)
* has enough space in its heap to allocate a buffer as large as the
* kernel's trace buffer.
*/
#pragma D option preallocate=100t
#pragma D option bufresize=auto
#pragma D option aggsize=100t

View File

@ -0,0 +1,97 @@
#
# 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) 2012, Joyent, Inc. All rights reserved.
#
let j=8
enable()
{
prog=/var/tmp/dtest.$$.d
err=/var/tmp/dtest.$$.err
nawk -v nprobes=$1 'BEGIN { \
for (i = 0; i < nprobes - 1; i++) { \
printf("dtrace:::BEGIN,\n"); \
} \
\
printf("dtrace:::BEGIN { exit(0); }\n"); \
}' /dev/null > $prog
dtrace -qs $prog > /dev/null 2> $err
if [[ "$?" -eq 0 ]]; then
return 0
else
if ! grep "DIF program exceeds maximum program size" $err \
1> /dev/null 2>&1 ; then
echo "failed to enable $prog: `cat $err`"
exit 1
fi
return 1
fi
}
#
# First, establish an upper bound
#
let upper=1
while enable $upper ; do
let lower=upper
let upper=upper+upper
echo success at $lower, raised to $upper
done
#
# Now search for the highest value that can be enabled
#
while [[ "$lower" -lt "$upper" ]]; do
let guess=$(((lower + upper) / 2))
echo "lower is $lower; upper is $upper; guess is $guess\c"
if enable $guess ; then
if [[ $((upper - lower)) -le 2 ]]; then
let upper=guess
fi
echo " (success)"
let lower=guess
else
echo " (failure)"
let upper=guess
fi
done
let expected=10000
if [[ "$lower" -lt "$expected" ]]; then
echo "expected support for enablings of at least $expected probes; \c"
echo "found $lower"
exit 1
fi
echo "maximum supported enabled probes found to be $lower"
exit 0

View File

@ -44,7 +44,7 @@ BEGIN
printf("\n");
printf("%%a = %a\n", &`kmem_alloc);
printf("%%a = %a\n", &`malloc);
printf("%%c = %c\n", i);
printf("%%d = %d\n", i);
printf("%%hd = %hd\n", (short)i);

View File

@ -1,5 +1,5 @@
%a = genunix`kmem_alloc
%a = kernel`malloc
%c = a
%d = 97
%hd = 97

View File

@ -36,6 +36,6 @@
BEGIN
{
printf("sysname = %s", `utsname.sysname);
printf("sysname = %s", `ostype);
exit(0);
}

View File

@ -1 +1 @@
sysname = SunOS
sysname = FreeBSD

View File

@ -38,6 +38,6 @@
BEGIN
{
printf("symbol = %a", &`kmem_alloc);
printf("symbol = %a", &`malloc);
exit(0);
}

View File

@ -1 +1 @@
symbol = kernel`kmem_alloc
symbol = kernel`malloc

View File

@ -64,7 +64,7 @@ child=$!
# ksh doing work. (This actually goes one step further and assumes that we
# catch some non-static function in ksh.)
#
script | tee /dev/fd/2 | grep 'ksh`[a-zA-Z_]' > /dev/null
script | tee /dev/fd/2 | egrep 'ksh(93)?`[a-zA-Z_]' > /dev/null
status=$?
kill $child

View File

@ -62,7 +62,7 @@ child=$!
#
# The only thing we can be sure of here is that ksh is doing some work.
#
script | tee /dev/fd/2 | grep -w ksh > /dev/null
script | tee /dev/fd/2 | egrep -w 'ksh(93)?' > /dev/null
status=$?
kill $child

View File

@ -63,7 +63,7 @@ child=$!
# This test is essentially the same as that in the ufunc test; see that
# test for the rationale.
#
script | tee /dev/fd/2 | grep 'ksh`[a-zA-Z_]' > /dev/null
script | tee /dev/fd/2 | egrep 'ksh(93)?`[a-zA-Z_]' > /dev/null
status=$?
kill $child

File diff suppressed because it is too large Load Diff

View File

@ -179,8 +179,19 @@ symtab_init(void)
size_t sz;
#endif
#if defined(__FreeBSD__)
if ((fd = open("/dev/ksyms", O_RDONLY)) == -1) {
if (errno == ENOENT && modfind("ksyms") == -1) {
kldload("ksyms");
fd = open("/dev/ksyms", O_RDONLY);
}
if (fd == -1)
return (-1);
}
#else
if ((fd = open("/dev/ksyms", O_RDONLY)) == -1)
return (-1);
#endif
#if defined(sun)
(void) elf_version(EV_CURRENT);

View File

@ -778,7 +778,8 @@ main(int argc, char **argv)
#endif
int err;
int opt_C = 0, opt_H = 0, opt_p = 0, opt_v = 0;
char c, *p, *end;
int c;
char *p, *end;
struct sigaction act;
int done = 0;

View File

@ -14,11 +14,12 @@
.\"
.\" Copyright 2012, Richard Lowe.
.\" Copyright (c) 2012, Marcelo Araujo <araujo@FreeBSD.org>.
.\" Copyright (c) 2012 by Delphix. All rights reserved.
.\" All Rights Reserved.
.\"
.\" $FreeBSD$
.\"
.Dd May 10, 2012
.Dd March 20, 2014
.Dt ZDB 8
.Os
.Sh NAME
@ -29,27 +30,35 @@
.Op Fl CumdibcsDvhLXFPA
.Op Fl e Op Fl p Ar path...
.Op Fl t Ar txg
.Op Fl U Ar cache
.Op Fl M Ar inflight I/Os
.Ar poolname
.Op Ar object ...
.Nm
.Op Fl divPA
.Op Fl e Op Fl p Ar path...
.Op Fl U Ar cache
.Ar dataset
.Op Ar object ...
.Nm
.Fl m Op Fl LXFPA
.Op Fl t Ar txg
.Op Fl e Op Fl p Ar path...
.Op Fl U Ar cache
.Ar poolname
.Nm
.Fl R Op Fl A
.Op Fl e Op Fl p Ar path...
.Op Fl U Ar cache
.Ar poolname
.Ar poolname
.Ar vdev Ns : Ns Ar offset Ns : Ns Ar size Ns Op Ns : Ns Ar flags
.Nm
.Fl S
.Op Fl AP
.Op Fl e Op Fl p Ar path...
.Op Fl U Ar cache
.Ar poolname
.Ar poolname
.Nm
.Fl l
@ -118,6 +127,12 @@ compression ratio (compress), inflation due to the zfs copies property
If specified twice, display a histogram of deduplication statistics, showing
the allocated (physically present on disk) and referenced (logically
referenced in the pool) block counts and sizes by reference count.
.Pp
If specified a third time, display the statistics independently for each deduplication table.
.Pp
If specified a fourth time, dump the contents of the deduplication tables describing duplicate blocks.
.Pp
If specified a fifth time, also dump the contents of the deduplication tables describing unique blocks.
.It Fl h
Display pool history similar to
.Cm zpool history ,
@ -205,6 +220,11 @@ flag specifies the path under which devices are to be searched.
.It Fl F
Attempt to make an unreadable pool readable by trying progressively older
transactions.
.It Fl M Ar inflight I/Os
Limit the number of outstanding checksum I/Os to the specified value.
The default value is 200. This option affects the performance of the
.Fl c
option.
.It Fl P
Print numbers in an unscaled form more amenable to parsing, eg. 1000000 rather
than 1M.
@ -218,9 +238,7 @@ options for a means to see the available uberblocks and their associated
transaction numbers.
.It Fl U Ar cachefile
Use a cache file other than
.Pa /etc/zfs/zpool.cache .
This option is only valid with
.Fl C
.Pa /boot/zfs/zpool.cache .
.It Fl v
Enable verbosity.
Specify multiple times for increased verbosity.

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
*/
#include <stdio.h>
@ -89,6 +89,7 @@ extern void dump_intent_log(zilog_t *);
uint64_t *zopt_object = NULL;
int zopt_objects = 0;
libzfs_handle_t *g_zfs;
uint64_t max_inflight = 200;
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
@ -110,16 +111,17 @@ static void
usage(void)
{
(void) fprintf(stderr,
"Usage: %s [-CumdibcsDvhLXFPA] [-t txg] [-e [-p path...]]"
"poolname [object...]\n"
" %s [-divPA] [-e -p path...] dataset [object...]\n"
" %s -m [-LXFPA] [-t txg] [-e [-p path...]]"
"poolname [vdev [metaslab...]]\n"
" %s -R [-A] [-e [-p path...]] poolname "
"vdev:offset:size[:flags]\n"
" %s -S [-PA] [-e [-p path...]] poolname\n"
" %s -l [-uA] device\n"
" %s -C [-A] [-U config]\n\n",
"Usage: %s [-CumdibcsDvhLXFPA] [-t txg] [-e [-p path...]] "
"[-U config] [-M inflight I/Os] poolname [object...]\n"
" %s [-divPA] [-e -p path...] [-U config] dataset "
"[object...]\n"
" %s -m [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
"poolname [vdev [metaslab...]]\n"
" %s -R [-A] [-e [-p path...]] poolname "
"vdev:offset:size[:flags]\n"
" %s -S [-PA] [-e [-p path...]] [-U config] poolname\n"
" %s -l [-uA] device\n"
" %s -C [-A] [-U config]\n\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
(void) fprintf(stderr, " Dataset name must include at least one "
@ -164,6 +166,8 @@ usage(void)
(void) fprintf(stderr, " -P print numbers in parseable form\n");
(void) fprintf(stderr, " -t <txg> -- highest txg to use when "
"searching for uberblocks\n");
(void) fprintf(stderr, " -M <number of inflight I/Os> -- "
"specify the maximum number of checksumming I/Os [default is 200]");
(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
"to make only that option verbose\n");
(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
@ -242,7 +246,7 @@ const char histo_stars[] = "****************************************";
const int histo_width = sizeof (histo_stars) - 1;
static void
dump_histogram(const uint64_t *histo, int size)
dump_histogram(const uint64_t *histo, int size, int offset)
{
int i;
int minidx = size - 1;
@ -263,7 +267,7 @@ dump_histogram(const uint64_t *histo, int size)
for (i = minidx; i <= maxidx; i++) {
(void) printf("\t\t\t%3u: %6llu %s\n",
i, (u_longlong_t)histo[i],
i + offset, (u_longlong_t)histo[i],
&histo_stars[(max - histo[i]) * histo_width / max]);
}
}
@ -316,19 +320,19 @@ dump_zap_stats(objset_t *os, uint64_t object)
(u_longlong_t)zs.zs_salt);
(void) printf("\t\tLeafs with 2^n pointers:\n");
dump_histogram(zs.zs_leafs_with_2n_pointers, ZAP_HISTOGRAM_SIZE);
dump_histogram(zs.zs_leafs_with_2n_pointers, ZAP_HISTOGRAM_SIZE, 0);
(void) printf("\t\tBlocks with n*5 entries:\n");
dump_histogram(zs.zs_blocks_with_n5_entries, ZAP_HISTOGRAM_SIZE);
dump_histogram(zs.zs_blocks_with_n5_entries, ZAP_HISTOGRAM_SIZE, 0);
(void) printf("\t\tBlocks n/10 full:\n");
dump_histogram(zs.zs_blocks_n_tenths_full, ZAP_HISTOGRAM_SIZE);
dump_histogram(zs.zs_blocks_n_tenths_full, ZAP_HISTOGRAM_SIZE, 0);
(void) printf("\t\tEntries with n chunks:\n");
dump_histogram(zs.zs_entries_using_n_chunks, ZAP_HISTOGRAM_SIZE);
dump_histogram(zs.zs_entries_using_n_chunks, ZAP_HISTOGRAM_SIZE, 0);
(void) printf("\t\tBuckets with n entries:\n");
dump_histogram(zs.zs_buckets_with_n_entries, ZAP_HISTOGRAM_SIZE);
dump_histogram(zs.zs_buckets_with_n_entries, ZAP_HISTOGRAM_SIZE, 0);
}
/*ARGSUSED*/
@ -517,26 +521,89 @@ dump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
zap_cursor_fini(&zc);
}
int
get_dtl_refcount(vdev_t *vd)
{
int refcount = 0;
if (vd->vdev_ops->vdev_op_leaf) {
space_map_t *sm = vd->vdev_dtl_sm;
if (sm != NULL &&
sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
return (1);
return (0);
}
for (int c = 0; c < vd->vdev_children; c++)
refcount += get_dtl_refcount(vd->vdev_child[c]);
return (refcount);
}
int
get_metaslab_refcount(vdev_t *vd)
{
int refcount = 0;
if (vd->vdev_top == vd) {
for (int m = 0; m < vd->vdev_ms_count; m++) {
space_map_t *sm = vd->vdev_ms[m]->ms_sm;
if (sm != NULL &&
sm->sm_dbuf->db_size == sizeof (space_map_phys_t))
refcount++;
}
}
for (int c = 0; c < vd->vdev_children; c++)
refcount += get_metaslab_refcount(vd->vdev_child[c]);
return (refcount);
}
static int
verify_spacemap_refcounts(spa_t *spa)
{
uint64_t expected_refcount = 0;
uint64_t actual_refcount;
(void) feature_get_refcount(spa,
&spa_feature_table[SPA_FEATURE_SPACEMAP_HISTOGRAM],
&expected_refcount);
actual_refcount = get_dtl_refcount(spa->spa_root_vdev);
actual_refcount += get_metaslab_refcount(spa->spa_root_vdev);
if (expected_refcount != actual_refcount) {
(void) printf("space map refcount mismatch: expected %lld != "
"actual %lld\n",
(longlong_t)expected_refcount,
(longlong_t)actual_refcount);
return (2);
}
return (0);
}
static void
dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
dump_spacemap(objset_t *os, space_map_t *sm)
{
uint64_t alloc, offset, entry;
uint8_t mapshift = sm->sm_shift;
uint64_t mapstart = sm->sm_start;
char *ddata[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
"INVALID", "INVALID", "INVALID", "INVALID" };
if (smo->smo_object == 0)
if (sm == NULL)
return;
/*
* Print out the freelist entries in both encoded and decoded form.
*/
alloc = 0;
for (offset = 0; offset < smo->smo_objsize; offset += sizeof (entry)) {
VERIFY3U(0, ==, dmu_read(os, smo->smo_object, offset,
for (offset = 0; offset < space_map_length(sm);
offset += sizeof (entry)) {
uint8_t mapshift = sm->sm_shift;
VERIFY0(dmu_read(os, space_map_object(sm), offset,
sizeof (entry), &entry, DMU_READ_PREFETCH));
if (SM_DEBUG_DECODE(entry)) {
(void) printf("\t [%6llu] %s: txg %llu, pass %llu\n",
(u_longlong_t)(offset / sizeof (entry)),
ddata[SM_DEBUG_ACTION_DECODE(entry)],
@ -548,10 +615,10 @@ dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
(u_longlong_t)(offset / sizeof (entry)),
SM_TYPE_DECODE(entry) == SM_ALLOC ? 'A' : 'F',
(u_longlong_t)((SM_OFFSET_DECODE(entry) <<
mapshift) + mapstart),
mapshift) + sm->sm_start),
(u_longlong_t)((SM_OFFSET_DECODE(entry) <<
mapshift) + mapstart + (SM_RUN_DECODE(entry) <<
mapshift)),
mapshift) + sm->sm_start +
(SM_RUN_DECODE(entry) << mapshift)),
(u_longlong_t)(SM_RUN_DECODE(entry) << mapshift));
if (SM_TYPE_DECODE(entry) == SM_ALLOC)
alloc += SM_RUN_DECODE(entry) << mapshift;
@ -559,10 +626,10 @@ dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
alloc -= SM_RUN_DECODE(entry) << mapshift;
}
}
if (alloc != smo->smo_alloc) {
if (alloc != space_map_allocated(sm)) {
(void) printf("space_map_object alloc (%llu) INCONSISTENT "
"with space map summary (%llu)\n",
(u_longlong_t)smo->smo_alloc, (u_longlong_t)alloc);
(u_longlong_t)space_map_allocated(sm), (u_longlong_t)alloc);
}
}
@ -570,15 +637,17 @@ static void
dump_metaslab_stats(metaslab_t *msp)
{
char maxbuf[32];
space_map_t *sm = msp->ms_map;
avl_tree_t *t = sm->sm_pp_root;
int free_pct = sm->sm_space * 100 / sm->sm_size;
range_tree_t *rt = msp->ms_tree;
avl_tree_t *t = &msp->ms_size_tree;
int free_pct = range_tree_space(rt) * 100 / msp->ms_size;
zdb_nicenum(space_map_maxsize(sm), maxbuf);
zdb_nicenum(metaslab_block_maxsize(msp), maxbuf);
(void) printf("\t %25s %10lu %7s %6s %4s %4d%%\n",
"segments", avl_numnodes(t), "maxsize", maxbuf,
"freepct", free_pct);
(void) printf("\tIn-memory histogram:\n");
dump_histogram(rt->rt_histogram, RANGE_TREE_HISTOGRAM_SIZE, 0);
}
static void
@ -586,33 +655,44 @@ dump_metaslab(metaslab_t *msp)
{
vdev_t *vd = msp->ms_group->mg_vd;
spa_t *spa = vd->vdev_spa;
space_map_t *sm = msp->ms_map;
space_map_obj_t *smo = &msp->ms_smo;
space_map_t *sm = msp->ms_sm;
char freebuf[32];
zdb_nicenum(sm->sm_size - smo->smo_alloc, freebuf);
zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf);
(void) printf(
"\tmetaslab %6llu offset %12llx spacemap %6llu free %5s\n",
(u_longlong_t)(sm->sm_start / sm->sm_size),
(u_longlong_t)sm->sm_start, (u_longlong_t)smo->smo_object, freebuf);
(u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
(u_longlong_t)space_map_object(sm), freebuf);
if (dump_opt['m'] > 1 && !dump_opt['L']) {
if (dump_opt['m'] > 2 && !dump_opt['L']) {
mutex_enter(&msp->ms_lock);
space_map_load_wait(sm);
if (!sm->sm_loaded)
VERIFY(space_map_load(sm, zfs_metaslab_ops,
SM_FREE, smo, spa->spa_meta_objset) == 0);
metaslab_load_wait(msp);
if (!msp->ms_loaded) {
VERIFY0(metaslab_load(msp));
range_tree_stat_verify(msp->ms_tree);
}
dump_metaslab_stats(msp);
space_map_unload(sm);
metaslab_unload(msp);
mutex_exit(&msp->ms_lock);
}
if (dump_opt['d'] > 5 || dump_opt['m'] > 2) {
ASSERT(sm->sm_size == (1ULL << vd->vdev_ms_shift));
if (dump_opt['m'] > 1 && sm != NULL &&
spa_feature_is_active(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
/*
* The space map histogram represents free space in chunks
* of sm_shift (i.e. bucket 0 refers to 2^sm_shift).
*/
(void) printf("\tOn-disk histogram:\n");
dump_histogram(sm->sm_phys->smp_histogram,
SPACE_MAP_HISTOGRAM_SIZE(sm), sm->sm_shift);
}
if (dump_opt['d'] > 5 || dump_opt['m'] > 3) {
ASSERT(msp->ms_size == (1ULL << vd->vdev_ms_shift));
mutex_enter(&msp->ms_lock);
dump_spacemap(spa->spa_meta_objset, smo, sm);
dump_spacemap(spa->spa_meta_objset, msp->ms_sm);
mutex_exit(&msp->ms_lock);
}
}
@ -684,7 +764,7 @@ dump_dde(const ddt_t *ddt, const ddt_entry_t *dde, uint64_t index)
if (ddp->ddp_phys_birth == 0)
continue;
ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk);
sprintf_blkptr(blkbuf, &blk);
snprintf_blkptr(blkbuf, sizeof (blkbuf), &blk);
(void) printf("index %llx refcnt %llu %s %s\n",
(u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt,
types[p], blkbuf);
@ -801,9 +881,9 @@ dump_all_ddts(spa_t *spa)
}
static void
dump_dtl_seg(space_map_t *sm, uint64_t start, uint64_t size)
dump_dtl_seg(void *arg, uint64_t start, uint64_t size)
{
char *prefix = (void *)sm;
char *prefix = arg;
(void) printf("%s [%llu,%llu) length %llu\n",
prefix,
@ -833,28 +913,32 @@ dump_dtl(vdev_t *vd, int indent)
required ? "DTL-required" : "DTL-expendable");
for (int t = 0; t < DTL_TYPES; t++) {
space_map_t *sm = &vd->vdev_dtl[t];
if (sm->sm_space == 0)
range_tree_t *rt = vd->vdev_dtl[t];
if (range_tree_space(rt) == 0)
continue;
(void) snprintf(prefix, sizeof (prefix), "\t%*s%s",
indent + 2, "", name[t]);
mutex_enter(sm->sm_lock);
space_map_walk(sm, dump_dtl_seg, (void *)prefix);
mutex_exit(sm->sm_lock);
mutex_enter(rt->rt_lock);
range_tree_walk(rt, dump_dtl_seg, prefix);
mutex_exit(rt->rt_lock);
if (dump_opt['d'] > 5 && vd->vdev_children == 0)
dump_spacemap(spa->spa_meta_objset,
&vd->vdev_dtl_smo, sm);
dump_spacemap(spa->spa_meta_objset, vd->vdev_dtl_sm);
}
for (int c = 0; c < vd->vdev_children; c++)
dump_dtl(vd->vdev_child[c], indent + 4);
}
/* from spa_history.c: spa_history_create_obj() */
#define HIS_BUF_LEN_DEF (128 << 10)
#define HIS_BUF_LEN_MAX (1 << 30)
static void
dump_history(spa_t *spa)
{
nvlist_t **events = NULL;
char buf[SPA_MAXBLOCKSIZE];
char *buf = NULL;
uint64_t bufsize = HIS_BUF_LEN_DEF;
uint64_t resid, len, off = 0;
uint_t num = 0;
int error;
@ -863,8 +947,11 @@ dump_history(spa_t *spa)
char tbuf[30];
char internalstr[MAXPATHLEN];
if ((buf = malloc(bufsize)) == NULL)
(void) fprintf(stderr, "Unable to read history: "
"out of memory\n");
do {
len = sizeof (buf);
len = bufsize;
if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
(void) fprintf(stderr, "Unable to read history: "
@ -874,9 +961,26 @@ dump_history(spa_t *spa)
if (zpool_history_unpack(buf, len, &resid, &events, &num) != 0)
break;
off -= resid;
/*
* If the history block is too big, double the buffer
* size and try again.
*/
if (resid == len) {
free(buf);
buf = NULL;
bufsize <<= 1;
if ((bufsize >= HIS_BUF_LEN_MAX) ||
((buf = malloc(bufsize)) == NULL)) {
(void) fprintf(stderr, "Unable to read history: "
"out of memory\n");
return;
}
}
} while (len != 0);
free(buf);
(void) printf("\nHistory:\n");
for (int i = 0; i < num; i++) {
@ -945,31 +1049,39 @@ blkid2offset(const dnode_phys_t *dnp, const blkptr_t *bp, const zbookmark_t *zb)
}
static void
sprintf_blkptr_compact(char *blkbuf, const blkptr_t *bp)
snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp)
{
const dva_t *dva = bp->blk_dva;
int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
if (dump_opt['b'] >= 6) {
sprintf_blkptr(blkbuf, bp);
snprintf_blkptr(blkbuf, buflen, bp);
return;
}
blkbuf[0] = '\0';
for (int i = 0; i < ndvas; i++)
(void) sprintf(blkbuf + strlen(blkbuf), "%llu:%llx:%llx ",
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), "%llu:%llx:%llx ",
(u_longlong_t)DVA_GET_VDEV(&dva[i]),
(u_longlong_t)DVA_GET_OFFSET(&dva[i]),
(u_longlong_t)DVA_GET_ASIZE(&dva[i]));
(void) sprintf(blkbuf + strlen(blkbuf),
"%llxL/%llxP F=%llu B=%llu/%llu",
(u_longlong_t)BP_GET_LSIZE(bp),
(u_longlong_t)BP_GET_PSIZE(bp),
(u_longlong_t)bp->blk_fill,
(u_longlong_t)bp->blk_birth,
(u_longlong_t)BP_PHYSICAL_BIRTH(bp));
if (BP_IS_HOLE(bp)) {
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), "B=%llu",
(u_longlong_t)bp->blk_birth);
} else {
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf),
"%llxL/%llxP F=%llu B=%llu/%llu",
(u_longlong_t)BP_GET_LSIZE(bp),
(u_longlong_t)BP_GET_PSIZE(bp),
(u_longlong_t)bp->blk_fill,
(u_longlong_t)bp->blk_birth,
(u_longlong_t)BP_PHYSICAL_BIRTH(bp));
}
}
static void
@ -994,7 +1106,7 @@ print_indirect(blkptr_t *bp, const zbookmark_t *zb,
}
}
sprintf_blkptr_compact(blkbuf, bp);
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp);
(void) printf("%s\n", blkbuf);
}
@ -1009,7 +1121,7 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
print_indirect(bp, zb, dnp);
if (BP_GET_LEVEL(bp) > 0) {
if (BP_GET_LEVEL(bp) > 0 && !BP_IS_HOLE(bp)) {
uint32_t flags = ARC_WAIT;
int i;
blkptr_t *cbp;
@ -1134,7 +1246,7 @@ dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
zdb_nicenum(ds->ds_compressed_bytes, compressed);
zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed);
zdb_nicenum(ds->ds_unique_bytes, unique);
sprintf_blkptr(blkbuf, &ds->ds_bp);
snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp);
(void) printf("\t\tdir_obj = %llu\n",
(u_longlong_t)ds->ds_dir_obj);
@ -1179,7 +1291,7 @@ dump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
char blkbuf[BP_SPRINTF_LEN];
if (bp->blk_birth != 0) {
sprintf_blkptr(blkbuf, bp);
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("\t%s\n", blkbuf);
}
return (0);
@ -1217,7 +1329,7 @@ dump_bpobj_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
char blkbuf[BP_SPRINTF_LEN];
ASSERT(bp->blk_birth != 0);
sprintf_blkptr_compact(blkbuf, bp);
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp);
(void) printf("\t%s\n", blkbuf);
return (0);
}
@ -1716,8 +1828,9 @@ dump_dir(objset_t *os)
zdb_nicenum(refdbytes, numbuf);
if (verbosity >= 4) {
(void) sprintf(blkbuf, ", rootbp ");
(void) sprintf_blkptr(blkbuf + strlen(blkbuf), os->os_rootbp);
(void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp ");
(void) snprintf_blkptr(blkbuf + strlen(blkbuf),
sizeof (blkbuf) - strlen(blkbuf), os->os_rootbp);
} else {
blkbuf[0] = '\0';
}
@ -1747,7 +1860,7 @@ dump_dir(objset_t *os)
if (verbosity < 2)
return;
if (os->os_rootbp->blk_birth == 0)
if (BP_IS_HOLE(os->os_rootbp))
return;
dump_object(os, 0, verbosity, &print_header);
@ -1788,7 +1901,7 @@ dump_uberblock(uberblock_t *ub, const char *header, const char *footer)
(u_longlong_t)ub->ub_timestamp, asctime(localtime(&timestamp)));
if (dump_opt['u'] >= 3) {
char blkbuf[BP_SPRINTF_LEN];
sprintf_blkptr(blkbuf, &ub->ub_rootbp);
snprintf_blkptr(blkbuf, sizeof (blkbuf), &ub->ub_rootbp);
(void) printf("\trootbp = %s\n", blkbuf);
}
(void) printf(footer ? footer : "");
@ -2079,16 +2192,68 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
bp, NULL, NULL, ZIO_FLAG_CANFAIL)), ==, 0);
}
/* ARGSUSED */
static void
zdb_blkptr_done(zio_t *zio)
{
spa_t *spa = zio->io_spa;
blkptr_t *bp = zio->io_bp;
int ioerr = zio->io_error;
zdb_cb_t *zcb = zio->io_private;
zbookmark_t *zb = &zio->io_bookmark;
zio_data_buf_free(zio->io_data, zio->io_size);
mutex_enter(&spa->spa_scrub_lock);
spa->spa_scrub_inflight--;
cv_broadcast(&spa->spa_scrub_io_cv);
if (ioerr && !(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
char blkbuf[BP_SPRINTF_LEN];
zcb->zcb_haderrors = 1;
zcb->zcb_errors[ioerr]++;
if (dump_opt['b'] >= 2)
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
else
blkbuf[0] = '\0';
(void) printf("zdb_blkptr_cb: "
"Got error %d reading "
"<%llu, %llu, %lld, %llx> %s -- skipping\n",
ioerr,
(u_longlong_t)zb->zb_objset,
(u_longlong_t)zb->zb_object,
(u_longlong_t)zb->zb_level,
(u_longlong_t)zb->zb_blkid,
blkbuf);
}
mutex_exit(&spa->spa_scrub_lock);
}
/* ARGSUSED */
static int
zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
zdb_cb_t *zcb = arg;
char blkbuf[BP_SPRINTF_LEN];
dmu_object_type_t type;
boolean_t is_metadata;
if (bp == NULL)
if (dump_opt['b'] >= 5 && bp->blk_birth > 0) {
char blkbuf[BP_SPRINTF_LEN];
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("objset %llu object %llu "
"level %lld offset 0x%llx %s\n",
(u_longlong_t)zb->zb_objset,
(u_longlong_t)zb->zb_object,
(longlong_t)zb->zb_level,
(u_longlong_t)blkid2offset(dnp, bp, zb),
blkbuf);
}
if (BP_IS_HOLE(bp))
return (0);
type = BP_GET_TYPE(bp);
@ -2099,53 +2264,26 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
is_metadata = (BP_GET_LEVEL(bp) != 0 || DMU_OT_IS_METADATA(type));
if (dump_opt['c'] > 1 || (dump_opt['c'] && is_metadata)) {
int ioerr;
size_t size = BP_GET_PSIZE(bp);
void *data = malloc(size);
void *data = zio_data_buf_alloc(size);
int flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_SCRUB | ZIO_FLAG_RAW;
/* If it's an intent log block, failure is expected. */
if (zb->zb_level == ZB_ZIL_LEVEL)
flags |= ZIO_FLAG_SPECULATIVE;
ioerr = zio_wait(zio_read(NULL, spa, bp, data, size,
NULL, NULL, ZIO_PRIORITY_ASYNC_READ, flags, zb));
mutex_enter(&spa->spa_scrub_lock);
while (spa->spa_scrub_inflight > max_inflight)
cv_wait(&spa->spa_scrub_io_cv, &spa->spa_scrub_lock);
spa->spa_scrub_inflight++;
mutex_exit(&spa->spa_scrub_lock);
free(data);
if (ioerr && !(flags & ZIO_FLAG_SPECULATIVE)) {
zcb->zcb_haderrors = 1;
zcb->zcb_errors[ioerr]++;
if (dump_opt['b'] >= 2)
sprintf_blkptr(blkbuf, bp);
else
blkbuf[0] = '\0';
(void) printf("zdb_blkptr_cb: "
"Got error %d reading "
"<%llu, %llu, %lld, %llx> %s -- skipping\n",
ioerr,
(u_longlong_t)zb->zb_objset,
(u_longlong_t)zb->zb_object,
(u_longlong_t)zb->zb_level,
(u_longlong_t)zb->zb_blkid,
blkbuf);
}
zio_nowait(zio_read(NULL, spa, bp, data, size,
zdb_blkptr_done, zcb, ZIO_PRIORITY_ASYNC_READ, flags, zb));
}
zcb->zcb_readfails = 0;
if (dump_opt['b'] >= 5) {
sprintf_blkptr(blkbuf, bp);
(void) printf("objset %llu object %llu "
"level %lld offset 0x%llx %s\n",
(u_longlong_t)zb->zb_objset,
(u_longlong_t)zb->zb_object,
(longlong_t)zb->zb_level,
(u_longlong_t)blkid2offset(dnp, bp, zb),
blkbuf);
}
if (dump_opt['b'] < 5 && isatty(STDERR_FILENO) &&
gethrtime() > zcb->zcb_lastprint + NANOSEC) {
uint64_t now = gethrtime();
@ -2172,39 +2310,17 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
}
static void
zdb_leak(space_map_t *sm, uint64_t start, uint64_t size)
zdb_leak(void *arg, uint64_t start, uint64_t size)
{
vdev_t *vd = sm->sm_ppd;
vdev_t *vd = arg;
(void) printf("leaked space: vdev %llu, offset 0x%llx, size %llu\n",
(u_longlong_t)vd->vdev_id, (u_longlong_t)start, (u_longlong_t)size);
}
/* ARGSUSED */
static void
zdb_space_map_load(space_map_t *sm)
{
}
static void
zdb_space_map_unload(space_map_t *sm)
{
space_map_vacate(sm, zdb_leak, sm);
}
/* ARGSUSED */
static void
zdb_space_map_claim(space_map_t *sm, uint64_t start, uint64_t size)
{
}
static space_map_ops_t zdb_space_map_ops = {
zdb_space_map_load,
zdb_space_map_unload,
static metaslab_ops_t zdb_metaslab_ops = {
NULL, /* alloc */
zdb_space_map_claim,
NULL, /* free */
NULL /* maxsize */
NULL /* fragmented */
};
static void
@ -2259,11 +2375,21 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
for (int m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
mutex_enter(&msp->ms_lock);
space_map_unload(msp->ms_map);
VERIFY(space_map_load(msp->ms_map,
&zdb_space_map_ops, SM_ALLOC, &msp->ms_smo,
spa->spa_meta_objset) == 0);
msp->ms_map->sm_ppd = vd;
metaslab_unload(msp);
/*
* For leak detection, we overload the metaslab
* ms_tree to contain allocated segments
* instead of free segments. As a result,
* we can't use the normal metaslab_load/unload
* interfaces.
*/
if (msp->ms_sm != NULL) {
msp->ms_ops = &zdb_metaslab_ops;
VERIFY0(space_map_load(msp->ms_sm,
msp->ms_tree, SM_ALLOC));
msp->ms_loaded = B_TRUE;
}
mutex_exit(&msp->ms_lock);
}
}
@ -2286,7 +2412,20 @@ zdb_leak_fini(spa_t *spa)
for (int m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
mutex_enter(&msp->ms_lock);
space_map_unload(msp->ms_map);
/*
* The ms_tree has been overloaded to
* contain allocated segments. Now that we
* finished traversing all blocks, any
* block that remains in the ms_tree
* represents an allocated block that we
* did not claim during the traversal.
* Claimed blocks would have been removed
* from the ms_tree.
*/
range_tree_vacate(msp->ms_tree, zdb_leak, vd);
msp->ms_loaded = B_FALSE;
mutex_exit(&msp->ms_lock);
}
}
@ -2301,7 +2440,7 @@ count_block_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
if (dump_opt['b'] >= 5) {
char blkbuf[BP_SPRINTF_LEN];
sprintf_blkptr(blkbuf, bp);
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("[%s] %s\n",
"deferred free", blkbuf);
}
@ -2344,8 +2483,7 @@ dump_block_stats(spa_t *spa)
(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
count_block_cb, &zcb, NULL);
}
if (spa_feature_is_active(spa,
&spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
if (spa_feature_is_active(spa, SPA_FEATURE_ASYNC_DESTROY)) {
VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
&zcb, NULL));
@ -2358,6 +2496,18 @@ dump_block_stats(spa_t *spa)
zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
zcb.zcb_haderrors |= traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
/*
* If we've traversed the data blocks then we need to wait for those
* I/Os to complete. We leverage "The Godfather" zio to wait on
* all async I/Os to complete.
*/
if (dump_opt['c']) {
(void) zio_wait(spa->spa_async_zio_root);
spa->spa_async_zio_root = zio_root(spa, NULL, NULL,
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
ZIO_FLAG_GODFATHER);
}
if (zcb.zcb_haderrors) {
(void) printf("\nError counts:\n\n");
(void) printf("\t%5s %s\n", "errno", "count");
@ -2489,7 +2639,7 @@ dump_block_stats(spa_t *spa)
"(in 512-byte sectors): "
"number of blocks\n");
dump_histogram(zb->zb_psize_histogram,
PSIZE_HISTO_SIZE);
PSIZE_HISTO_SIZE, 0);
}
}
}
@ -2524,7 +2674,7 @@ zdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
avl_index_t where;
zdb_ddt_entry_t *zdde, zdde_search;
if (bp == NULL)
if (BP_IS_HOLE(bp))
return (0);
if (dump_opt['S'] > 1 && zb->zb_level == ZB_ROOT_LEVEL) {
@ -2591,7 +2741,8 @@ dump_simulated_ddt(spa_t *spa)
dds.dds_ref_psize = zdde->zdde_ref_psize;
dds.dds_ref_dsize = zdde->zdde_ref_dsize;
ddt_stat_add(&ddh_total.ddh_stat[highbit(refcnt) - 1], &dds, 0);
ddt_stat_add(&ddh_total.ddh_stat[highbit64(refcnt) - 1],
&dds, 0);
umem_free(zdde, sizeof (*zdde));
}
@ -2646,7 +2797,7 @@ dump_zpool(spa_t *spa)
}
if (spa_feature_is_active(spa,
&spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
SPA_FEATURE_ASYNC_DESTROY)) {
dump_bptree(spa->spa_meta_objset,
spa->spa_dsl_pool->dp_bptree_obj,
"Pool dataset frees");
@ -2659,6 +2810,9 @@ dump_zpool(spa_t *spa)
if (dump_opt['b'] || dump_opt['c'])
rc = dump_block_stats(spa);
if (rc == 0)
rc = verify_spacemap_refcounts(spa);
if (dump_opt['s'])
show_pool_stats(spa);
@ -2688,7 +2842,7 @@ zdb_print_blkptr(blkptr_t *bp, int flags)
if (flags & ZDB_FLAG_BSWAP)
byteswap_uint64_array((void *)bp, sizeof (blkptr_t));
sprintf_blkptr(blkbuf, bp);
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("%s\n", blkbuf);
}
@ -2884,6 +3038,7 @@ zdb_read_block(char *thing, spa_t *spa)
free(dup);
return;
}
i += p - &flagstr[i + 1]; /* skip over the number */
}
}
@ -3124,7 +3279,7 @@ main(int argc, char **argv)
dprintf_setup(&argc, argv);
while ((c = getopt(argc, argv, "bcdhilmsuCDRSAFLXevp:t:U:P")) != -1) {
while ((c = getopt(argc, argv, "bcdhilmM:suCDRSAFLXevp:t:U:P")) != -1) {
switch (c) {
case 'b':
case 'c':
@ -3153,6 +3308,15 @@ main(int argc, char **argv)
case 'v':
verbose++;
break;
case 'M':
max_inflight = strtoull(optarg, NULL, 0);
if (max_inflight == 0) {
(void) fprintf(stderr, "maximum number "
"of inflight I/Os must be greater "
"than 0\n");
usage();
}
break;
case 'p':
if (searchdirs == NULL) {
searchdirs = umem_alloc(sizeof (char *),

View File

@ -23,6 +23,10 @@
* Use is subject to license terms.
*/
/*
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
/*
* Print intent log header and statistics.
*/
@ -47,7 +51,7 @@ print_log_bp(const blkptr_t *bp, const char *prefix)
{
char blkbuf[BP_SPRINTF_LEN];
sprintf_blkptr(blkbuf, bp);
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("%s%s\n", prefix, blkbuf);
}
@ -132,6 +136,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
(void) printf("%shas blkptr, %s\n", prefix,
!BP_IS_HOLE(bp) &&
bp->blk_birth >= spa_first_txg(zilog->zl_spa) ?
"will claim" : "won't claim");
print_log_bp(bp, prefix);
@ -139,8 +144,6 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
if (BP_IS_HOLE(bp)) {
(void) printf("\t\t\tLSIZE 0x%llx\n",
(u_longlong_t)BP_GET_LSIZE(bp));
}
if (bp->blk_birth == 0) {
bzero(buf, sizeof (buf));
(void) printf("%s<hole>\n", prefix);
return;
@ -313,7 +316,8 @@ print_log_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
if (verbose >= 5) {
(void) strcpy(blkbuf, ", ");
sprintf_blkptr(blkbuf + strlen(blkbuf), bp);
snprintf_blkptr(blkbuf + strlen(blkbuf),
sizeof (blkbuf) - strlen(blkbuf), bp);
} else {
blkbuf[0] = '\0';
}
@ -361,7 +365,7 @@ dump_intent_log(zilog_t *zilog)
int verbose = MAX(dump_opt['d'], dump_opt['i']);
int i;
if (zh->zh_log.blk_birth == 0 || verbose < 1)
if (BP_IS_HOLE(&zh->zh_log) || verbose < 1)
return;
(void) printf("\n ZIL header: claim_txg %llu, "

View File

@ -18,17 +18,19 @@
.\" information: Portions Copyright [yyyy] [name of copyright owner]
.\"
.\" Copyright (c) 2010, Sun Microsystems, Inc. All Rights Reserved.
.\" Copyright (c) 2012 by Delphix. All rights reserved.
.\" Copyright (c) 2013 by Delphix. All rights reserved.
.\" Copyright (c) 2011, Pawel Jakub Dawidek <pjd@FreeBSD.org>
.\" Copyright (c) 2012, Glen Barber <gjb@FreeBSD.org>
.\" Copyright (c) 2012, Bryan Drewery <bdrewery@FreeBSD.org>
.\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
.\" Copyright (c) 2013 Nexenta Systems, Inc. All Rights Reserved.
.\" Copyright (c) 2013, Joyent, Inc. All rights reserved.
.\" Copyright (c) 2014, Joyent, Inc. All rights reserved.
.\" Copyright (c) 2013, Steven Hartland <smh@FreeBSD.org>
.\" Copyright (c) 2014, Xin LI <delphij@FreeBSD.org>
.\"
.\" $FreeBSD$
.\"
.Dd September 20, 2013
.Dd April 23, 2014
.Dt ZFS 8
.Os
.Sh NAME
@ -56,12 +58,17 @@
.Cm destroy
.Op Fl dnpRrv
.Sm off
.Ar snapshot
.Op % Ns Ar snapname
.Ar filesystem Ns | Ns volume
.Ns @snap
.Op % Ns Ar snap
.Op , Ns Ar snap Op % Ns Ar snap
.Op , Ns ...
.Sm on
.Nm
.Cm snapshot
.Cm destroy
.Ar filesystem Ns | Ns Ar volume Ns # Ns Ar bookmark
.Nm
.Cm snapshot Ns | Ns Cm snap
.Op Fl r
.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ...
.Ar filesystem@snapname Ns | Ns Ar volume@snapname
@ -101,7 +108,7 @@
.Nm
.Cm list
.Op Fl r Ns | Ns Fl d Ar depth
.Op Fl H
.Op Fl Hp
.Op Fl o Ar property Ns Oo , Ns property Ns Oc Ns ...
.Op Fl t Ar type Ns Oo , Ns type Ns Oc Ns ...
.Oo Fl s Ar property Oc Ns ...
@ -157,7 +164,7 @@
.Op Fl o Ar property Ns Oo , Ns Ar property Oc Ns ...
.Fl a | Ar filesystem
.Nm
.Cm unmount
.Cm unmount Ns | Ns Cm umount
.Op Fl f
.Fl a | Ar filesystem Ns | Ns Ar mountpoint
.Nm
@ -167,16 +174,24 @@
.Cm unshare
.Fl a | Ar filesystem Ns | Ns Ar mountpoint
.Nm
.Cm bookmark
.Ar snapshot
.Ar bookmark
.Nm
.Cm send
.Op Fl DnPpRv
.Op Fl i Ar snapshot | Fl I Ar snapshot
.Ar snapshot
.Nm
.Cm receive
.Cm send
.Op Fl i Ar snapshot Ns | Ns bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Nm
.Cm receive Ns | Ns Cm recv
.Op Fl vnFu
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Nm
.Cm receive
.Cm receive Ns | Ns Cm recv
.Op Fl vnFu
.Op Fl d | e
.Ar filesystem
@ -527,6 +542,13 @@ if the snapshot has been marked for deferred destroy by using the
.Qq Nm Cm destroy -d
command. Otherwise, the property is
.Cm off .
.It Sy filesystem_count
The total number of filesystems and volumes that exist under this location in the
dataset tree.
This value is only available when a
.Sy filesystem_limit
has
been set somewhere in the tree under which the dataset resides.
.It Sy logicalreferenced
The amount of space that is
.Qq logically
@ -585,6 +607,12 @@ The compression ratio achieved for the
space of this dataset, expressed as a multiplier. See also the
.Sy compressratio
property.
.It Sy snapshot_count
The total number of snapshots that exist under this location in the dataset tree.
This value is only available when a
.Sy snapshot_limit
has been set somewhere
in the tree under which the dataset resides.
.It Sy type
The type of dataset:
.Sy filesystem , volume , No or Sy snapshot .
@ -1005,6 +1033,23 @@ The
.Sy mlslabel
property is currently not supported on
.Fx .
.It Sy filesystem_limit Ns = Ns Ar count | Cm none
Limits the number of filesystems and volumes that can exist under this point in
the dataset tree.
The limit is not enforced if the user is allowed to change
the limit.
Setting a
.Sy filesystem_limit
on a descendent of a filesystem that
already has a
.Sy filesystem_limit
does not override the ancestor's
.Sy filesystem_limit ,
but rather imposes an additional limit.
This feature must be enabled to be used
.Po see
.Xr zpool-features 7
.Pc .
.It Sy mountpoint Ns = Ns Ar path | Cm none | legacy
Controls the mount point used for this file system. See the
.Qq Sx Mount Points
@ -1046,6 +1091,27 @@ the ancestor's quota, but rather imposes an additional limit.
Quotas cannot be set on volumes, as the
.Sy volsize
property acts as an implicit quota.
.It Sy snapshot_limit Ns = Ns Ar count | Cm none
Limits the number of snapshots that can be created on a dataset and its
descendents.
Setting a
.Sy snapshot_limit
on a descendent of a dataset that already
has a
.Sy snapshot_limit
does not override the ancestor's
.Sy snapshot_limit ,
but
rather imposes an additional limit.
The limit is not enforced if the user is
allowed to change the limit.
For example, this means that recursive snapshots
taken from the global zone are counted against each delegated dataset within
a jail.
This feature must be enabled to be used
.Po see
.Xr zpool-features 7
.Pc .
.It Sy userquota@ Ns Ar user Ns = Ns Ar size | Cm none
Limits the amount of space consumed by the specified user.
Similar to the
@ -1291,6 +1357,38 @@ Consequently, writes to a sparse volume can fail with
when the pool is low on space. For a sparse volume, changes to
.Sy volsize
are not reflected in the reservation.
.It Sy volmode Ns = Ns Cm default | geom | dev | none
This property specifies how volumes should be exposed to the OS.
Setting it to
.Sy geom
exposes volumes as
.Xr geom 4
providers, providing maximal functionality.
Setting it to
.Sy dev
exposes volumes only as cdev device in devfs.
Such volumes can be accessed only as raw disk device files, i.e. they
can not be partitioned, mounted, participate in RAIDs, etc, but they
are faster, and in some use scenarios with untrusted consumer, such as
NAS or VM storage, can be more safe.
Volumes with property set to
.Sy none
are not exposed outside ZFS, but can be snapshoted, cloned, replicated, etc,
that can be suitable for backup purposes.
Value
.Sy default
means that volumes exposition is controlled by system-wide sysctl/tunable
.Va vfs.zfs.vol.mode ,
where
.Sy geom ,
.Sy dev
and
.Sy none
are encoded as 1, 2 and 3 respectively.
The default values is
.Sy geom .
This property can be changed any time, but so far it is processed only
during volume creation and pool import.
.It Sy vscan Ns = Ns Cm off | on
The
.Sy vscan
@ -1320,10 +1418,21 @@ features being supported, the new file system will have the default values for
these properties.
.Bl -tag -width 4n
.It Sy casesensitivity Ns = Ns Cm sensitive | insensitive | mixed
The
Indicates whether the file name matching algorithm used by the file system
should be case-sensitive, case-insensitive, or allow a combination of both
styles of matching. The default value for the
.Sy casesensitivity
property is currently not supported on
.Fx .
property is
.Cm sensitive .
Traditionally, UNIX and POSIX file systems have case-sensitive file names.
.Pp
The
.Cm mixed
value for the
.Sy casesensitivity
property indicates that the
file system can support requests for both case-sensitive and case-insensitive
matching behavior.
.It Sy normalization Ns = Ns Cm none | formC | formD | formKC | formKD
Indicates whether the file system should perform a
.Sy unicode
@ -1653,7 +1762,14 @@ options, as they can destroy large portions of a pool and cause unexpected
behavior for mounted file systems in use.
.It Xo
.Nm
.Cm snapshot
.Cm destroy
.Ar filesystem Ns | Ns Ar volume Ns # Ns Ar bookmark
.Xc
.Pp
The given bookmark is destroyed.
.It Xo
.Nm
.Cm snapshot Ns | Ns Cm snap
.Op Fl r
.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ...
.Ar filesystem@snapname Ns | Ns volume@snapname
@ -1685,14 +1801,24 @@ Roll back the given dataset to a previous snapshot. When a dataset is rolled
back, all data that has changed since the snapshot is discarded, and the
dataset reverts to the state at the time of the snapshot. By default, the
command refuses to roll back to a snapshot other than the most recent one. In
order to do so, all intermediate snapshots must be destroyed by specifying the
order to do so, all intermediate snapshots and bookmarks must be destroyed
by specifying the
.Fl r
option.
.Pp
The
.Fl rR
options do not recursively destroy the child snapshots of a
recursive snapshot.
Only direct snapshots of the specified filesystem
are destroyed by either of these options.
To completely roll back a
recursive snapshot, you must rollback the individual child snapshots.
.Bl -tag -width indent
.It Fl r
Recursively destroy any snapshots more recent than the one specified.
Destroy any snapshots and bookmarks more recent than the one specified.
.It Fl R
Recursively destroy any more recent snapshots, as well as any clones of those
Destroy any more recent snapshots and bookmarks, as well as any clones of those
snapshots.
.It Fl f
Used with the
@ -1806,7 +1932,7 @@ only dataset that can be renamed recursively.
.Nm
.Cm list
.Op Fl r Ns | Ns Fl d Ar depth
.Op Fl H
.Op Fl Hp
.Op Fl o Ar property Ns Oo , Ns Ar property Oc Ns ...
.Op Fl t Ar type Ns Oo , Ns Ar type Oc Ns ...
.Oo Fl s Ar property Oc Ns ...
@ -1837,6 +1963,8 @@ will display only the dataset and its direct children.
.It Fl H
Used for scripting mode. Do not print headers and separate fields by a single
tab instead of arbitrary white space.
.It Fl p
Display numbers in parsable (exact) values.
.It Fl o Ar property Ns Oo , Ns Ar property Oc Ns ...
A comma-separated list of properties to display. The property must be:
.Bl -bullet -offset 2n
@ -1865,7 +1993,7 @@ syntax.
A comma-separated list of types to display, where
.Ar type
is one of
.Sy filesystem , snapshot , volume , No or Sy all .
.Sy filesystem , snapshot , snap , volume , bookmark , No or Sy all .
For example, specifying
.Fl t Cm snapshot
displays only snapshots.
@ -1962,7 +2090,7 @@ sections.
The special value
.Cm all
can be used to display all properties that apply to the given dataset's type
(filesystem, volume, or snapshot).
(filesystem, volume, snapshot, or bookmark).
.Bl -tag -width indent
.It Fl r
Recursively display properties for any children.
@ -1977,7 +2105,7 @@ Display output in a form more easily parsed by scripts. Any headers are
omitted, and fields are explicitly separated by a single tab instead of an
arbitrary amount of space.
.It Fl p
Display numbers in parseable (exact) values.
Display numbers in parsable (exact) values.
.It Fl o Cm all | Ar field Ns Oo , Ns Ar field Oc Ns ...
A comma-separated list of columns to display. Supported values are
.Sy name,property,value,received,source .
@ -2194,7 +2322,7 @@ Mount the specified filesystem.
.El
.It Xo
.Nm
.Cm unmount
.Cm unmount Ns | Ns Cm umount
.Op Fl f
.Fl a | Ar filesystem Ns | Ns Ar mountpoint
.Xc
@ -2280,6 +2408,26 @@ file system shared on the system.
.El
.It Xo
.Nm
.Cm bookmark
.Ar snapshot
.Ar bookmark
.Xc
.Pp
Creates a bookmark of the given snapshot.
Bookmarks mark the point in time
when the snapshot was created, and can be used as the incremental source for
a
.Qq Nm Cm send
command.
.Pp
This feature must be enabled to be used.
See
.Xr zpool-features 7
for details on ZFS feature flags and the
.Sy bookmark
feature.
.It Xo
.Nm
.Cm send
.Op Fl DnPpRv
.Op Fl i Ar snapshot | Fl I Ar snapshot
@ -2298,17 +2446,15 @@ a file or to a different system (for example, using
By default, a full stream is generated.
.Bl -tag -width indent
.It Fl i Ar snapshot
Generate an incremental stream from the
.Fl i Ar snapshot
to the last
.Ar snapshot .
The incremental source (the
.Fl i Ar snapshot )
can be specified as the last component of the snapshot name (for example, the
part after the
.Sy @ ) ,
and it is assumed to be from the same file system as the last
.Ar snapshot .
Generate an incremental stream from the first
.Ar snapshot Pq the incremental source
to the second
.Ar snapshot Pq the incremental target .
The incremental source can be specified as the last component of the
snapshot name
.Pq the Em @ No character and following
and
it is assumed to be from the same file system as the incremental target.
.Pp
If the destination is a clone, the source may be the origin snapshot, which
must be fully specified (for example,
@ -2316,15 +2462,16 @@ must be fully specified (for example,
not just
.Cm @origin ) .
.It Fl I Ar snapshot
Generate a stream package that sends all intermediary snapshots from the
.Fl I Ar snapshot
to the last
Generate a stream package that sends all intermediary snapshots from the first
.Ar snapshot
to the second
.Ar snapshot .
For example,
.Ic -I @a fs@d
is similar to
.Ic -i @a fs@b; -i @b fs@c; -i @c fs@d .
The incremental source snapshot may be specified as with the
The incremental
source may be specified as with the
.Fl i
option.
.It Fl R
@ -2377,13 +2524,42 @@ on future versions of
.Tn ZFS .
.It Xo
.Nm
.Cm receive
.Cm send
.Op Fl i Ar snapshot Ns | Ns Ar bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Xc
.Pp
Generate a send stream, which may be of a filesystem, and may be
incremental from a bookmark.
If the destination is a filesystem or volume,
the pool must be read-only, or the filesystem must not be mounted.
When the
stream generated from a filesystem or volume is received, the default snapshot
name will be
.Pq --head-- .
.Bl -tag -width indent
.It Fl i Ar snapshot Ns | Ns bookmark
Generate an incremental send stream.
The incremental source must be an earlier
snapshot in the destination's history.
It will commonly be an earlier
snapshot in the destination's filesystem, in which case it can be
specified as the last component of the name
.Pq the Em # No or Em @ No character and following .
.Pp
If the incremental target is a clone, the incremental source can
be the origin snapshot, or an earlier snapshot in the origin's filesystem,
or the origin's origin, etc.
.El
.It Xo
.Nm
.Cm receive Ns | Ns Cm recv
.Op Fl vnFu
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Xc
.It Xo
.Nm
.Cm receive
.Cm receive Ns | Ns Cm recv
.Op Fl vnFu
.Op Fl d | e
.Ar filesystem
@ -2474,7 +2650,7 @@ option to verify the name the receive operation would use.
Force a rollback of the file system to the most recent snapshot before
performing the receive operation. If receiving an incremental replication
stream (for example, one generated by
.Qq Nm Cm send Fl R Fi iI ) ,
.Qq Nm Cm send Fl R Bro Fl i | Fl I Brc ) ,
destroy snapshots and file systems that do not exist on the sending side.
.El
.It Xo
@ -2613,6 +2789,7 @@ protocol
.It dedup Ta property
.It devices Ta property
.It exec Ta property
.It filesystem_limit Ta property
.It logbias Ta property
.It jailed Ta property
.It mlslabel Ta property
@ -2631,6 +2808,7 @@ protocol
.It sharenfs Ta property
.It sharesmb Ta property
.It snapdir Ta property
.It snapshot_limit Ta property
.It sync Ta property
.It utf8only Ta property
.It version Ta property
@ -2819,7 +2997,7 @@ option of
.It \&P Ta event port (not supported on Fx )
.El
.It Fl H
Give more parseable tab-separated output, without header lines and without
Give more parsable tab-separated output, without header lines and without
arrows.
.It Fl t
Display the path's inode change time as the first column of output.
@ -2977,10 +3155,12 @@ pool/home/bob compression on local
pool/home/bob atime on default
pool/home/bob devices on default
pool/home/bob exec on default
pool/home/bob filesystem_limit none default
pool/home/bob setuid on default
pool/home/bob readonly off default
pool/home/bob jailed off default
pool/home/bob snapdir hidden default
pool/home/bob snapshot_limit none default
pool/home/bob aclmode discard default
pool/home/bob aclinherit restricted default
pool/home/bob canmount on default

View File

@ -18,10 +18,13 @@
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <libintl.h>
@ -70,7 +73,7 @@ uu_avl_pool_t *avl_pool;
* Include snaps if they were requested or if this a zfs list where types
* were not specified and the "listsnapshots" property is set on this pool.
*/
static int
static boolean_t
zfs_include_snapshots(zfs_handle_t *zhp, callback_data_t *cb)
{
zpool_handle_t *zph;
@ -90,8 +93,9 @@ static int
zfs_callback(zfs_handle_t *zhp, void *data)
{
callback_data_t *cb = data;
int dontclose = 0;
int include_snaps = zfs_include_snapshots(zhp, cb);
boolean_t dontclose = B_FALSE;
boolean_t include_snaps = zfs_include_snapshots(zhp, cb);
boolean_t include_bmarks = (cb->cb_types & ZFS_TYPE_BOOKMARK);
if ((zfs_get_type(zhp) & cb->cb_types) ||
((zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) && include_snaps)) {
@ -109,14 +113,15 @@ zfs_callback(zfs_handle_t *zhp, void *data)
cb->cb_props_table);
if (zfs_expand_proplist(zhp, cb->cb_proplist,
(cb->cb_flags & ZFS_ITER_RECVD_PROPS))
(cb->cb_flags & ZFS_ITER_RECVD_PROPS),
(cb->cb_flags & ZFS_ITER_LITERAL_PROPS))
!= 0) {
free(node);
return (-1);
}
}
uu_avl_insert(cb->cb_avl, node, idx);
dontclose = 1;
dontclose = B_TRUE;
} else {
free(node);
}
@ -131,11 +136,14 @@ zfs_callback(zfs_handle_t *zhp, void *data)
cb->cb_depth++;
if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
(void) zfs_iter_filesystems(zhp, zfs_callback, data);
if ((zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) && include_snaps) {
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
(void) zfs_iter_snapshots(zhp,
(cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
data);
}
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks)
(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
cb->cb_depth--;
}

View File

@ -18,9 +18,11 @@
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef ZFS_ITER_H
@ -44,6 +46,7 @@ typedef struct zfs_sort_column {
#define ZFS_ITER_DEPTH_LIMIT (1 << 3)
#define ZFS_ITER_RECVD_PROPS (1 << 4)
#define ZFS_ITER_SIMPLE (1 << 5)
#define ZFS_ITER_LITERAL_PROPS (1 << 6)
int zfs_for_each(int, char **, int options, zfs_type_t,
zfs_sort_column_t *, zprop_list_t **, int, zfs_iter_f, void *);

View File

@ -21,14 +21,14 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <assert.h>
@ -107,6 +107,7 @@ static int zfs_do_release(int argc, char **argv);
static int zfs_do_diff(int argc, char **argv);
static int zfs_do_jail(int argc, char **argv);
static int zfs_do_unjail(int argc, char **argv);
static int zfs_do_bookmark(int argc, char **argv);
/*
* Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
@ -155,6 +156,7 @@ typedef enum {
HELP_HOLDS,
HELP_RELEASE,
HELP_DIFF,
HELP_BOOKMARK,
} zfs_help_t;
typedef struct zfs_command {
@ -181,6 +183,7 @@ static zfs_command_t command_table[] = {
{ "clone", zfs_do_clone, HELP_CLONE },
{ "promote", zfs_do_promote, HELP_PROMOTE },
{ "rename", zfs_do_rename, HELP_RENAME },
{ "bookmark", zfs_do_bookmark, HELP_BOOKMARK },
{ NULL },
{ "list", zfs_do_list, HELP_LIST },
{ NULL },
@ -231,11 +234,12 @@ get_usage(zfs_help_t idx)
case HELP_DESTROY:
return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n"
"\tdestroy [-dnpRrv] "
"<snapshot>[%<snapname>][,...]\n"));
"<filesystem|volume>@<snap>[%<snap>][,...]\n"
"\tdestroy <filesystem|volume>#<bookmark>\n"));
case HELP_GET:
return (gettext("\tget [-rHp] [-d max] "
"[-o \"all\" | field[,...]] [-t type[,...]] "
"[-s source[,...]]\n"
"[-o \"all\" | field[,...]]\n"
"\t [-t type[,...]] [-s source[,...]]\n"
"\t <\"all\" | property[,...]> "
"[filesystem|volume|snapshot] ...\n"));
case HELP_INHERIT:
@ -249,9 +253,8 @@ get_usage(zfs_help_t idx)
case HELP_UNJAIL:
return (gettext("\tunjail <jailid|jailname> <filesystem>\n"));
case HELP_LIST:
return (gettext("\tlist [-rH][-d max] "
"[-o property[,...]] [-t type[,...]] [-s property] ...\n"
"\t [-S property] ... "
return (gettext("\tlist [-Hp] [-r|-d max] [-o property[,...]] "
"[-s property]...\n\t [-S property]... [-t type[,...]] "
"[filesystem|volume|snapshot] ...\n"));
case HELP_MOUNT:
return (gettext("\tmount\n"
@ -259,31 +262,32 @@ get_usage(zfs_help_t idx)
case HELP_PROMOTE:
return (gettext("\tpromote <clone-filesystem>\n"));
case HELP_RECEIVE:
return (gettext("\treceive [-vnFu] <filesystem|volume|"
return (gettext("\treceive|recv [-vnFu] <filesystem|volume|"
"snapshot>\n"
"\treceive [-vnFu] [-d | -e] <filesystem>\n"));
"\treceive|recv [-vnFu] [-d | -e] <filesystem>\n"));
case HELP_RENAME:
return (gettext("\trename [-f] <filesystem|volume|snapshot> "
"<filesystem|volume|snapshot>\n"
"\trename [-f] -p <filesystem|volume> "
"<filesystem|volume>\n"
"\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
"\trename -r <snapshot> <snapshot>\n"
"\trename -u [-p] <filesystem> <filesystem>"));
case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND:
return (gettext("\tsend [-DnPpRv] "
"[-i snapshot | -I snapshot] <snapshot>\n"));
return (gettext("\tsend [-DnPpRv] [-[iI] snapshot] "
"<snapshot>\n"
"\tsend [-i snapshot|bookmark] "
"<filesystem|volume|snapshot>\n"));
case HELP_SET:
return (gettext("\tset <property=value> "
"<filesystem|volume|snapshot> ...\n"));
case HELP_SHARE:
return (gettext("\tshare <-a | filesystem>\n"));
case HELP_SNAPSHOT:
return (gettext("\tsnapshot [-r] [-o property=value] ... "
"<filesystem@snapname|volume@snapname> ...\n"));
return (gettext("\tsnapshot|snap [-r] [-o property=value] ... "
"<filesystem|volume>@<snap> ...\n"));
case HELP_UNMOUNT:
return (gettext("\tunmount [-f] "
return (gettext("\tunmount|umount [-f] "
"<-a | filesystem|mountpoint>\n"));
case HELP_UNSHARE:
return (gettext("\tunshare "
@ -310,12 +314,14 @@ get_usage(zfs_help_t idx)
"<filesystem|volume>\n"));
case HELP_USERSPACE:
return (gettext("\tuserspace [-Hinp] [-o field[,...]] "
"[-s field] ...\n\t[-S field] ... "
"[-t type[,...]] <filesystem|snapshot>\n"));
"[-s field] ...\n"
"\t [-S field] ... [-t type[,...]] "
"<filesystem|snapshot>\n"));
case HELP_GROUPSPACE:
return (gettext("\tgroupspace [-Hinp] [-o field[,...]] "
"[-s field] ...\n\t[-S field] ... "
"[-t type[,...]] <filesystem|snapshot>\n"));
"[-s field] ...\n"
"\t [-S field] ... [-t type[,...]] "
"<filesystem|snapshot>\n"));
case HELP_HOLD:
return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
case HELP_HOLDS:
@ -325,6 +331,8 @@ get_usage(zfs_help_t idx)
case HELP_DIFF:
return (gettext("\tdiff [-FHt] <snapshot> "
"[snapshot|filesystem]\n"));
case HELP_BOOKMARK:
return (gettext("\tbookmark <snapshot> <bookmark>\n"));
}
abort();
@ -487,9 +495,8 @@ usage(boolean_t requested)
}
static int
parseprop(nvlist_t *props)
parseprop(nvlist_t *props, char *propname)
{
char *propname = optarg;
char *propval, *strval;
if ((propval = strchr(propname, '=')) == NULL) {
@ -518,7 +525,7 @@ parse_depth(char *opt, int *flags)
depth = (int)strtol(opt, &tmp, 0);
if (*tmp) {
(void) fprintf(stderr,
gettext("%s is not an integer\n"), optarg);
gettext("%s is not an integer\n"), opt);
usage(B_FALSE);
}
if (depth < 0) {
@ -609,7 +616,7 @@ zfs_do_clone(int argc, char **argv)
while ((c = getopt(argc, argv, "o:p")) != -1) {
switch (c) {
case 'o':
if (parseprop(props))
if (parseprop(props, optarg))
return (1);
break;
case 'p':
@ -759,7 +766,7 @@ zfs_do_create(int argc, char **argv)
nomem();
break;
case 'o':
if (parseprop(props))
if (parseprop(props, optarg))
goto error;
break;
case 's':
@ -927,6 +934,7 @@ typedef struct destroy_cbdata {
char *cb_prevsnap;
int64_t cb_snapused;
char *cb_snapspec;
char *cb_bookmark;
} destroy_cbdata_t;
/*
@ -1196,7 +1204,7 @@ zfs_do_destroy(int argc, char **argv)
int err = 0;
int c;
zfs_handle_t *zhp = NULL;
char *at;
char *at, *pound;
zfs_type_t type = ZFS_TYPE_DATASET;
/* check options */
@ -1248,6 +1256,7 @@ zfs_do_destroy(int argc, char **argv)
}
at = strchr(argv[0], '@');
pound = strchr(argv[0], '#');
if (at != NULL) {
/* Build the list of snaps to destroy in cb_nvl. */
@ -1309,6 +1318,46 @@ zfs_do_destroy(int argc, char **argv)
if (err != 0)
rv = 1;
} else if (pound != NULL) {
int err;
nvlist_t *nvl;
if (cb.cb_dryrun) {
(void) fprintf(stderr,
"dryrun is not supported with bookmark\n");
return (-1);
}
if (cb.cb_defer_destroy) {
(void) fprintf(stderr,
"defer destroy is not supported with bookmark\n");
return (-1);
}
if (cb.cb_recurse) {
(void) fprintf(stderr,
"recursive is not supported with bookmark\n");
return (-1);
}
if (!zfs_bookmark_exists(argv[0])) {
(void) fprintf(stderr, gettext("bookmark '%s' "
"does not exist.\n"), argv[0]);
return (1);
}
nvl = fnvlist_alloc();
fnvlist_add_boolean(nvl, argv[0]);
err = lzc_destroy_bookmarks(nvl, NULL);
if (err != 0) {
(void) zfs_standard_error(g_zfs, err,
"cannot destroy bookmark");
}
nvlist_free(cb.cb_nvl);
return (err);
} else {
/* Open the given dataset */
if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
@ -1671,7 +1720,8 @@ zfs_do_get(int argc, char **argv)
flags &= ~ZFS_ITER_PROP_LISTSNAPS;
while (*optarg != '\0') {
static char *type_subopts[] = { "filesystem",
"volume", "snapshot", "all", NULL };
"volume", "snapshot", "bookmark",
"all", NULL };
switch (getsubopt(&optarg, type_subopts,
&value)) {
@ -1685,7 +1735,11 @@ zfs_do_get(int argc, char **argv)
types |= ZFS_TYPE_SNAPSHOT;
break;
case 3:
types = ZFS_TYPE_DATASET;
types |= ZFS_TYPE_BOOKMARK;
break;
case 4:
types = ZFS_TYPE_DATASET |
ZFS_TYPE_BOOKMARK;
break;
default:
@ -2011,7 +2065,7 @@ zfs_do_upgrade(int argc, char **argv)
boolean_t showversions = B_FALSE;
int ret = 0;
upgrade_cbdata_t cb = { 0 };
char c;
int c;
int flags = ZFS_ITER_ARGS_CAN_BE_PATHS;
/* check options */
@ -2124,7 +2178,7 @@ zfs_do_upgrade(int argc, char **argv)
* -i Translate SID to POSIX ID.
* -n Print numeric ID instead of user/group name.
* -o Control which fields to display.
* -p Use exact (parseable) numeric output.
* -p Use exact (parsable) numeric output.
* -s Specify sort columns, descending order.
* -S Specify sort columns, ascending order.
* -t Control which object types to display.
@ -2158,7 +2212,7 @@ static int us_type_bits[] = {
USTYPE_SMB_USR,
USTYPE_ALL
};
static char *us_type_names[] = { "posixgroup", "posxiuser", "smbgroup",
static char *us_type_names[] = { "posixgroup", "posixuser", "smbgroup",
"smbuser", "all" };
typedef struct us_node {
@ -2811,24 +2865,25 @@ zfs_do_userspace(int argc, char **argv)
}
/*
* list [-r][-d max] [-H] [-o property[,property]...] [-t type[,type]...]
* [-s property [-s property]...] [-S property [-S property]...]
* <dataset> ...
* list [-Hp][-r|-d max] [-o property[,...]] [-s property] ... [-S property] ...
* [-t type[,...]] [filesystem|volume|snapshot] ...
*
* -r Recurse over all children
* -H Scripted mode; elide headers and separate columns by tabs.
* -p Display values in parsable (literal) format.
* -r Recurse over all children.
* -d Limit recursion by depth.
* -H Scripted mode; elide headers and separate columns by tabs
* -o Control which fields to display.
* -t Control which object types to display.
* -s Specify sort columns, descending order.
* -S Specify sort columns, ascending order.
* -t Control which object types to display.
*
* When given no arguments, lists all filesystems in the system.
* When given no arguments, list all filesystems in the system.
* Otherwise, list the specified datasets, optionally recursing down them if
* '-r' is specified.
*/
typedef struct list_cbdata {
boolean_t cb_first;
boolean_t cb_literal;
boolean_t cb_scripted;
zprop_list_t *cb_proplist;
} list_cbdata_t;
@ -2837,8 +2892,9 @@ typedef struct list_cbdata {
* Given a list of columns to display, output appropriate headers for each one.
*/
static void
print_header(zprop_list_t *pl)
print_header(list_cbdata_t *cb)
{
zprop_list_t *pl = cb->cb_proplist;
char headerbuf[ZFS_MAXPROPLEN];
const char *header;
int i;
@ -2879,19 +2935,19 @@ print_header(zprop_list_t *pl)
* to the described layout.
*/
static void
print_dataset(zfs_handle_t *zhp, zprop_list_t *pl, boolean_t scripted)
print_dataset(zfs_handle_t *zhp, list_cbdata_t *cb)
{
zprop_list_t *pl = cb->cb_proplist;
boolean_t first = B_TRUE;
char property[ZFS_MAXPROPLEN];
nvlist_t *userprops = zfs_get_user_props(zhp);
nvlist_t *propval;
char *propstr;
boolean_t right_justify;
int width;
for (; pl != NULL; pl = pl->pl_next) {
if (!first) {
if (scripted)
if (cb->cb_scripted)
(void) printf("\t");
else
(void) printf(" ");
@ -2906,22 +2962,22 @@ print_dataset(zfs_handle_t *zhp, zprop_list_t *pl, boolean_t scripted)
right_justify = zfs_prop_align_right(pl->pl_prop);
} else if (pl->pl_prop != ZPROP_INVAL) {
if (zfs_prop_get(zhp, pl->pl_prop, property,
sizeof (property), NULL, NULL, 0, B_FALSE) != 0)
sizeof (property), NULL, NULL, 0,
cb->cb_literal) != 0)
propstr = "-";
else
propstr = property;
right_justify = zfs_prop_align_right(pl->pl_prop);
} else if (zfs_prop_userquota(pl->pl_user_prop)) {
if (zfs_prop_get_userquota(zhp, pl->pl_user_prop,
property, sizeof (property), B_FALSE) != 0)
property, sizeof (property), cb->cb_literal) != 0)
propstr = "-";
else
propstr = property;
right_justify = B_TRUE;
} else if (zfs_prop_written(pl->pl_user_prop)) {
if (zfs_prop_get_written(zhp, pl->pl_user_prop,
property, sizeof (property), B_FALSE) != 0)
property, sizeof (property), cb->cb_literal) != 0)
propstr = "-";
else
propstr = property;
@ -2936,19 +2992,17 @@ print_dataset(zfs_handle_t *zhp, zprop_list_t *pl, boolean_t scripted)
right_justify = B_FALSE;
}
width = pl->pl_width;
/*
* If this is being called in scripted mode, or if this is the
* last column and it is left-justified, don't include a width
* format specifier.
*/
if (scripted || (pl->pl_next == NULL && !right_justify))
if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
(void) printf("%s", propstr);
else if (right_justify)
(void) printf("%*s", width, propstr);
(void) printf("%*s", pl->pl_width, propstr);
else
(void) printf("%-*s", width, propstr);
(void) printf("%-*s", pl->pl_width, propstr);
}
(void) printf("\n");
@ -2964,11 +3018,11 @@ list_callback(zfs_handle_t *zhp, void *data)
if (cbp->cb_first) {
if (!cbp->cb_scripted)
print_header(cbp->cb_proplist);
print_header(cbp);
cbp->cb_first = B_FALSE;
}
print_dataset(zhp, cbp->cb_proplist, cbp->cb_scripted);
print_dataset(zhp, cbp);
return (0);
}
@ -2977,7 +3031,6 @@ static int
zfs_do_list(int argc, char **argv)
{
int c;
boolean_t scripted = B_FALSE;
static char default_fields[] =
"name,used,available,referenced,mountpoint";
int types = ZFS_TYPE_DATASET;
@ -2991,11 +3044,15 @@ zfs_do_list(int argc, char **argv)
int flags = ZFS_ITER_PROP_LISTSNAPS | ZFS_ITER_ARGS_CAN_BE_PATHS;
/* check options */
while ((c = getopt(argc, argv, ":d:o:rt:Hs:S:")) != -1) {
while ((c = getopt(argc, argv, "HS:d:o:prs:t:")) != -1) {
switch (c) {
case 'o':
fields = optarg;
break;
case 'p':
cb.cb_literal = B_TRUE;
flags |= ZFS_ITER_LITERAL_PROPS;
break;
case 'd':
limit = parse_depth(optarg, &flags);
break;
@ -3003,7 +3060,7 @@ zfs_do_list(int argc, char **argv)
flags |= ZFS_ITER_RECURSE;
break;
case 'H':
scripted = B_TRUE;
cb.cb_scripted = B_TRUE;
break;
case 's':
if (zfs_add_sort_column(&sortcol, optarg,
@ -3027,7 +3084,8 @@ zfs_do_list(int argc, char **argv)
flags &= ~ZFS_ITER_PROP_LISTSNAPS;
while (*optarg != '\0') {
static char *type_subopts[] = { "filesystem",
"volume", "snapshot", "all", NULL };
"volume", "snapshot", "snap", "bookmark",
"all", NULL };
switch (getsubopt(&optarg, type_subopts,
&value)) {
@ -3038,12 +3096,16 @@ zfs_do_list(int argc, char **argv)
types |= ZFS_TYPE_VOLUME;
break;
case 2:
case 3:
types |= ZFS_TYPE_SNAPSHOT;
break;
case 3:
types = ZFS_TYPE_DATASET;
case 4:
types |= ZFS_TYPE_BOOKMARK;
break;
case 5:
types = ZFS_TYPE_DATASET |
ZFS_TYPE_BOOKMARK;
break;
default:
(void) fprintf(stderr,
gettext("invalid type '%s'\n"),
@ -3092,7 +3154,6 @@ zfs_do_list(int argc, char **argv)
!= 0)
usage(B_FALSE);
cb.cb_scripted = scripted;
cb.cb_first = B_TRUE;
ret = zfs_for_each(argc, argv, flags, types, sortcol, &cb.cb_proplist,
@ -3284,9 +3345,29 @@ typedef struct rollback_cbdata {
char *cb_target;
int cb_error;
boolean_t cb_recurse;
boolean_t cb_dependent;
} rollback_cbdata_t;
static int
rollback_check_dependent(zfs_handle_t *zhp, void *data)
{
rollback_cbdata_t *cbp = data;
if (cbp->cb_first && cbp->cb_recurse) {
(void) fprintf(stderr, gettext("cannot rollback to "
"'%s': clones of previous snapshots exist\n"),
cbp->cb_target);
(void) fprintf(stderr, gettext("use '-R' to "
"force deletion of the following clones and "
"dependents:\n"));
cbp->cb_first = 0;
cbp->cb_error = 1;
}
(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
zfs_close(zhp);
return (0);
}
/*
* Report any snapshots more recent than the one specified. Used when '-r' is
* not specified. We reuse this same callback for the snapshot dependents - if
@ -3303,52 +3384,30 @@ rollback_check(zfs_handle_t *zhp, void *data)
return (0);
}
if (!cbp->cb_dependent) {
if (strcmp(zfs_get_name(zhp), cbp->cb_target) != 0 &&
zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
cbp->cb_create) {
if (cbp->cb_first && !cbp->cb_recurse) {
(void) fprintf(stderr, gettext("cannot "
"rollback to '%s': more recent snapshots "
"exist\n"),
cbp->cb_target);
(void) fprintf(stderr, gettext("use '-r' to "
"force deletion of the following "
"snapshots:\n"));
cbp->cb_first = 0;
cbp->cb_error = 1;
}
if (cbp->cb_recurse) {
cbp->cb_dependent = B_TRUE;
if (zfs_iter_dependents(zhp, B_TRUE,
rollback_check, cbp) != 0) {
zfs_close(zhp);
return (-1);
}
cbp->cb_dependent = B_FALSE;
} else {
(void) fprintf(stderr, "%s\n",
zfs_get_name(zhp));
}
}
} else {
if (cbp->cb_first && cbp->cb_recurse) {
(void) fprintf(stderr, gettext("cannot rollback to "
"'%s': clones of previous snapshots exist\n"),
if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
if (cbp->cb_first && !cbp->cb_recurse) {
(void) fprintf(stderr, gettext("cannot "
"rollback to '%s': more recent snapshots "
"or bookmarks exist\n"),
cbp->cb_target);
(void) fprintf(stderr, gettext("use '-R' to "
"force deletion of the following clones and "
"dependents:\n"));
(void) fprintf(stderr, gettext("use '-r' to "
"force deletion of the following "
"snapshots and bookmarks:\n"));
cbp->cb_first = 0;
cbp->cb_error = 1;
}
(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
if (cbp->cb_recurse) {
if (zfs_iter_dependents(zhp, B_TRUE,
rollback_check_dependent, cbp) != 0) {
zfs_close(zhp);
return (-1);
}
} else {
(void) fprintf(stderr, "%s\n",
zfs_get_name(zhp));
}
}
zfs_close(zhp);
return (0);
}
@ -3418,7 +3477,9 @@ zfs_do_rollback(int argc, char **argv)
cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
cb.cb_first = B_TRUE;
cb.cb_error = 0;
if ((ret = zfs_iter_children(zhp, rollback_check, &cb)) != 0)
if ((ret = zfs_iter_snapshots(zhp, B_FALSE, rollback_check, &cb)) != 0)
goto out;
if ((ret = zfs_iter_bookmarks(zhp, rollback_check, &cb)) != 0)
goto out;
if ((ret = cb.cb_error) != 0)
@ -3560,7 +3621,7 @@ static int
zfs_do_snapshot(int argc, char **argv)
{
int ret = 0;
char c;
int c;
nvlist_t *props;
snap_cbdata_t sd = { 0 };
boolean_t multiple_snaps = B_FALSE;
@ -3574,7 +3635,7 @@ zfs_do_snapshot(int argc, char **argv)
while ((c = getopt(argc, argv, "ro:")) != -1) {
switch (c) {
case 'o':
if (parseprop(props))
if (parseprop(props, optarg))
return (1);
break;
case 'r':
@ -3713,12 +3774,45 @@ zfs_do_send(int argc, char **argv)
return (1);
}
cp = strchr(argv[0], '@');
if (cp == NULL) {
(void) fprintf(stderr,
gettext("argument must be a snapshot\n"));
usage(B_FALSE);
/*
* Special case sending a filesystem, or from a bookmark.
*/
if (strchr(argv[0], '@') == NULL ||
(fromname && strchr(fromname, '#') != NULL)) {
char frombuf[ZFS_MAXNAMELEN];
if (flags.replicate || flags.doall || flags.props ||
flags.dedup || flags.dryrun || flags.verbose ||
flags.progress) {
(void) fprintf(stderr,
gettext("Error: "
"Unsupported flag with filesystem or bookmark.\n"));
return (1);
}
zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET);
if (zhp == NULL)
return (1);
if (fromname != NULL &&
(fromname[0] == '#' || fromname[0] == '@')) {
/*
* Incremental source name begins with # or @.
* Default to same fs as target.
*/
(void) strncpy(frombuf, argv[0], sizeof (frombuf));
cp = strchr(frombuf, '@');
if (cp != NULL)
*cp = '\0';
(void) strlcat(frombuf, fromname, sizeof (frombuf));
fromname = frombuf;
}
err = zfs_send_one(zhp, fromname, STDOUT_FILENO);
zfs_close(zhp);
return (err != 0);
}
cp = strchr(argv[0], '@');
*cp = '\0';
toname = cp + 1;
zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
@ -3874,6 +3968,7 @@ zfs_do_receive(int argc, char **argv)
#define ZFS_DELEG_PERM_HOLD "hold"
#define ZFS_DELEG_PERM_RELEASE "release"
#define ZFS_DELEG_PERM_DIFF "diff"
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
#define ZFS_NUM_DELEG_NOTES ZFS_DELEG_NOTE_NONE
@ -3893,6 +3988,7 @@ static zfs_deleg_perm_tab_t zfs_deleg_perm_tbl[] = {
{ ZFS_DELEG_PERM_SEND, ZFS_DELEG_NOTE_SEND },
{ ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE },
{ ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
{ ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
{ ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA },
{ ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED },
@ -6664,6 +6760,108 @@ zfs_do_diff(int argc, char **argv)
return (err != 0);
}
/*
* zfs bookmark <fs@snap> <fs#bmark>
*
* Creates a bookmark with the given name from the given snapshot.
*/
static int
zfs_do_bookmark(int argc, char **argv)
{
char snapname[ZFS_MAXNAMELEN];
zfs_handle_t *zhp;
nvlist_t *nvl;
int ret = 0;
int c;
/* check options */
while ((c = getopt(argc, argv, "")) != -1) {
switch (c) {
case '?':
(void) fprintf(stderr,
gettext("invalid option '%c'\n"), optopt);
goto usage;
}
}
argc -= optind;
argv += optind;
/* check number of arguments */
if (argc < 1) {
(void) fprintf(stderr, gettext("missing snapshot argument\n"));
goto usage;
}
if (argc < 2) {
(void) fprintf(stderr, gettext("missing bookmark argument\n"));
goto usage;
}
if (strchr(argv[1], '#') == NULL) {
(void) fprintf(stderr,
gettext("invalid bookmark name '%s' -- "
"must contain a '#'\n"), argv[1]);
goto usage;
}
if (argv[0][0] == '@') {
/*
* Snapshot name begins with @.
* Default to same fs as bookmark.
*/
(void) strncpy(snapname, argv[1], sizeof (snapname));
*strchr(snapname, '#') = '\0';
(void) strlcat(snapname, argv[0], sizeof (snapname));
} else {
(void) strncpy(snapname, argv[0], sizeof (snapname));
}
zhp = zfs_open(g_zfs, snapname, ZFS_TYPE_SNAPSHOT);
if (zhp == NULL)
goto usage;
zfs_close(zhp);
nvl = fnvlist_alloc();
fnvlist_add_string(nvl, argv[1], snapname);
ret = lzc_bookmark(nvl, NULL);
fnvlist_free(nvl);
if (ret != 0) {
const char *err_msg;
char errbuf[1024];
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN,
"cannot create bookmark '%s'"), argv[1]);
switch (ret) {
case EXDEV:
err_msg = "bookmark is in a different pool";
break;
case EEXIST:
err_msg = "bookmark exists";
break;
case EINVAL:
err_msg = "invalid argument";
break;
case ENOTSUP:
err_msg = "bookmark feature not enabled";
break;
default:
err_msg = "unknown error";
break;
}
(void) fprintf(stderr, "%s: %s\n", errbuf,
dgettext(TEXT_DOMAIN, err_msg));
}
return (ret);
usage:
usage(B_FALSE);
return (-1);
}
int
main(int argc, char **argv)
{
@ -6725,6 +6923,12 @@ main(int argc, char **argv)
if (strcmp(cmdname, "recv") == 0)
cmdname = "receive";
/*
* The 'snap' command is an alias for 'snapshot'
*/
if (strcmp(cmdname, "snap") == 0)
cmdname = "snapshot";
/*
* Special case '-?'
*/

View File

@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
@ -85,10 +85,15 @@ usage(void)
static void
fatal(const char *fmt, ...)
fatal(spa_t *spa, void *tag, const char *fmt, ...)
{
va_list ap;
if (spa != NULL) {
spa_close(spa, tag);
(void) spa_export(g_pool, NULL, B_TRUE, B_FALSE);
}
va_start(ap, fmt);
(void) fprintf(stderr, "%s: ", cmdname);
(void) vfprintf(stderr, fmt, ap);
@ -159,13 +164,14 @@ import_pool(const char *target, boolean_t readonly)
g_importargs.can_be_active = B_TRUE;
if (zpool_search_import(g_zfs, &g_importargs) != NULL ||
spa_open(target, &spa, FTAG) == 0) {
fatal("cannot import '%s': pool is active; run "
"\"zpool export %s\" first\n",
g_pool, g_pool);
fatal(spa, FTAG, "cannot import '%s': pool is "
"active; run " "\"zpool export %s\" "
"first\n", g_pool, g_pool);
}
}
fatal("cannot import '%s': no such pool available\n", g_pool);
fatal(NULL, FTAG, "cannot import '%s': no such pool "
"available\n", g_pool);
}
elem = nvlist_next_nvpair(pools, NULL);
@ -186,7 +192,8 @@ import_pool(const char *target, boolean_t readonly)
error = 0;
if (error)
fatal("can't import '%s': %s", name, strerror(error));
fatal(NULL, FTAG, "can't import '%s': %s", name,
strerror(error));
}
static void
@ -201,10 +208,11 @@ zhack_spa_open(const char *target, boolean_t readonly, void *tag, spa_t **spa)
zfeature_checks_disable = B_FALSE;
if (err != 0)
fatal("cannot open '%s': %s", target, strerror(err));
fatal(*spa, FTAG, "cannot open '%s': %s", target,
strerror(err));
if (spa_version(*spa) < SPA_VERSION_FEATURES) {
fatal("'%s' has version %d, features not enabled", target,
(int)spa_version(*spa));
fatal(*spa, FTAG, "'%s' has version %d, features not enabled",
target, (int)spa_version(*spa));
}
}
@ -269,18 +277,22 @@ zhack_do_feature_stat(int argc, char **argv)
dump_obj(os, spa->spa_feat_for_read_obj, "for_read");
dump_obj(os, spa->spa_feat_for_write_obj, "for_write");
dump_obj(os, spa->spa_feat_desc_obj, "descriptions");
if (spa_feature_is_active(spa, SPA_FEATURE_ENABLED_TXG)) {
dump_obj(os, spa->spa_feat_enabled_txg_obj, "enabled_txg");
}
dump_mos(spa);
spa_close(spa, FTAG);
}
static void
feature_enable_sync(void *arg, dmu_tx_t *tx)
zhack_feature_enable_sync(void *arg, dmu_tx_t *tx)
{
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
zfeature_info_t *feature = arg;
spa_feature_enable(spa, feature, tx);
feature_enable_sync(spa, feature, tx);
spa_history_log_internal(spa, "zhack enable feature", tx,
"name=%s can_readonly=%u",
feature->fi_guid, feature->fi_can_readonly);
@ -294,7 +306,7 @@ zhack_do_feature_enable(int argc, char **argv)
spa_t *spa;
objset_t *mos;
zfeature_info_t feature;
zfeature_info_t *nodeps[] = { NULL };
spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
/*
* Features are not added to the pool's label until their refcounts
@ -304,7 +316,9 @@ zhack_do_feature_enable(int argc, char **argv)
feature.fi_uname = "zhack";
feature.fi_mos = B_FALSE;
feature.fi_can_readonly = B_FALSE;
feature.fi_activate_on_enable = B_FALSE;
feature.fi_depends = nodeps;
feature.fi_feature = SPA_FEATURE_NONE;
optind = 1;
while ((c = getopt(argc, argv, "rmd:")) != -1) {
@ -336,18 +350,19 @@ zhack_do_feature_enable(int argc, char **argv)
feature.fi_guid = argv[1];
if (!zfeature_is_valid_guid(feature.fi_guid))
fatal("invalid feature guid: %s", feature.fi_guid);
fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
zhack_spa_open(target, B_FALSE, FTAG, &spa);
mos = spa->spa_meta_objset;
if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
fatal("'%s' is a real feature, will not enable");
if (zfeature_is_supported(feature.fi_guid))
fatal(spa, FTAG, "'%s' is a real feature, will not enable");
if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid))
fatal("feature already enabled: %s", feature.fi_guid);
fatal(spa, FTAG, "feature already enabled: %s",
feature.fi_guid);
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
feature_enable_sync, &feature, 5));
zhack_feature_enable_sync, &feature, 5));
spa_close(spa, FTAG);
@ -359,8 +374,10 @@ feature_incr_sync(void *arg, dmu_tx_t *tx)
{
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
zfeature_info_t *feature = arg;
uint64_t refcount;
spa_feature_incr(spa, feature, tx);
VERIFY0(feature_get_refcount_from_disk(spa, feature, &refcount));
feature_sync(spa, feature, refcount + 1, tx);
spa_history_log_internal(spa, "zhack feature incr", tx,
"name=%s", feature->fi_guid);
}
@ -370,8 +387,10 @@ feature_decr_sync(void *arg, dmu_tx_t *tx)
{
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
zfeature_info_t *feature = arg;
uint64_t refcount;
spa_feature_decr(spa, feature, tx);
VERIFY0(feature_get_refcount_from_disk(spa, feature, &refcount));
feature_sync(spa, feature, refcount - 1, tx);
spa_history_log_internal(spa, "zhack feature decr", tx,
"name=%s", feature->fi_guid);
}
@ -385,7 +404,7 @@ zhack_do_feature_ref(int argc, char **argv)
spa_t *spa;
objset_t *mos;
zfeature_info_t feature;
zfeature_info_t *nodeps[] = { NULL };
spa_feature_t nodeps[] = { SPA_FEATURE_NONE };
/*
* fi_desc does not matter here because it was written to disk
@ -397,6 +416,7 @@ zhack_do_feature_ref(int argc, char **argv)
feature.fi_mos = B_FALSE;
feature.fi_desc = NULL;
feature.fi_depends = nodeps;
feature.fi_feature = SPA_FEATURE_NONE;
optind = 1;
while ((c = getopt(argc, argv, "md")) != -1) {
@ -423,13 +443,15 @@ zhack_do_feature_ref(int argc, char **argv)
feature.fi_guid = argv[1];
if (!zfeature_is_valid_guid(feature.fi_guid))
fatal("invalid feature guid: %s", feature.fi_guid);
fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
zhack_spa_open(target, B_FALSE, FTAG, &spa);
mos = spa->spa_meta_objset;
if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
fatal("'%s' is a real feature, will not change refcount");
if (zfeature_is_supported(feature.fi_guid)) {
fatal(spa, FTAG,
"'%s' is a real feature, will not change refcount");
}
if (0 == zap_contains(mos, spa->spa_feat_for_read_obj,
feature.fi_guid)) {
@ -438,11 +460,17 @@ zhack_do_feature_ref(int argc, char **argv)
feature.fi_guid)) {
feature.fi_can_readonly = B_TRUE;
} else {
fatal("feature is not enabled: %s", feature.fi_guid);
fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid);
}
if (decr && !spa_feature_is_active(spa, &feature))
fatal("feature refcount already 0: %s", feature.fi_guid);
if (decr) {
uint64_t count;
if (feature_get_refcount_from_disk(spa, &feature,
&count) == 0 && count != 0) {
fatal(spa, FTAG, "feature refcount already 0: %s",
feature.fi_guid);
}
}
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
decr ? feature_decr_sync : feature_incr_sync, &feature, 5));
@ -530,8 +558,8 @@ main(int argc, char **argv)
usage();
}
if (!g_readonly && spa_export(g_pool, NULL, B_TRUE, B_TRUE) != 0) {
fatal("pool export failed; "
if (!g_readonly && spa_export(g_pool, NULL, B_TRUE, B_FALSE) != 0) {
fatal(NULL, FTAG, "pool export failed; "
"changes may not be committed to disk\n");
}

View File

@ -148,6 +148,7 @@
#include <sys/mount.h>
#include <libzfs.h>
#include <libzfs_compat.h>
#undef verify /* both libzfs.h and zfs_context.h want to define this */

View File

@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd September 20, 2013
.Dd April 23, 2014
.Dt ZPOOL-FEATURES 7
.Os
.Sh NAME
@ -187,6 +187,23 @@ This feature is
.Sy active
while there are any filesystems, volumes, or snapshots which were created
after enabling this feature.
.It Sy filesystem_limits
.Bl -column "READ\-ONLY COMPATIBLE" "com.joyent:filesystem_limits"
.It GUID Ta com.joyent:filesystem_limits
.It READ\-ONLY COMPATIBLE Ta yes
.It DEPENDENCIES Ta extensible_dataset
.El
.Pp
This feature enables filesystem and snapshot limits.
These limits can be used
to control how many filesystems and/or snapshots can be created at the point in
the tree on which the limits are set.
.Pp
This feature is
.Sy active
once either of the limit properties has been
set on a dataset.
Once activated the feature is never deactivated.
.It Sy lz4_compress
.Bl -column "READ\-ONLY COMPATIBLE" "org.illumos:lz4_compress"
.It GUID Ta org.illumos:lz4_compress
@ -222,12 +239,16 @@ command. Please note that doing so will
immediately activate the
.Sy lz4_compress
feature on the underlying
pool (even before any data is written). Since this feature is not
read-only compatible, this operation will render the pool unimportable
on systems without support for the
pool
.Pq even before any data is written ,
and the feature will not be
deactivated.
Since this feature is not read-only compatible, this
operation will render the pool unimportable on systems without support
for the
.Sy lz4_compress
feature. At the
moment, this operation cannot be reversed. Booting off of
feature.
Booting off of
.Sy lz4
-compressed root pools is supported.
.It Sy multi_vdev_crash_dump
@ -251,6 +272,130 @@ configuration.
.\" .Xr dumpon 8
.\" command to configure a
.\" dump device on a pool comprised of multiple vdevs.
.It Sy spacemap_histogram
.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:spacemap_histogram"
.It GUID Ta com.delphix:spacemap_histogram
.It READ\-ONLY COMPATIBLE Ta yes
.It DEPENDENCIES Ta none
.El
.Pp
This features allows ZFS to maintain more information about how free space
is organized within the pool. If this feature is
.Sy enabled ,
ZFS will
set this feature to
.Sy active
when a new space map object is created or
an existing space map is upgraded to the new format.
Once the feature is
.Sy active ,
it will remain in that state until the pool is destroyed.
.It Sy extensible_dataset
.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:extensible_dataset"
.It GUID Ta com.delphix:extensible_dataset
.It READ\-ONLY COMPATIBLE Ta no
.It DEPENDENCIES Ta none
.El
.Pp
This feature allows more flexible use of internal ZFS data structures,
and exists for other features to depend on.
.Pp
This feature will be
.Sy active
when the first dependent feature uses it,
and will be returned to the
.Sy enabled
state when all datasets that use
this feature are destroyed.
.It Sy bookmarks
.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:bookmarks"
.It GUID Ta com.delphix:bookmarks
.It READ\-ONLY COMPATIBLE Ta yes
.It DEPENDENCIES Ta extensible_dataset
.El
.Pp
This feature enables use of the
.Nm zfs
.Cm bookmark
subcommand.
.Pp
This feature is
.Sy active
while any bookmarks exist in the pool.
All bookmarks in the pool can be listed by running
.Nm zfs
.Cm list
.Fl t No bookmark Fl r Ar poolname .
.It Sy enabled_txg
.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:enabled_txg"
.It GUID Ta com.delphix:enabled_txg
.It READ\-ONLY COMPATIBLE Ta yes
.It DEPENDENCIES Ta none
.El
.Pp
Once this feature is enabled ZFS records the transaction group number
in which new features are enabled. This has no user-visible impact,
but other features may depend on this feature.
.Pp
This feature becomes
.Sy active
as soon as it is enabled and will
never return to being
.Sy enabled .
.It Sy hole_birth
.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:hole_birth"
.It GUID Ta com.delphix:hole_birth
.It READ\-ONLY COMPATIBLE Ta no
.It DEPENDENCIES Ta enabled_txg
.El
.Pp
This feature improves performance of incremental sends
.Pq Dq zfs send -i
and receives for objects with many holes.
The most common case of
hole-filled objects is zvols.
.Pp
An incremental send stream from snapshot
.Sy A
to snapshot
.Sy B
contains information about every block that changed between
.Sy A
and
.Sy B .
Blocks which did not change between those snapshots can be
identified and omitted from the stream using a piece of metadata called
the 'block birth time', but birth times are not recorded for holes
.Pq blocks filled only with zeroes .
Since holes created after
.Sy A
cannot be
distinguished from holes created before
.Sy A ,
information about every
hole in the entire filesystem or zvol is included in the send stream.
.Pp
For workloads where holes are rare this is not a problem.
However, when
incrementally replicating filesystems or zvols with many holes
.Pq for example a zvol formatted with another filesystem
a lot of time will
be spent sending and receiving unnecessary information about holes that
already exist on the receiving side.
.Pp
Once the
.Sy hole_birth
feature has been enabled the block birth times
of all new holes will be recorded.
Incremental sends between snapshots
created after this feature is enabled will use this new metadata to avoid
sending information about holes that already exist on the receiving side.
.Pp
This feature becomes
.Sy active
as soon as it is enabled and will
never return to being
.Sy enabled .
.El
.Sh SEE ALSO
.Xr zpool 8

View File

@ -1,5 +1,6 @@
'\" te
.\" Copyright (c) 2012, Martin Matuska <mm@FreeBSD.org>.
.\" Copyright (c) 2013-2014, Xin Li <delphij@FreeBSD.org>.
.\" All Rights Reserved.
.\"
.\" The contents of this file are subject to the terms of the
@ -25,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 14, 2013
.Dd March 28, 2014
.Dt ZPOOL 8
.Os
.Sh NAME
@ -70,6 +71,8 @@
.Ar pool ...
.Nm
.Cm get
.Op Fl Hp
.Op Fl o Ar field Ns Op , Ns Ar ...
.Ar all | property Ns Op , Ns Ar ...
.Ar pool ...
.Nm
@ -120,7 +123,7 @@
.Ar device
.Nm
.Cm list
.Op Fl H
.Op Fl Hpv
.Op Fl o Ar property Ns Op , Ns Ar ...
.Op Fl T Cm d Ns | Ns Cm u
.Op Ar pool
@ -141,6 +144,9 @@
.Cm remove
.Ar pool device ...
.Nm
.Cm reopen
.Ar pool
.Nm
.Cm replace
.Op Fl f
.Ar pool device
@ -621,6 +627,9 @@ Datasets of this pool can only be mounted read-only
.It
To write to a read-only pool, a export and import of the pool is required.
.El
.Pp
This property can also be referred to by its shortened column name,
.Sy rdonly .
.El
.Pp
The following properties can be set at creation time and import time, and later
@ -679,7 +688,9 @@ property.
Threshold for the number of block ditto copies. If the reference count for a
deduplicated block increases above this number, a new ditto copy of this block
is automatically stored. Default setting is
.Cm 0 .
.Cm 0
which causes no ditto copies to be created for deduplicated blocks.
The miniumum legal nonzero setting is 100.
.It Sy delegation Ns = Ns Cm on No | Cm off
Controls whether a non-privileged user is granted access based on the dataset
permissions defined on the dataset. See
@ -1010,6 +1021,8 @@ is currently being used. This may lead to potential data corruption.
.It Xo
.Nm
.Cm get
.Op Fl Hp
.Op Fl o Ar field Ns Op , Ns Ar ...
.Ar all | property Ns Op , Ns Ar ...
.Ar pool ...
.Xc
@ -1028,6 +1041,19 @@ the following fields:
See the
.Qq Sx Properties
section for more information on the available pool properties.
.Pp
.It Fl H
Scripted mode. Do not display headers, and separate fields by a single tab
instead of arbitrary space.
.It Fl p
Display numbers in parsable (exact) values.
.It Fl o Ar field
A comma-separated list of columns to display.
.Sy name Ns , Ns
.Sy property Ns , Ns
.Sy value Ns , Ns
.Sy source
is the default value.
.It Xo
.Nm
.Cm history
@ -1149,9 +1175,10 @@ option is also required.
.It Fl f
Forces import, even if the pool appears to be potentially active.
.It Fl m
Enables import with missing log devices.
Allows a pool to import when there is a missing log device. Recent transactions
can be lost because the log device will be discarded.
.It Fl N
Do not mount any filesystems from the imported pool.
Import the pool without mounting any file systems.
.It Fl R Ar root
Sets the
.Qq Sy cachefile
@ -1242,9 +1269,10 @@ option is also required.
.It Fl f
Forces import, even if the pool appears to be potentially active.
.It Fl m
Enables import with missing log devices.
Allows a pool to import when there is a missing log device. Recent transactions
can be lost because the log device will be discarded.
.It Fl N
Do not mount any filesystems from the imported pool.
Import the pool without mounting any file systems.
.It Fl R Ar root
Equivalent to
.Qq Fl o Cm cachefile=none,altroot= Ns Pa root
@ -1319,13 +1347,13 @@ The
.Ar device
must not be part of an active pool configuration.
.Bl -tag -width indent
.It Fl v
.It Fl f
Treat exported or foreign devices as inactive.
.El
.It Xo
.Nm
.Cm list
.Op Fl Hv
.Op Fl Hpv
.Op Fl o Ar property Ns Op , Ns Ar ...
.Op Fl T Cm d Ns | Ns Cm u
.Op Ar pool
@ -1333,8 +1361,9 @@ Treat exported or foreign devices as inactive.
.Op Ar inverval Op Ar count
.Xc
.Pp
Lists the given pools along with a health status and space usage. When given no
arguments, all pools in the system are listed.
Lists the given pools along with a health status and space usage. If no
.Ar pools
are specified, all pools in the system are listed.
.Pp
When given an interval, the output is printed every
.Ar interval
@ -1346,9 +1375,22 @@ is specified, the command exits after
.Ar count
reports are printed.
.Bl -tag -width indent
.It Fl T Cm d Ns | Ns Cm u
Print a timestamp.
.Pp
Use modifier
.Cm d
for standard date format. See
.Xr date 1 .
Use modifier
.Cm u
for unixtime
.Pq equals Qq Ic date +%s .
.It Fl H
Scripted mode. Do not display headers, and separate fields by a single tab
instead of arbitrary space.
.It Fl p
Display numbers in parsable (exact) values.
.It Fl v
Show more detailed information.
.It Fl o Ar property Ns Op , Ns Ar ...
@ -1431,6 +1473,13 @@ command. Non-redundant and
devices cannot be removed from a pool.
.It Xo
.Nm
.Cm reopen
.Ar pool
.Xc
.Pp
Reopen all the vdevs associated with the pool.
.It Xo
.Nm
.Cm replace
.Op Fl f
.Ar pool device
@ -1667,7 +1716,7 @@ Once this is done, the pool will no longer be accessible on systems that do
not support feature flags.
See
.Xr zpool-features 7
for details on compatability with system sthat support feature flags, but do
for details on compatibility with systems that support feature flags, but do
not support all features enabled on the pool.
.Bl -tag -width indent
.It Fl a
@ -1946,3 +1995,9 @@ The
.Xr mdoc 7
implementation of this manual page was initially written by
.An Martin Matuska Aq mm@FreeBSD.org .
.Sh CAVEATS
The
.Cm spare
feature requires a utility to detect zpool degradation and initiate
disk replacement within the zpool.
FreeBSD does not provide such a utility at this time.

View File

@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012 by Frederik Wessels. All rights reserved.
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
@ -236,7 +236,7 @@ get_usage(zpool_help_t idx) {
case HELP_LABELCLEAR:
return (gettext("\tlabelclear [-f] <vdev>\n"));
case HELP_LIST:
return (gettext("\tlist [-Hv] [-o property[,...]] "
return (gettext("\tlist [-Hpv] [-o property[,...]] "
"[-T d|u] [pool] ... [interval [count]]\n"));
case HELP_OFFLINE:
return (gettext("\toffline [-t] <pool> <device> ...\n"));
@ -248,7 +248,7 @@ get_usage(zpool_help_t idx) {
case HELP_REMOVE:
return (gettext("\tremove <pool> <device> ...\n"));
case HELP_REOPEN:
return (""); /* Undocumented command */
return (gettext("\treopen <pool>\n"));
case HELP_SCRUB:
return (gettext("\tscrub [-s] <pool> ...\n"));
case HELP_STATUS:
@ -258,8 +258,8 @@ get_usage(zpool_help_t idx) {
return (gettext("\tupgrade [-v]\n"
"\tupgrade [-V version] <-a | pool ...>\n"));
case HELP_GET:
return (gettext("\tget <\"all\" | property[,...]> "
"<pool> ...\n"));
return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
"<\"all\" | property[,...]> <pool> ...\n"));
case HELP_SET:
return (gettext("\tset <property=value> <pool> \n"));
case HELP_SPLIT:
@ -1004,7 +1004,7 @@ zpool_do_create(int argc, char **argv)
* Hand off to libzfs.
*/
if (enable_all_pool_feat) {
int i;
spa_feature_t i;
for (i = 0; i < SPA_FEATURES; i++) {
char propname[MAXPATHLEN];
zfeature_info_t *feat = &spa_feature_table[i];
@ -1702,6 +1702,12 @@ show_import(nvlist_t *config)
"resilvered.\n"));
break;
case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
(void) printf(gettext("status: One or more devices were "
"configured to use a non-native block size.\n"
"\tExpect reduced performance.\n"));
break;
default:
/*
* No other status can be seen when importing pools.
@ -1963,7 +1969,7 @@ zpool_do_import(int argc, char **argv)
char *endptr;
/* check options */
while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) {
while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:R:T:VX")) != -1) {
switch (c) {
case 'a':
do_all = B_TRUE;
@ -2759,6 +2765,7 @@ typedef struct list_cbdata {
int cb_namewidth;
boolean_t cb_scripted;
zprop_list_t *cb_proplist;
boolean_t cb_literal;
} list_cbdata_t;
/*
@ -2854,7 +2861,7 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
zpool_get_prop_int(zhp, pl->pl_prop, NULL) == 0)
propstr = "-";
else if (zpool_get_prop(zhp, pl->pl_prop, property,
sizeof (property), NULL) != 0)
sizeof (property), NULL, cb->cb_literal) != 0)
propstr = "-";
else
propstr = property;
@ -3005,12 +3012,13 @@ list_callback(zpool_handle_t *zhp, void *data)
}
/*
* zpool list [-H] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
* zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
*
* -H Scripted mode. Don't display headers, and separate properties
* by a single tab.
* -o List of properties to display. Defaults to
* "name,size,allocated,free,capacity,health,altroot"
* -p Diplay values in parsable (exact) format.
* -T Display a timestamp in date(1) or Unix format
*
* List all pools in the system, whether or not they're healthy. Output space
@ -3031,7 +3039,7 @@ zpool_do_list(int argc, char **argv)
boolean_t first = B_TRUE;
/* check options */
while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) {
while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
switch (c) {
case 'H':
cb.cb_scripted = B_TRUE;
@ -3039,6 +3047,9 @@ zpool_do_list(int argc, char **argv)
case 'o':
props = optarg;
break;
case 'p':
cb.cb_literal = B_TRUE;
break;
case 'T':
get_timestamp_arg(*optarg);
break;
@ -3714,22 +3725,37 @@ zpool_do_reguid(int argc, char **argv)
* zpool reopen <pool>
*
* Reopen the pool so that the kernel can update the sizes of all vdevs.
*
* NOTE: This command is currently undocumented. If the command is ever
* exposed then the appropriate usage() messages will need to be made.
*/
int
zpool_do_reopen(int argc, char **argv)
{
int c;
int ret = 0;
zpool_handle_t *zhp;
char *pool;
/* check options */
while ((c = getopt(argc, argv, "")) != -1) {
switch (c) {
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
usage(B_FALSE);
}
}
argc--;
argv++;
if (argc != 1)
return (2);
if (argc < 1) {
(void) fprintf(stderr, gettext("missing pool name\n"));
usage(B_FALSE);
}
if (argc > 1) {
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
}
pool = argv[0];
if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
@ -5178,7 +5204,7 @@ get_callback(zpool_handle_t *zhp, void *data)
}
} else {
if (zpool_get_prop(zhp, pl->pl_prop, value,
sizeof (value), &srctype) != 0)
sizeof (value), &srctype, cbp->cb_literal) != 0)
continue;
zprop_print_one_property(zpool_get_name(zhp), cbp,
@ -5189,20 +5215,32 @@ get_callback(zpool_handle_t *zhp, void *data)
return (0);
}
/*
* zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
*
* -H Scripted mode. Don't display headers, and separate properties
* by a single tab.
* -o List of columns to display. Defaults to
* "name,property,value,source".
* -p Diplay values in parsable (exact) format.
*
* Get properties of pools in the system. Output space statistics
* for each one as well as other attributes.
*/
int
zpool_do_get(int argc, char **argv)
{
zprop_get_cbdata_t cb = { 0 };
zprop_list_t fake_name = { 0 };
int ret;
if (argc < 2) {
(void) fprintf(stderr, gettext("missing property "
"argument\n"));
usage(B_FALSE);
}
int c, i;
char *value;
cb.cb_first = B_TRUE;
/*
* Set up default columns and sources.
*/
cb.cb_sources = ZPROP_SRC_ALL;
cb.cb_columns[0] = GET_COL_NAME;
cb.cb_columns[1] = GET_COL_PROPERTY;
@ -5210,10 +5248,89 @@ zpool_do_get(int argc, char **argv)
cb.cb_columns[3] = GET_COL_SOURCE;
cb.cb_type = ZFS_TYPE_POOL;
if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
/* check options */
while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
switch (c) {
case 'p':
cb.cb_literal = B_TRUE;
break;
case 'H':
cb.cb_scripted = B_TRUE;
break;
case 'o':
bzero(&cb.cb_columns, sizeof (cb.cb_columns));
i = 0;
while (*optarg != '\0') {
static char *col_subopts[] =
{ "name", "property", "value", "source",
"all", NULL };
if (i == ZFS_GET_NCOLS) {
(void) fprintf(stderr, gettext("too "
"many fields given to -o "
"option\n"));
usage(B_FALSE);
}
switch (getsubopt(&optarg, col_subopts,
&value)) {
case 0:
cb.cb_columns[i++] = GET_COL_NAME;
break;
case 1:
cb.cb_columns[i++] = GET_COL_PROPERTY;
break;
case 2:
cb.cb_columns[i++] = GET_COL_VALUE;
break;
case 3:
cb.cb_columns[i++] = GET_COL_SOURCE;
break;
case 4:
if (i > 0) {
(void) fprintf(stderr,
gettext("\"all\" conflicts "
"with specific fields "
"given to -o option\n"));
usage(B_FALSE);
}
cb.cb_columns[0] = GET_COL_NAME;
cb.cb_columns[1] = GET_COL_PROPERTY;
cb.cb_columns[2] = GET_COL_VALUE;
cb.cb_columns[3] = GET_COL_SOURCE;
i = ZFS_GET_NCOLS;
break;
default:
(void) fprintf(stderr,
gettext("invalid column name "
"'%s'\n"), value);
usage(B_FALSE);
}
}
break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
usage(B_FALSE);
}
}
argc -= optind;
argv += optind;
if (argc < 1) {
(void) fprintf(stderr, gettext("missing property "
"argument\n"));
usage(B_FALSE);
}
if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
ZFS_TYPE_POOL) != 0)
usage(B_FALSE);
argc--;
argv++;
if (cb.cb_proplist != NULL) {
fake_name.pl_prop = ZPOOL_PROP_NAME;
fake_name.pl_width = strlen(gettext("NAME"));
@ -5221,7 +5338,7 @@ zpool_do_get(int argc, char **argv)
cb.cb_proplist = &fake_name;
}
ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
get_callback, &cb);
if (cb.cb_proplist == &fake_name)

View File

@ -18,10 +18,11 @@
.\" information: Portions Copyright [yyyy] [name of copyright owner]
.\"
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
.\" Copyright (c) 2013, Delphix. All Rights Reserved.
.\"
.\" $FreeBSD$
.\"
.Dd November 26, 2011
.Dd December 31, 2013
.Dt ZSTREAMDUMP 8
.Os
.Sh NAME
@ -30,6 +31,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl C
.Op Fl d
.Op Fl v
.Sh DESCRIPTION
The
@ -43,6 +45,8 @@ The following options are supported:
.Bl -tag -width indent
.It Fl C
Suppress the validation of checksums.
.It Fl d
Dump contents of blocks modified, implies verbose.
.It Fl v
Verbose. Dump all headers, not only begin and end headers.
.El

View File

@ -24,6 +24,11 @@
* Use is subject to license terms.
*/
/*
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <ctype.h>
#include <libnvpair.h>
#include <stdio.h>
#include <stdlib.h>
@ -34,6 +39,16 @@
#include <sys/zfs_ioctl.h>
#include <zfs_fletcher.h>
/*
* If dump mode is enabled, the number of bytes to print per line
*/
#define BYTES_PER_LINE 16
/*
* If dump mode is enabled, the number of bytes to group together, separated
* by newlines or spaces
*/
#define DUMP_GROUPING 4
uint64_t drr_record_count[DRR_NUMTYPES];
uint64_t total_write_size = 0;
uint64_t total_stream_len = 0;
@ -45,9 +60,11 @@ boolean_t do_cksum = B_TRUE;
static void
usage(void)
{
(void) fprintf(stderr, "usage: zstreamdump [-v] [-C] < file\n");
(void) fprintf(stderr, "usage: zstreamdump [-v] [-C] [-d] < file\n");
(void) fprintf(stderr, "\t -v -- verbose\n");
(void) fprintf(stderr, "\t -C -- suppress checksum verification\n");
(void) fprintf(stderr, "\t -d -- dump contents of blocks modified, "
"implies verbose\n");
exit(1);
}
@ -75,6 +92,70 @@ ssread(void *buf, size_t len, zio_cksum_t *cksum)
return (outlen);
}
/*
* Print part of a block in ASCII characters
*/
static void
print_ascii_block(char *subbuf, int length)
{
int i;
for (i = 0; i < length; i++) {
char char_print = isprint(subbuf[i]) ? subbuf[i] : '.';
if (i != 0 && i % DUMP_GROUPING == 0) {
(void) printf(" ");
}
(void) printf("%c", char_print);
}
(void) printf("\n");
}
/*
* print_block - Dump the contents of a modified block to STDOUT
*
* Assume that buf has capacity evenly divisible by BYTES_PER_LINE
*/
static void
print_block(char *buf, int length)
{
int i;
/*
* Start printing ASCII characters at a constant offset, after
* the hex prints. Leave 3 characters per byte on a line (2 digit
* hex number plus 1 space) plus spaces between characters and
* groupings
*/
int ascii_start = BYTES_PER_LINE * 3 +
BYTES_PER_LINE / DUMP_GROUPING + 2;
for (i = 0; i < length; i += BYTES_PER_LINE) {
int j;
int this_line_length = MIN(BYTES_PER_LINE, length - i);
int print_offset = 0;
for (j = 0; j < this_line_length; j++) {
int buf_offset = i + j;
/*
* Separate every DUMP_GROUPING bytes by a space.
*/
if (buf_offset % DUMP_GROUPING == 0) {
print_offset += printf(" ");
}
/*
* Print the two-digit hex value for this byte.
*/
unsigned char hex_print = buf[buf_offset];
print_offset += printf("%02x ", hex_print);
}
(void) printf("%*s", ascii_start - print_offset, " ");
print_ascii_block(buf + i, this_line_length);
}
}
int
main(int argc, char *argv[])
{
@ -92,11 +173,17 @@ main(int argc, char *argv[])
char c;
boolean_t verbose = B_FALSE;
boolean_t first = B_TRUE;
/*
* dump flag controls whether the contents of any modified data blocks
* are printed to the console during processing of the stream. Warning:
* for large streams, this can obviously lead to massive prints.
*/
boolean_t dump = B_FALSE;
int err;
zio_cksum_t zc = { 0 };
zio_cksum_t pcksum = { 0 };
while ((c = getopt(argc, argv, ":vC")) != -1) {
while ((c = getopt(argc, argv, ":vCd")) != -1) {
switch (c) {
case 'C':
do_cksum = B_FALSE;
@ -104,6 +191,10 @@ main(int argc, char *argv[])
case 'v':
verbose = B_TRUE;
break;
case 'd':
dump = B_TRUE;
verbose = B_TRUE;
break;
case ':':
(void) fprintf(stderr,
"missing argument for '%c' option\n", optopt);
@ -128,6 +219,10 @@ main(int argc, char *argv[])
pcksum = zc;
while (ssread(drr, sizeof (dmu_replay_record_t), &zc)) {
/*
* If this is the first DMU record being processed, check for
* the magic bytes and figure out the endian-ness based on them.
*/
if (first) {
if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
do_byteswap = B_TRUE;
@ -209,7 +304,7 @@ main(int argc, char *argv[])
nvlist_t *nv;
int sz = drr->drr_payloadlen;
if (sz > 1<<20) {
if (sz > INITIAL_BUFLEN) {
free(buf);
buf = malloc(sz);
}
@ -283,6 +378,10 @@ main(int argc, char *argv[])
if (drro->drr_bonuslen > 0) {
(void) ssread(buf, P2ROUNDUP(drro->drr_bonuslen,
8), &zc);
if (dump) {
print_block(buf,
P2ROUNDUP(drro->drr_bonuslen, 8));
}
}
break;
@ -312,6 +411,10 @@ main(int argc, char *argv[])
drrw->drr_key.ddk_prop =
BSWAP_64(drrw->drr_key.ddk_prop);
}
/*
* If this is verbose and/or dump output,
* print info on the modified block
*/
if (verbose) {
(void) printf("WRITE object = %llu type = %u "
"checksum type = %u\n"
@ -324,7 +427,16 @@ main(int argc, char *argv[])
(u_longlong_t)drrw->drr_length,
(u_longlong_t)drrw->drr_key.ddk_prop);
}
/*
* Read the contents of the block in from STDIN to buf
*/
(void) ssread(buf, drrw->drr_length, &zc);
/*
* If in dump mode
*/
if (dump) {
print_block(buf, drrw->drr_length);
}
total_write_size += drrw->drr_length;
break;
@ -390,6 +502,9 @@ main(int argc, char *argv[])
drrs->drr_length);
}
(void) ssread(buf, drrs->drr_length, &zc);
if (dump) {
print_block(buf, drrs->drr_length);
}
break;
}
pcksum = zc;

View File

@ -186,7 +186,7 @@ static const ztest_shared_opts_t ztest_opts_defaults = {
extern uint64_t metaslab_gang_bang;
extern uint64_t metaslab_df_alloc_threshold;
extern uint64_t zfs_deadman_synctime;
extern uint64_t zfs_deadman_synctime_ms;
static ztest_shared_opts_t *ztest_shared_opts;
static ztest_shared_opts_t ztest_opts;
@ -5328,10 +5328,10 @@ ztest_deadman_thread(void *arg)
hrtime_t delta, total = 0;
for (;;) {
delta = (zs->zs_thread_stop - zs->zs_thread_start) /
NANOSEC + zfs_deadman_synctime;
delta = zs->zs_thread_stop - zs->zs_thread_start +
MSEC2NSEC(zfs_deadman_synctime_ms);
(void) poll(NULL, 0, (int)(1000 * delta));
(void) poll(NULL, 0, (int)NSEC2MSEC(delta));
/*
* If the pool is suspended then fail immediately. Otherwise,
@ -5339,15 +5339,15 @@ ztest_deadman_thread(void *arg)
* vdev_deadman() discovers that there hasn't been any recent
* I/Os then it will end up aborting the tests.
*/
if (spa_suspended(spa)) {
if (spa_suspended(spa) || spa->spa_root_vdev == NULL) {
fatal(0, "aborting test after %llu seconds because "
"pool has transitioned to a suspended state.",
zfs_deadman_synctime);
zfs_deadman_synctime_ms / 1000);
return (NULL);
}
vdev_deadman(spa->spa_root_vdev);
total += zfs_deadman_synctime;
total += zfs_deadman_synctime_ms/1000;
(void) printf("ztest has been running for %lld seconds\n",
total);
}
@ -6080,7 +6080,7 @@ main(int argc, char **argv)
(void) setvbuf(stdout, NULL, _IOLBF, 0);
dprintf_setup(&argc, argv);
zfs_deadman_synctime = 300;
zfs_deadman_synctime_ms = 300000;
ztest_fd_rand = open("/dev/urandom", O_RDONLY);
ASSERT3S(ztest_fd_rand, >=, 0);

View File

@ -65,7 +65,7 @@ ctf_create(int *errp)
cts.cts_name = _CTF_SECTION;
cts.cts_type = SHT_PROGBITS;
cts.cts_flags = 0;
cts.cts_data = &hdr;
cts.cts_data = (void *)&hdr;
cts.cts_size = sizeof (hdr);
cts.cts_entsize = 1;
cts.cts_offset = 0;

View File

@ -20,6 +20,7 @@
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Copyright 2013 Voxer Inc. All rights reserved.
* Use is subject to license terms.
*/
@ -144,7 +145,8 @@ dtrace_dof_init(void)
Lmid_t lmid;
#else
u_long lmid = 0;
dof_sec_t *sec;
dof_sec_t *sec, *secstart, *dofstrtab, *dofprobes;
dof_provider_t *dofprovider;
size_t i;
#endif
int fd;
@ -152,14 +154,15 @@ dtrace_dof_init(void)
#if !defined(sun)
Elf *e;
Elf_Scn *scn = NULL;
Elf_Data *symtabdata = NULL, *dynsymdata = NULL;
Elf_Data *symtabdata = NULL, *dynsymdata = NULL, *dofdata = NULL;
dof_hdr_t *dof_next = NULL;
GElf_Shdr shdr;
int efd, nprobes;
char *s;
char *dofstrtabraw;
size_t shstridx, symtabidx = 0, dynsymidx = 0;
unsigned char *dofstrtab = NULL;
unsigned char *buf;
int fixedprobes = 0;
int fixedprobes;
#endif
if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
@ -209,7 +212,8 @@ dtrace_dof_init(void)
} else if (shdr.sh_type == SHT_PROGBITS) {
s = elf_strptr(e, shstridx, shdr.sh_name);
if (s && strcmp(s, ".SUNW_dof") == 0) {
dof = elf_getdata(scn, NULL)->d_buf;
dofdata = elf_getdata(scn, NULL);
dof = dofdata->d_buf;
}
}
}
@ -219,6 +223,10 @@ dtrace_dof_init(void)
close(efd);
return;
}
while ((char *) dof < (char *) dofdata->d_buf + dofdata->d_size) {
fixedprobes = 0;
dof_next = (void *) ((char *) dof + dof->dofh_filesz);
#endif
if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
@ -290,34 +298,49 @@ dtrace_dof_init(void)
* We are assuming the number of probes is less than the number of
* symbols (libc can have 4k symbols, for example).
*/
sec = (dof_sec_t *)(dof + 1);
secstart = sec = (dof_sec_t *)(dof + 1);
buf = (char *)dof;
for (i = 0; i < dof->dofh_secnum; i++, sec++) {
if (sec->dofs_type == DOF_SECT_STRTAB)
dofstrtab = (unsigned char *)(buf + sec->dofs_offset);
else if (sec->dofs_type == DOF_SECT_PROBES && dofstrtab)
if (sec->dofs_type != DOF_SECT_PROVIDER)
continue;
dofprovider = (void *) (buf + sec->dofs_offset);
dofstrtab = secstart + dofprovider->dofpv_strtab;
dofprobes = secstart + dofprovider->dofpv_probes;
if (dofstrtab->dofs_type != DOF_SECT_STRTAB) {
fprintf(stderr, "WARNING: expected STRTAB section, but got %d\n",
dofstrtab->dofs_type);
break;
}
nprobes = sec->dofs_size / sec->dofs_entsize;
fixsymbol(e, symtabdata, symtabidx, nprobes, buf, sec, &fixedprobes,
dofstrtab);
if (fixedprobes != nprobes) {
/*
* If we haven't fixed all the probes using the
* symtab section, look inside the dynsym
* section.
*/
fixsymbol(e, dynsymdata, dynsymidx, nprobes, buf, sec,
&fixedprobes, dofstrtab);
}
if (fixedprobes != nprobes) {
fprintf(stderr, "WARNING: number of probes "
"fixed does not match the number of "
"defined probes (%d != %d, "
"respectively)\n", fixedprobes, nprobes);
fprintf(stderr, "WARNING: some probes might "
"not fire or your program might crash\n");
}
if (dofprobes->dofs_type != DOF_SECT_PROBES) {
fprintf(stderr, "WARNING: expected PROBES section, but got %d\n",
dofprobes->dofs_type);
break;
}
dprintf(1, "found provider %p\n", dofprovider);
dofstrtabraw = (char *)(buf + dofstrtab->dofs_offset);
nprobes = dofprobes->dofs_size / dofprobes->dofs_entsize;
fixsymbol(e, symtabdata, symtabidx, nprobes, buf, dofprobes, &fixedprobes,
dofstrtabraw);
if (fixedprobes != nprobes) {
/*
* If we haven't fixed all the probes using the
* symtab section, look inside the dynsym
* section.
*/
fixsymbol(e, dynsymdata, dynsymidx, nprobes, buf, dofprobes,
&fixedprobes, dofstrtabraw);
}
if (fixedprobes != nprobes) {
fprintf(stderr, "WARNING: number of probes "
"fixed does not match the number of "
"defined probes (%d != %d, "
"respectively)\n", fixedprobes, nprobes);
fprintf(stderr, "WARNING: some probes might "
"not fire or your program might crash\n");
}
}
#endif
if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
@ -330,7 +353,12 @@ dtrace_dof_init(void)
}
(void) close(fd);
#if !defined(sun)
/* End of while loop */
dof = dof_next;
}
elf_end(e);
(void) close(efd);
#endif

View File

@ -22,6 +22,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
@ -486,7 +487,7 @@ dof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
return (0);
}
static void
static int
dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
{
dtrace_hdl_t *dtp = ddo->ddo_hdl;
@ -497,8 +498,12 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
size_t sz;
id_t i;
if (pvp->pv_flags & DT_PROVIDER_IMPL)
return; /* ignore providers that are exported by dtrace(7D) */
if (pvp->pv_flags & DT_PROVIDER_IMPL) {
/*
* ignore providers that are exported by dtrace(7D)
*/
return (0);
}
nxr = dt_popcb(pvp->pv_xrefs, pvp->pv_xrmax);
dofs = alloca(sizeof (dof_secidx_t) * (nxr + 1));
@ -525,6 +530,9 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
(void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo);
if (dt_buf_len(&ddo->ddo_probes) == 0)
return (dt_set_errno(dtp, EDT_NOPROBES));
dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES,
sizeof (uint64_t), 0, sizeof (dof_probe_t),
dt_buf_len(&ddo->ddo_probes));
@ -579,6 +587,8 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
sizeof (dof_secidx_t), 0, sizeof (dof_secidx_t),
sizeof (dof_secidx_t) * (nxr + 1));
}
return (0);
}
static int
@ -822,8 +832,10 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
*/
if (flags & DTRACE_D_PROBES) {
for (pvp = dt_list_next(&dtp->dt_provlist);
pvp != NULL; pvp = dt_list_next(pvp))
dof_add_provider(ddo, pvp);
pvp != NULL; pvp = dt_list_next(pvp)) {
if (dof_add_provider(ddo, pvp) != 0)
return (NULL);
}
}
/*

View File

@ -26,6 +26,7 @@
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <string.h>
@ -109,7 +110,8 @@ static const struct {
{ EDT_BADSTACKPC, "Invalid stack program counter size" },
{ EDT_BADAGGVAR, "Invalid aggregation variable identifier" },
{ EDT_OVERSION, "Client requested deprecated version of library" },
{ EDT_ENABLING_ERR, "Failed to enable probe" }
{ EDT_ENABLING_ERR, "Failed to enable probe" },
{ EDT_NOPROBES, "No probe sites found for declared provider" }
};
static const int _dt_nerr = sizeof (_dt_errlist) / sizeof (_dt_errlist[0]);

View File

@ -25,7 +25,7 @@
*/
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@ -535,7 +535,8 @@ enum {
EDT_BADSTACKPC, /* invalid stack program counter size */
EDT_BADAGGVAR, /* invalid aggregation variable identifier */
EDT_OVERSION, /* client is requesting deprecated version */
EDT_ENABLING_ERR /* failed to enable probe */
EDT_ENABLING_ERR, /* failed to enable probe */
EDT_NOPROBES /* no probes sites for declared provider */
};
/*

View File

@ -242,8 +242,14 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
#elif defined(__powerpc__)
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
/*
* Add 4 bytes to hit the low half of this 64-bit
* big-endian address.
*/
rel->r_offset = s->dofs_offset +
dofr[j].dofr_offset + 4;
rel->r_info = ELF32_R_INFO(count + dep->de_global,
R_PPC_REL32);
#elif defined(__sparc)
/*
* Add 4 bytes to hit the low half of this 64-bit
@ -423,7 +429,10 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
#elif defined(__mips__)
/* XXX */
#elif defined(__powerpc__)
/* XXX */
rel->r_offset = s->dofs_offset +
dofr[j].dofr_offset;
rel->r_info = ELF64_R_INFO(count + dep->de_global,
R_PPC64_REL64);
#elif defined(__i386) || defined(__amd64)
rel->r_offset = s->dofs_offset +
dofr[j].dofr_offset;
@ -824,12 +833,84 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
return (0);
}
#elif defined(__powerpc__)
/* The sentinel is 'xor r3,r3,r3'. */
#define DT_OP_XOR_R3 0x7c631a78
#define DT_OP_NOP 0x60000000
#define DT_OP_BLR 0x4e800020
/* This captures all forms of branching to address. */
#define DT_IS_BRANCH(inst) ((inst & 0xfc000000) == 0x48000000)
#define DT_IS_BL(inst) (DT_IS_BRANCH(inst) && (inst & 0x01))
/* XXX */
static int
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
uint32_t *off)
{
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
uint32_t *ip;
if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
return (-1);
/*LINTED*/
ip = (uint32_t *)(p + rela->r_offset);
/*
* We only know about some specific relocation types.
*/
if (GELF_R_TYPE(rela->r_info) != R_PPC_REL24 &&
GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24)
return (-1);
/*
* We may have already processed this object file in an earlier linker
* invocation. Check to see if the present instruction sequence matches
* the one we would install below.
*/
if (isenabled) {
if (ip[0] == DT_OP_XOR_R3) {
(*off) += sizeof (ip[0]);
return (0);
}
} else {
if (ip[0] == DT_OP_NOP) {
(*off) += sizeof (ip[0]);
return (0);
}
}
/*
* We only expect branch to address instructions.
*/
if (!DT_IS_BRANCH(ip[0])) {
dt_dprintf("found %x instead of a branch instruction at %llx\n",
ip[0], (u_longlong_t)rela->r_offset);
return (-1);
}
if (isenabled) {
/*
* It would necessarily indicate incorrect usage if an is-
* enabled probe were tail-called so flag that as an error.
* It's also potentially (very) tricky to handle gracefully,
* but could be done if this were a desired use scenario.
*/
if (!DT_IS_BL(ip[0])) {
dt_dprintf("tail call to is-enabled probe at %llx\n",
(u_longlong_t)rela->r_offset);
return (-1);
}
ip[0] = DT_OP_XOR_R3;
(*off) += sizeof (ip[0]);
} else {
if (DT_IS_BL(ip[0]))
ip[0] = DT_OP_NOP;
else
ip[0] = DT_OP_BLR;
}
return (0);
}
@ -1539,10 +1620,17 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
* the executable file as the symbol is going to be
* change from UND to ABS.
*/
rela.r_offset = 0;
rela.r_info = 0;
rela.r_addend = 0;
(void) gelf_update_rela(data_rel, i, &rela);
if (shdr_rel.sh_type == SHT_RELA) {
rela.r_offset = 0;
rela.r_info = 0;
rela.r_addend = 0;
(void) gelf_update_rela(data_rel, i, &rela);
} else {
GElf_Rel rel;
rel.r_offset = 0;
rel.r_info = 0;
(void) gelf_update_rel(data_rel, i, &rel);
}
#endif
mod = 1;
@ -1628,8 +1716,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
*/
return (0);
}
/* XXX Should get a temp file name here. */
snprintf(tfile, sizeof(tfile), "%s.tmp", file);
#endif
/*
@ -1704,9 +1790,11 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
"failed to open %s: %s", file, strerror(errno)));
}
#else
if ((fd = open(tfile, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1)
snprintf(tfile, sizeof(tfile), "%s.XXXXXX", file);
if ((fd = mkstemp(tfile)) == -1)
return (dt_link_error(dtp, NULL, -1, NULL,
"failed to open %s: %s", tfile, strerror(errno)));
"failed to create temporary file %s: %s",
tfile, strerror(errno)));
#endif
/*
@ -1749,13 +1837,15 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
status = dump_elf32(dtp, dof, fd);
if (status != 0 || lseek(fd, 0, SEEK_SET) != 0) {
#else
/* We don't write the ELF header, just the DOF section */
if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz) {
#endif
return (dt_link_error(dtp, NULL, -1, NULL,
"failed to write %s: %s", file, strerror(errno)));
}
#else
/* We don't write the ELF header, just the DOF section */
if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz)
return (dt_link_error(dtp, NULL, -1, NULL,
"failed to write %s: %s", tfile, strerror(errno)));
#endif
if (!dtp->dt_lazyload) {
#if defined(sun)
@ -1783,7 +1873,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
* Arches which default to 64-bit need to explicitly use
* the 32-bit library path.
*/
int use_32 = !(dtp->dt_oflags & DTRACE_O_LP64);
int use_32 = (dtp->dt_oflags & DTRACE_O_ILP32);
#else
/*
* Arches which are 32-bit only just use the normal
@ -1798,9 +1888,7 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
drti) + 1;
#if !defined(sun)
len *= 2;
#endif
cmd = alloca(len);
(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file,

View File

@ -311,6 +311,10 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_func, "void(@)" },
{ "memref", DT_IDENT_FUNC, 0, DIF_SUBR_MEMREF, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "uintptr_t *(void *, size_t)" },
#if !defined(sun)
{ "memstr", DT_IDENT_FUNC, 0, DIF_SUBR_MEMSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "string(void *, char, size_t)" },
#endif
{ "min", DT_IDENT_AGGFUNC, 0, DTRACEAGG_MIN, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void(@)" },
{ "mod", DT_IDENT_ACTFUNC, 0, DT_ACT_MOD, DT_ATTR_STABCMN,
@ -483,22 +487,16 @@ static const dt_ident_t _dtrace_globals[] = {
DT_VERS_1_0, &dt_idops_func, "void(...)" },
{ "typeref", DT_IDENT_FUNC, 0, DIF_SUBR_TYPEREF, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "uintptr_t *(void *, size_t, string, size_t)" },
#if defined(sun)
{ "uaddr", DT_IDENT_ACTFUNC, 0, DT_ACT_UADDR, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
#endif
{ "ucaller", DT_IDENT_SCALAR, 0, DIF_VAR_UCALLER, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_type, "uint64_t" },
#if defined(sun)
{ "ufunc", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
#endif
{ "uid", DT_IDENT_SCALAR, 0, DIF_VAR_UID, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uid_t" },
#if defined(sun)
{ "umod", DT_IDENT_ACTFUNC, 0, DT_ACT_UMOD, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
#endif
{ "uregs", DT_IDENT_ARRAY, 0, DIF_VAR_UREGS, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_regs, NULL },
{ "ustack", DT_IDENT_ACTFUNC, 0, DT_ACT_USTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
@ -506,10 +504,8 @@ static const dt_ident_t _dtrace_globals[] = {
{ "ustackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_USTACKDEPTH,
DT_ATTR_STABCMN, DT_VERS_1_2,
&dt_idops_type, "uint32_t" },
#if defined(sun)
{ "usym", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
#endif
{ "vtimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_VTIMESTAMP,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uint64_t" },

View File

@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@ -906,30 +904,6 @@ dt_options_load(dtrace_hdl_t *dtp)
return (0);
}
/*ARGSUSED*/
static int
dt_opt_preallocate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
{
dtrace_optval_t size;
void *p;
if (arg == NULL || dt_optval_parse(arg, &size) != 0)
return (dt_set_errno(dtp, EDT_BADOPTVAL));
if (size > SIZE_MAX)
size = SIZE_MAX;
if ((p = dt_zalloc(dtp, size)) == NULL) {
do {
size /= 2;
} while ((p = dt_zalloc(dtp, size)) == NULL);
}
dt_free(dtp, p);
return (0);
}
typedef struct dt_option {
const char *o_name;
int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
@ -968,7 +942,6 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "linktype", dt_opt_linktype },
{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
{ "pgmax", dt_opt_pgmax },
{ "preallocate", dt_opt_preallocate },
{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
{ "setenv", dt_opt_setenv, 1 },
{ "stdc", dt_opt_stdc },

View File

@ -694,8 +694,13 @@ static const dt_pfconv_t _dtrace_conversions[] = {
{ "S", "s", pfproto_cstr, pfcheck_str, pfprint_estr },
{ "T", "s", "int64_t", pfcheck_time, pfprint_time822 },
{ "u", "u", pfproto_xint, pfcheck_xint, pfprint_uint },
#if defined(sun)
{ "wc", "wc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wchar_t */
{ "ws", "ws", pfproto_wstr, pfcheck_wstr, pfprint_wstr },
#else
{ "wc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wchar_t */
{ "ws", "ls", pfproto_wstr, pfcheck_wstr, pfprint_wstr },
#endif
{ "x", "x", pfproto_xint, pfcheck_xint, pfprint_uint },
{ "X", "X", pfproto_xint, pfcheck_xint, pfprint_uint },
{ "Y", "s", "int64_t", pfcheck_time, pfprint_time },

View File

@ -734,11 +734,6 @@ dt_zalloc(dtrace_hdl_t *dtp, size_t size)
{
void *data;
if (size > 16 * 1024 * 1024) {
(void) dt_set_errno(dtp, EDT_NOMEM);
return (NULL);
}
if ((data = malloc(size)) == NULL)
(void) dt_set_errno(dtp, EDT_NOMEM);
else
@ -752,11 +747,6 @@ dt_alloc(dtrace_hdl_t *dtp, size_t size)
{
void *data;
if (size > 16 * 1024 * 1024) {
(void) dt_set_errno(dtp, EDT_NOMEM);
return (NULL);
}
if ((data = malloc(size)) == NULL)
(void) dt_set_errno(dtp, EDT_NOMEM);

View File

@ -35,14 +35,26 @@
#include <dt_impl.h>
#include <dt_pid.h>
#include <libproc_compat.h>
/*ARGSUSED*/
int
dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
{
ftp->ftps_type = DTFTP_ENTRY;
ftp->ftps_pc = (uintptr_t)symp->st_value;
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 1;
ftp->ftps_offs[0] = 0;
dt_dprintf("%s: unimplemented\n", __func__);
return (DT_PROC_ERR);
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
return (1);
}
int
@ -50,8 +62,74 @@ dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
{
dt_dprintf("%s: unimplemented\n", __func__);
return (DT_PROC_ERR);
uintptr_t temp;
uint32_t *text;
int i;
int srdepth = 0;
if ((text = malloc(symp->st_size + 4)) == NULL) {
dt_dprintf("mr sparkle: malloc() failed\n");
return (DT_PROC_ERR);
}
if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
dt_dprintf("mr sparkle: Pread() failed\n");
free(text);
return (DT_PROC_ERR);
}
/*
* Leave a dummy instruction in the last slot to simplify edge
* conditions.
*/
text[symp->st_size / 4] = 0;
ftp->ftps_type = DTFTP_RETURN;
ftp->ftps_pc = symp->st_value;
ftp->ftps_size = symp->st_size;
ftp->ftps_noffs = 0;
for (i = 0; i < symp->st_size / 4; i++) {
if ((text[i] & 0xfc000001) != 0x48000000 &&
text[i] != 0x4e800020)
continue;
/*
* Check for a jump within this function. If it's outside this
* function then it's a tail-call, so a return point.
*/
if ((text[i] & 0xfc000000) == 0x48000000) {
temp = (text[i] & 0x03fffffc);
/* Bit 30 denotes an absolute address. */
if (!(text[i] & 0x02)) {
temp += symp->st_value + i * 4;
}
else {
/* Sign extend the absolute address. */
if (temp & 0x02000000) {
temp |= (UINTPTR_MAX - 0x03ffffff);
}
}
if (temp >= symp->st_value &&
temp <= (symp->st_value + symp->st_size))
continue;
}
dt_dprintf("return at offset %x\n", i * 4);
ftp->ftps_offs[ftp->ftps_noffs++] = i * 4;
}
free(text);
if (ftp->ftps_noffs > 0) {
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
}
return (ftp->ftps_noffs);
}
/*ARGSUSED*/
@ -59,9 +137,22 @@ int
dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
{
if (off & 0x3)
return (DT_PROC_ALIGN);
dt_dprintf("%s: unimplemented\n", __func__);
return (DT_PROC_ERR);
ftp->ftps_type = DTFTP_OFFSETS;
ftp->ftps_pc = (uintptr_t)symp->st_value;
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 1;
ftp->ftps_offs[0] = off;
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
return (1);
}
/*ARGSUSED*/
@ -69,7 +160,38 @@ int
dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
{
ulong_t i;
dt_dprintf("%s: unimplemented\n", __func__);
return (DT_PROC_ERR);
ftp->ftps_type = DTFTP_OFFSETS;
ftp->ftps_pc = (uintptr_t)symp->st_value;
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 0;
/*
* If we're matching against everything, just iterate through each
* instruction in the function, otherwise look for matching offset
* names by constructing the string and comparing it against the
* pattern.
*/
if (strcmp("*", pattern) == 0) {
for (i = 0; i < symp->st_size; i += 4) {
ftp->ftps_offs[ftp->ftps_noffs++] = i;
}
} else {
char name[sizeof (i) * 2 + 1];
for (i = 0; i < symp->st_size; i += 4) {
(void) sprintf(name, "%lx", i);
if (gmatch(name, pattern))
ftp->ftps_offs[ftp->ftps_noffs++] = i;
}
}
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
return (ftp->ftps_noffs);
}

View File

@ -210,7 +210,7 @@ NVLIST_PRTFUNC(int32, int32_t, int32_t, "%d")
NVLIST_PRTFUNC(uint32, uint32_t, uint32_t, "0x%x")
NVLIST_PRTFUNC(int64, int64_t, longlong_t, "%lld")
NVLIST_PRTFUNC(uint64, uint64_t, u_longlong_t, "0x%llx")
NVLIST_PRTFUNC(double, double, double, "0x%llf")
NVLIST_PRTFUNC(double, double, double, "0x%f")
NVLIST_PRTFUNC(string, char *, char *, "%s")
NVLIST_PRTFUNC(hrtime, hrtime_t, hrtime_t, "0x%llx")

View File

@ -128,6 +128,7 @@ uu_avl_pool_destroy(uu_avl_pool_t *pp)
pp->uap_next->uap_prev = pp->uap_prev;
pp->uap_prev->uap_next = pp->uap_next;
(void) pthread_mutex_unlock(&uu_apool_list_lock);
(void) pthread_mutex_destroy(&pp->uap_lock);
pp->uap_prev = NULL;
pp->uap_next = NULL;
uu_free(pp);

View File

@ -21,13 +21,13 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _LIBZFS_H
@ -193,6 +193,7 @@ extern int zpool_log_history(libzfs_handle_t *, const char *);
extern int libzfs_errno(libzfs_handle_t *);
extern const char *libzfs_error_action(libzfs_handle_t *);
extern const char *libzfs_error_description(libzfs_handle_t *);
extern int zfs_standard_error(libzfs_handle_t *, int, const char *);
extern void libzfs_mnttab_init(libzfs_handle_t *);
extern void libzfs_mnttab_fini(libzfs_handle_t *);
extern void libzfs_mnttab_cache(libzfs_handle_t *, boolean_t);
@ -269,7 +270,7 @@ extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, const char *);
*/
extern int zpool_set_prop(zpool_handle_t *, const char *, const char *);
extern int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *,
size_t proplen, zprop_source_t *);
size_t proplen, zprop_source_t *, boolean_t);
extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t,
zprop_source_t *);
@ -463,7 +464,8 @@ typedef struct zprop_list {
boolean_t pl_fixed;
} zprop_list_t;
extern int zfs_expand_proplist(zfs_handle_t *, zprop_list_t **, boolean_t);
extern int zfs_expand_proplist(zfs_handle_t *, zprop_list_t **, boolean_t,
boolean_t);
extern void zfs_prune_proplist(zfs_handle_t *, uint8_t *);
#define ZFS_MOUNTPOINT_NONE "none"
@ -536,6 +538,7 @@ extern int zfs_iter_filesystems(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_snapshots(zfs_handle_t *, boolean_t, zfs_iter_f, void *);
extern int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_snapspec(zfs_handle_t *, const char *, zfs_iter_f, void *);
extern int zfs_iter_bookmarks(zfs_handle_t *, zfs_iter_f, void *);
typedef struct get_all_cb {
zfs_handle_t **cb_handles;
@ -610,6 +613,7 @@ typedef boolean_t (snapfilter_cb_t)(zfs_handle_t *, void *);
extern int zfs_send(zfs_handle_t *, const char *, const char *,
sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
extern int zfs_send_one(zfs_handle_t *, const char *, int);
extern int zfs_promote(zfs_handle_t *);
extern int zfs_hold(zfs_handle_t *, const char *, const char *,
@ -679,6 +683,7 @@ extern zfs_handle_t *zfs_path_to_zhandle(libzfs_handle_t *, char *, zfs_type_t);
extern boolean_t zfs_dataset_exists(libzfs_handle_t *, const char *,
zfs_type_t);
extern int zfs_spa_version(zfs_handle_t *, int *);
extern boolean_t zfs_bookmark_exists(const char *path);
/*
* Mount support functions.

View File

@ -21,13 +21,14 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <ctype.h>
@ -295,7 +296,7 @@ zpool_handle(zfs_handle_t *zhp)
int len;
zpool_handle_t *zph;
len = strcspn(zhp->zfs_name, "/@") + 1;
len = strcspn(zhp->zfs_name, "/@#") + 1;
pool_name = zfs_alloc(zhp->zfs_hdl, len);
(void) strlcpy(pool_name, zhp->zfs_name, len);
@ -579,6 +580,70 @@ zfs_handle_dup(zfs_handle_t *zhp_orig)
return (zhp);
}
boolean_t
zfs_bookmark_exists(const char *path)
{
nvlist_t *bmarks;
nvlist_t *props;
char fsname[ZFS_MAXNAMELEN];
char *bmark_name;
char *pound;
int err;
boolean_t rv;
(void) strlcpy(fsname, path, sizeof (fsname));
pound = strchr(fsname, '#');
if (pound == NULL)
return (B_FALSE);
*pound = '\0';
bmark_name = pound + 1;
props = fnvlist_alloc();
err = lzc_get_bookmarks(fsname, props, &bmarks);
nvlist_free(props);
if (err != 0) {
nvlist_free(bmarks);
return (B_FALSE);
}
rv = nvlist_exists(bmarks, bmark_name);
nvlist_free(bmarks);
return (rv);
}
zfs_handle_t *
make_bookmark_handle(zfs_handle_t *parent, const char *path,
nvlist_t *bmark_props)
{
zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
if (zhp == NULL)
return (NULL);
/* Fill in the name. */
zhp->zfs_hdl = parent->zfs_hdl;
(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
/* Set the property lists. */
if (nvlist_dup(bmark_props, &zhp->zfs_props, 0) != 0) {
free(zhp);
return (NULL);
}
/* Set the types. */
zhp->zfs_head_type = parent->zfs_head_type;
zhp->zfs_type = ZFS_TYPE_BOOKMARK;
if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL) {
nvlist_free(zhp->zfs_props);
free(zhp);
return (NULL);
}
return (zhp);
}
/*
* Opens the given snapshot, filesystem, or volume. The 'types'
* argument is a mask of acceptable types. The function will print an
@ -1846,6 +1911,10 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
case ZFS_PROP_REFQUOTA:
case ZFS_PROP_RESERVATION:
case ZFS_PROP_REFRESERVATION:
case ZFS_PROP_FILESYSTEM_LIMIT:
case ZFS_PROP_SNAPSHOT_LIMIT:
case ZFS_PROP_FILESYSTEM_COUNT:
case ZFS_PROP_SNAPSHOT_COUNT:
*val = getprop_uint64(zhp, prop, source);
if (*source == NULL) {
@ -2173,8 +2242,8 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
}
if ((zpool_get_prop(zhp->zpool_hdl,
ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) ||
(strcmp(root, "-") == 0))
ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL,
B_FALSE)) || (strcmp(root, "-") == 0))
root[0] = '\0';
/*
* Special case an alternate root of '/'. This will
@ -2251,6 +2320,30 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
}
break;
case ZFS_PROP_FILESYSTEM_LIMIT:
case ZFS_PROP_SNAPSHOT_LIMIT:
case ZFS_PROP_FILESYSTEM_COUNT:
case ZFS_PROP_SNAPSHOT_COUNT:
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
return (-1);
/*
* If limit is UINT64_MAX, we translate this into 'none' (unless
* literal is set), and indicate that it's the default value.
* Otherwise, we print the number nicely and indicate that it's
* set locally.
*/
if (literal) {
(void) snprintf(propbuf, proplen, "%llu",
(u_longlong_t)val);
} else if (val == UINT64_MAX) {
(void) strlcpy(propbuf, "none", proplen);
} else {
zfs_nicenum(val, propbuf, proplen);
}
break;
case ZFS_PROP_REFRATIO:
case ZFS_PROP_COMPRESSRATIO:
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
@ -2271,6 +2364,9 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
case ZFS_TYPE_SNAPSHOT:
str = "snapshot";
break;
case ZFS_TYPE_BOOKMARK:
str = "bookmark";
break;
default:
abort();
}
@ -2477,6 +2573,7 @@ idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
return (err);
#else /* !sun */
assert(!"invalid code path");
return (EINVAL); // silence compiler warning
#endif /* !sun */
}
@ -3133,6 +3230,19 @@ zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
{
zfs_cmd_t zc = { 0 };
if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
nvlist_t *nv = fnvlist_alloc();
fnvlist_add_boolean(nv, zhp->zfs_name);
int error = lzc_destroy_bookmarks(nv, NULL);
fnvlist_free(nv);
if (error != 0) {
return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
zhp->zfs_name));
}
return (0);
}
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
if (ZFS_IS_VOLUME(zhp)) {
@ -3515,45 +3625,44 @@ typedef struct rollback_data {
const char *cb_target; /* the snapshot */
uint64_t cb_create; /* creation time reference */
boolean_t cb_error;
boolean_t cb_dependent;
boolean_t cb_force;
} rollback_data_t;
static int
rollback_destroy_dependent(zfs_handle_t *zhp, void *data)
{
rollback_data_t *cbp = data;
prop_changelist_t *clp;
/* We must destroy this clone; first unmount it */
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
cbp->cb_force ? MS_FORCE: 0);
if (clp == NULL || changelist_prefix(clp) != 0) {
cbp->cb_error = B_TRUE;
zfs_close(zhp);
return (0);
}
if (zfs_destroy(zhp, B_FALSE) != 0)
cbp->cb_error = B_TRUE;
else
changelist_remove(clp, zhp->zfs_name);
(void) changelist_postfix(clp);
changelist_free(clp);
zfs_close(zhp);
return (0);
}
static int
rollback_destroy(zfs_handle_t *zhp, void *data)
{
rollback_data_t *cbp = data;
if (!cbp->cb_dependent) {
if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 &&
zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
cbp->cb_create) {
if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
rollback_destroy_dependent, cbp);
cbp->cb_dependent = B_TRUE;
cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
rollback_destroy, cbp);
cbp->cb_dependent = B_FALSE;
cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
}
} else {
/* We must destroy this clone; first unmount it */
prop_changelist_t *clp;
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
cbp->cb_force ? MS_FORCE: 0);
if (clp == NULL || changelist_prefix(clp) != 0) {
cbp->cb_error = B_TRUE;
zfs_close(zhp);
return (0);
}
if (zfs_destroy(zhp, B_FALSE) != 0)
cbp->cb_error = B_TRUE;
else
changelist_remove(clp, zhp->zfs_name);
(void) changelist_postfix(clp);
changelist_free(clp);
cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
}
zfs_close(zhp);
@ -3564,8 +3673,8 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
* Given a dataset, rollback to a specific snapshot, discarding any
* data changes since then and making it the active dataset.
*
* Any snapshots more recent than the target are destroyed, along with
* their dependents.
* Any snapshots and bookmarks more recent than the target are
* destroyed, along with their dependents (i.e. clones).
*/
int
zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
@ -3585,7 +3694,8 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
cb.cb_force = force;
cb.cb_target = snap->zfs_name;
cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
(void) zfs_iter_children(zhp, rollback_destroy, &cb);
(void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb);
(void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
if (cb.cb_error)
return (-1);
@ -3882,7 +3992,8 @@ zfs_get_recvd_props(zfs_handle_t *zhp)
* of the RECEIVED column.
*/
int
zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received)
zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received,
boolean_t literal)
{
libzfs_handle_t *hdl = zhp->zfs_hdl;
zprop_list_t *entry;
@ -3944,18 +4055,18 @@ zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received)
* Now go through and check the width of any non-fixed columns
*/
for (entry = *plp; entry != NULL; entry = entry->pl_next) {
if (entry->pl_fixed)
if (entry->pl_fixed && !literal)
continue;
if (entry->pl_prop != ZPROP_INVAL) {
if (zfs_prop_get(zhp, entry->pl_prop,
buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) {
buf, sizeof (buf), NULL, NULL, 0, literal) == 0) {
if (strlen(buf) > entry->pl_width)
entry->pl_width = strlen(buf);
}
if (received && zfs_prop_get_recvd(zhp,
zfs_prop_to_name(entry->pl_prop),
buf, sizeof (buf), B_FALSE) == 0)
buf, sizeof (buf), literal) == 0)
if (strlen(buf) > entry->pl_recvd_width)
entry->pl_recvd_width = strlen(buf);
} else {
@ -3968,7 +4079,7 @@ zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received)
}
if (received && zfs_prop_get_recvd(zhp,
entry->pl_user_prop,
buf, sizeof (buf), B_FALSE) == 0)
buf, sizeof (buf), literal) == 0)
if (strlen(buf) > entry->pl_recvd_width)
entry->pl_recvd_width = strlen(buf);
}

View File

@ -23,7 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
*/
@ -191,6 +191,8 @@ int create_parents(libzfs_handle_t *, char *, int);
boolean_t isa_child_of(const char *dataset, const char *parent);
zfs_handle_t *make_dataset_handle(libzfs_handle_t *, const char *);
zfs_handle_t *make_bookmark_handle(zfs_handle_t *, const char *,
nvlist_t *props);
int zpool_open_silent(libzfs_handle_t *, const char *, zpool_handle_t **);

View File

@ -20,8 +20,8 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@ -995,10 +995,10 @@ nozpool_all_slices(avl_tree_t *r, const char *sname)
#endif /* sun */
}
#ifdef sun
static void
check_slices(avl_tree_t *r, int fd, const char *sname)
{
#ifdef sun
struct extvtoc vtoc;
struct dk_gpt *gpt;
char diskname[MAXNAMELEN];
@ -1028,8 +1028,8 @@ check_slices(avl_tree_t *r, int fd, const char *sname)
check_one_slice(r, diskname, i, 0, 1);
efi_free(gpt);
}
#endif /* sun */
}
#endif /* sun */
static void
zpool_open_func(void *arg)
@ -1059,6 +1059,7 @@ zpool_open_func(void *arg)
return;
}
/* this file is too small to hold a zpool */
#ifdef sun
if (S_ISREG(statbuf.st_mode) &&
statbuf.st_size < SPA_MINDEVSIZE) {
(void) close(fd);
@ -1070,6 +1071,12 @@ zpool_open_func(void *arg)
*/
check_slices(rn->rn_avl, fd, rn->rn_name);
}
#else /* !sun */
if (statbuf.st_size < SPA_MINDEVSIZE) {
(void) close(fd);
return;
}
#endif /* sun */
if ((zpool_read_label(fd, &config)) != 0) {
(void) close(fd);
@ -1606,9 +1613,16 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
* its state to active.
*/
if (pool_active(hdl, name, guid, &isactive) == 0 && isactive &&
(zhp = zpool_open_canfail(hdl, name)) != NULL &&
zpool_get_prop_int(zhp, ZPOOL_PROP_READONLY, NULL))
stateval = POOL_STATE_ACTIVE;
(zhp = zpool_open_canfail(hdl, name)) != NULL) {
if (zpool_get_prop_int(zhp, ZPOOL_PROP_READONLY, NULL))
stateval = POOL_STATE_ACTIVE;
/*
* All we needed the zpool handle for is the
* readonly prop check.
*/
zpool_close(zhp);
}
ret = B_TRUE;
break;

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
@ -146,7 +146,8 @@ zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
zfs_handle_t *nzhp;
int ret;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT ||
zhp->zfs_type == ZFS_TYPE_BOOKMARK)
return (0);
zc.zc_simple = simple;
@ -172,6 +173,59 @@ zfs_iter_snapshots(zfs_handle_t *zhp, boolean_t simple, zfs_iter_f func,
return ((ret < 0) ? ret : 0);
}
/*
* Iterate over all bookmarks
*/
int
zfs_iter_bookmarks(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
zfs_handle_t *nzhp;
nvlist_t *props = NULL;
nvlist_t *bmarks = NULL;
int err;
if ((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT | ZFS_TYPE_BOOKMARK)) != 0)
return (0);
/* Setup the requested properties nvlist. */
props = fnvlist_alloc();
fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_GUID));
fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATETXG));
fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATION));
/* Allocate an nvlist to hold the bookmarks. */
bmarks = fnvlist_alloc();
if ((err = lzc_get_bookmarks(zhp->zfs_name, props, &bmarks)) != 0)
goto out;
for (nvpair_t *pair = nvlist_next_nvpair(bmarks, NULL);
pair != NULL; pair = nvlist_next_nvpair(bmarks, pair)) {
char name[ZFS_MAXNAMELEN];
char *bmark_name;
nvlist_t *bmark_props;
bmark_name = nvpair_name(pair);
bmark_props = fnvpair_value_nvlist(pair);
(void) snprintf(name, sizeof (name), "%s#%s", zhp->zfs_name,
bmark_name);
nzhp = make_bookmark_handle(zhp, name, bmark_props);
if (nzhp == NULL)
continue;
if ((err = func(nzhp, data)) != 0)
goto out;
}
out:
fnvlist_free(props);
fnvlist_free(bmarks);
return (err);
}
/*
* Routines for dealing with the sorted snapshot functionality
*/
@ -406,13 +460,13 @@ static int
iter_dependents_cb(zfs_handle_t *zhp, void *arg)
{
iter_dependents_arg_t *ida = arg;
int err;
int err = 0;
boolean_t first = ida->first;
ida->first = B_FALSE;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
err = zfs_iter_clones(zhp, iter_dependents_cb, ida);
} else {
} else if (zhp->zfs_type != ZFS_TYPE_BOOKMARK) {
iter_stack_frame_t isf;
iter_stack_frame_t *f;

View File

@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@ -240,7 +240,7 @@ zpool_pool_state_to_name(pool_state_t state)
*/
int
zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
zprop_source_t *srctype)
zprop_source_t *srctype, boolean_t literal)
{
uint64_t intval;
const char *strval;
@ -272,9 +272,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
(void) strlcpy(buf,
zpool_get_prop_string(zhp, prop, &src),
len);
if (srctype != NULL)
*srctype = src;
return (0);
break;
}
/* FALLTHROUGH */
default:
@ -306,12 +304,22 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
case ZPOOL_PROP_FREE:
case ZPOOL_PROP_FREEING:
case ZPOOL_PROP_EXPANDSZ:
(void) zfs_nicenum(intval, buf, len);
if (literal) {
(void) snprintf(buf, len, "%llu",
(u_longlong_t)intval);
} else {
(void) zfs_nicenum(intval, buf, len);
}
break;
case ZPOOL_PROP_CAPACITY:
(void) snprintf(buf, len, "%llu%%",
(u_longlong_t)intval);
if (literal) {
(void) snprintf(buf, len, "%llu",
(u_longlong_t)intval);
} else {
(void) snprintf(buf, len, "%llu%%",
(u_longlong_t)intval);
}
break;
case ZPOOL_PROP_DEDUPRATIO:
@ -407,7 +415,7 @@ zpool_is_bootable(zpool_handle_t *zhp)
char bootfs[ZPOOL_MAXNAMELEN];
return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
sizeof (bootfs), NULL) == 0 && strncmp(bootfs, "-",
sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-",
sizeof (bootfs)) != 0);
}
@ -443,10 +451,9 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
prop = zpool_name_to_prop(propname);
if (prop == ZPROP_INVAL && zpool_prop_feature(propname)) {
int err;
zfeature_info_t *feature;
char *fname = strchr(propname, '@') + 1;
err = zfeature_lookup_name(fname, &feature);
err = zfeature_lookup_name(fname, NULL);
if (err != 0) {
ASSERT3U(err, ==, ENOENT);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@ -807,7 +814,7 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
if (entry->pl_prop != ZPROP_INVAL &&
zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
NULL) == 0) {
NULL, B_FALSE) == 0) {
if (strlen(buf) > entry->pl_width)
entry->pl_width = strlen(buf);
}
@ -839,14 +846,14 @@ zpool_prop_get_feature(zpool_handle_t *zhp, const char *propname, char *buf,
*/
if (supported) {
int ret;
zfeature_info_t *fi;
spa_feature_t fid;
ret = zfeature_lookup_name(feature, &fi);
ret = zfeature_lookup_name(feature, &fid);
if (ret != 0) {
(void) strlcpy(buf, "-", len);
return (ENOTSUP);
}
feature = fi->fi_guid;
feature = spa_feature_table[fid].fi_guid;
}
if (nvlist_lookup_uint64(features, feature, &refcount) == 0)
@ -3737,7 +3744,9 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
return (0);
}
#define HIS_BUF_LEN (128*1024)
/* from spa_history.c: spa_history_create_obj() */
#define HIS_BUF_LEN_DEF (128 << 10)
#define HIS_BUF_LEN_MAX (1 << 30)
/*
* Retrieve the command history of a pool.
@ -3745,21 +3754,24 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
int
zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
{
char buf[HIS_BUF_LEN];
char *buf = NULL;
uint64_t bufsize = HIS_BUF_LEN_DEF;
uint64_t off = 0;
nvlist_t **records = NULL;
uint_t numrecords = 0;
int err, i;
if ((buf = malloc(bufsize)) == NULL)
return (ENOMEM);
do {
uint64_t bytes_read = sizeof (buf);
uint64_t bytes_read = bufsize;
uint64_t leftover;
if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
break;
/* if nothing else was read in, we're at EOF, just return */
if (!bytes_read)
if (bytes_read == 0)
break;
if ((err = zpool_history_unpack(buf, bytes_read,
@ -3767,8 +3779,25 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
break;
off -= leftover;
/*
* If the history block is too big, double the buffer
* size and try again.
*/
if (leftover == bytes_read) {
free(buf);
buf = NULL;
bufsize <<= 1;
if ((bufsize >= HIS_BUF_LEN_MAX) ||
((buf = malloc(bufsize)) == NULL)) {
err = ENOMEM;
break;
}
}
/* CONSTCOND */
} while (1);
free(buf);
if (!err) {
verify(nvlist_alloc(nvhisp, NV_UNIQUE_NAME, 0) == 0);

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
@ -1619,6 +1619,62 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
return (err);
}
int
zfs_send_one(zfs_handle_t *zhp, const char *from, int fd)
{
int err;
libzfs_handle_t *hdl = zhp->zfs_hdl;
char errbuf[1024];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"warning: cannot send '%s'"), zhp->zfs_name);
err = lzc_send(zhp->zfs_name, from, fd);
if (err != 0) {
switch (errno) {
case EXDEV:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"not an earlier snapshot from the same fs"));
return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
case ENOENT:
case ESRCH:
if (lzc_exists(zhp->zfs_name)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"incremental source (%s) does not exist"),
from);
}
return (zfs_error(hdl, EZFS_NOENT, errbuf));
case EBUSY:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"target is busy; if a filesystem, "
"it must not be mounted"));
return (zfs_error(hdl, EZFS_BUSY, errbuf));
case EDQUOT:
case EFBIG:
case EIO:
case ENOLINK:
case ENOSPC:
#ifdef illumos
case ENOSTR:
#endif
case ENXIO:
case EPIPE:
case ERANGE:
case EFAULT:
case EROFS:
zfs_error_aux(hdl, strerror(errno));
return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
default:
return (zfs_standard_error(hdl, errno, errbuf));
}
}
return (err != 0);
}
/*
* Routines specific to "zfs recv"
*/

View File

@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@ -1268,6 +1269,16 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
"use 'none' to disable quota/refquota"));
goto error;
}
/*
* Special handling for "*_limit=none". In this case it's not
* 0 but UINT64_MAX.
*/
if ((type & ZFS_TYPE_DATASET) && isnone &&
(prop == ZFS_PROP_FILESYSTEM_LIMIT ||
prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
*ivalp = UINT64_MAX;
}
break;
case PROP_TYPE_INDEX:

View File

@ -486,18 +486,30 @@ lzc_get_holds(const char *snapname, nvlist_t **holdsp)
}
/*
* If fromsnap is NULL, a full (non-incremental) stream will be sent.
*
* "snapname" is the full name of the snapshot to send (e.g. "pool/fs@snap")
*
* If "from" is NULL, a full (non-incremental) stream will be sent.
* If "from" is non-NULL, it must be the full name of a snapshot or
* bookmark to send an incremental from (e.g. "pool/fs@earlier_snap" or
* "pool/fs#earlier_bmark"). If non-NULL, the specified snapshot or
* bookmark must represent an earlier point in the history of "snapname").
* It can be an earlier snapshot in the same filesystem or zvol as "snapname",
* or it can be the origin of "snapname"'s filesystem, or an earlier
* snapshot in the origin, etc.
*
* "fd" is the file descriptor to write the send stream to.
*/
int
lzc_send(const char *snapname, const char *fromsnap, int fd)
lzc_send(const char *snapname, const char *from, int fd)
{
nvlist_t *args;
int err;
args = fnvlist_alloc();
fnvlist_add_int32(args, "fd", fd);
if (fromsnap != NULL)
fnvlist_add_string(args, "fromsnap", fromsnap);
if (from != NULL)
fnvlist_add_string(args, "fromsnap", from);
err = lzc_ioctl(ZFS_IOC_SEND_NEW, snapname, args, NULL);
nvlist_free(args);
return (err);
@ -652,3 +664,97 @@ lzc_rollback(const char *fsname, char *snapnamebuf, int snapnamelen)
}
return (err);
}
/*
* Creates bookmarks.
*
* The bookmarks nvlist maps from name of the bookmark (e.g. "pool/fs#bmark") to
* the name of the snapshot (e.g. "pool/fs@snap"). All the bookmarks and
* snapshots must be in the same pool.
*
* The returned results nvlist will have an entry for each bookmark that failed.
* The value will be the (int32) error code.
*
* The return value will be 0 if all bookmarks were created, otherwise it will
* be the errno of a (undetermined) bookmarks that failed.
*/
int
lzc_bookmark(nvlist_t *bookmarks, nvlist_t **errlist)
{
nvpair_t *elem;
int error;
char pool[MAXNAMELEN];
/* determine the pool name */
elem = nvlist_next_nvpair(bookmarks, NULL);
if (elem == NULL)
return (0);
(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
pool[strcspn(pool, "/#")] = '\0';
error = lzc_ioctl(ZFS_IOC_BOOKMARK, pool, bookmarks, errlist);
return (error);
}
/*
* Retrieve bookmarks.
*
* Retrieve the list of bookmarks for the given file system. The props
* parameter is an nvlist of property names (with no values) that will be
* returned for each bookmark.
*
* The following are valid properties on bookmarks, all of which are numbers
* (represented as uint64 in the nvlist)
*
* "guid" - globally unique identifier of the snapshot it refers to
* "createtxg" - txg when the snapshot it refers to was created
* "creation" - timestamp when the snapshot it refers to was created
*
* The format of the returned nvlist as follows:
* <short name of bookmark> -> {
* <name of property> -> {
* "value" -> uint64
* }
* }
*/
int
lzc_get_bookmarks(const char *fsname, nvlist_t *props, nvlist_t **bmarks)
{
return (lzc_ioctl(ZFS_IOC_GET_BOOKMARKS, fsname, props, bmarks));
}
/*
* Destroys bookmarks.
*
* The keys in the bmarks nvlist are the bookmarks to be destroyed.
* They must all be in the same pool. Bookmarks are specified as
* <fs>#<bmark>.
*
* Bookmarks that do not exist will be silently ignored.
*
* The return value will be 0 if all bookmarks that existed were destroyed.
*
* Otherwise the return value will be the errno of a (undetermined) bookmark
* that failed, no bookmarks will be destroyed, and the errlist will have an
* entry for each bookmarks that failed. The value in the errlist will be
* the (int32) error code.
*/
int
lzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **errlist)
{
nvpair_t *elem;
int error;
char pool[MAXNAMELEN];
/* determine the pool name */
elem = nvlist_next_nvpair(bmarks, NULL);
if (elem == NULL)
return (0);
(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
pool[strcspn(pool, "/#")] = '\0';
error = lzc_ioctl(ZFS_IOC_DESTROY_BOOKMARKS, pool, bmarks, errlist);
return (error);
}

View File

@ -39,27 +39,27 @@ extern "C" {
int libzfs_core_init(void);
void libzfs_core_fini(void);
int lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist);
int lzc_create(const char *fsname, dmu_objset_type_t type, nvlist_t *props);
int lzc_clone(const char *fsname, const char *origin, nvlist_t *props);
int lzc_destroy_snaps(nvlist_t *snaps, boolean_t defer, nvlist_t **errlist);
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
int lzc_create(const char *, dmu_objset_type_t, nvlist_t *);
int lzc_clone(const char *, const char *, nvlist_t *);
int lzc_destroy_snaps(nvlist_t *, boolean_t, nvlist_t **);
int lzc_bookmark(nvlist_t *, nvlist_t **);
int lzc_get_bookmarks(const char *, nvlist_t *, nvlist_t **);
int lzc_destroy_bookmarks(nvlist_t *, nvlist_t **);
int lzc_snaprange_space(const char *firstsnap, const char *lastsnap,
uint64_t *usedp);
int lzc_snaprange_space(const char *, const char *, uint64_t *);
int lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist);
int lzc_release(nvlist_t *holds, nvlist_t **errlist);
int lzc_get_holds(const char *snapname, nvlist_t **holdsp);
int lzc_hold(nvlist_t *, int, nvlist_t **);
int lzc_release(nvlist_t *, nvlist_t **);
int lzc_get_holds(const char *, nvlist_t **);
int lzc_send(const char *snapname, const char *fromsnap, int fd);
int lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, int fd);
int lzc_send_space(const char *snapname, const char *fromsnap,
uint64_t *result);
int lzc_send(const char *, const char *, int);
int lzc_receive(const char *, nvlist_t *, const char *, boolean_t, int);
int lzc_send_space(const char *, const char *, uint64_t *);
boolean_t lzc_exists(const char *dataset);
boolean_t lzc_exists(const char *);
int lzc_rollback(const char *fsname, char *snapnamebuf, int snapnamelen);
int lzc_rollback(const char *, char *, int);
#ifdef __cplusplus
}

View File

@ -20,6 +20,8 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <assert.h>
@ -661,7 +663,7 @@ __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
if (dprintf_find_string("pid"))
(void) printf("%d ", getpid());
if (dprintf_find_string("tid"))
(void) printf("%u ", thr_self());
(void) printf("%ul ", thr_self());
#if 0
if (dprintf_find_string("cpu"))
(void) printf("%u ", getcpuid());
@ -800,20 +802,17 @@ delay(clock_t ticks)
/*
* Find highest one bit set.
* Returns bit number + 1 of highest bit that is set, otherwise returns 0.
* High order bit is 31 (or 63 in _LP64 kernel).
*/
int
highbit(ulong_t i)
highbit64(uint64_t i)
{
register int h = 1;
int h = 1;
if (i == 0)
return (0);
#ifdef _LP64
if (i & 0xffffffff00000000ul) {
if (i & 0xffffffff00000000ULL) {
h += 32; i >>= 32;
}
#endif
if (i & 0xffff0000) {
h += 16; i >>= 16;
}
@ -1125,3 +1124,50 @@ zvol_create_minors(const char *name)
return (0);
}
#endif
#ifdef illumos
void
bioinit(buf_t *bp)
{
bzero(bp, sizeof (buf_t));
}
void
biodone(buf_t *bp)
{
if (bp->b_iodone != NULL) {
(*(bp->b_iodone))(bp);
return;
}
ASSERT((bp->b_flags & B_DONE) == 0);
bp->b_flags |= B_DONE;
}
void
bioerror(buf_t *bp, int error)
{
ASSERT(bp != NULL);
ASSERT(error >= 0);
if (error != 0) {
bp->b_flags |= B_ERROR;
} else {
bp->b_flags &= ~B_ERROR;
}
bp->b_error = error;
}
int
geterror(struct buf *bp)
{
int error = 0;
if (bp->b_flags & B_ERROR) {
error = bp->b_error;
if (!error)
error = EIO;
}
return (error);
}
#endif

View File

@ -20,9 +20,12 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_ZFS_CONTEXT_H
#define _SYS_ZFS_CONTEXT_H
@ -62,6 +65,7 @@ extern "C" {
#include <inttypes.h>
#include <fsshare.h>
#include <pthread.h>
#include <sched.h>
#include <sys/debug.h>
#include <sys/note.h>
#include <sys/types.h>
@ -201,6 +205,8 @@ extern int aok;
*/
#define curthread ((void *)(uintptr_t)thr_self())
#define kpreempt(x) sched_yield()
typedef struct kthread kthread_t;
#define thread_create(stk, stksize, func, arg, len, pp, state, pri) \
@ -367,6 +373,16 @@ typedef struct taskq taskq_t;
typedef uintptr_t taskqid_t;
typedef void (task_func_t)(void *);
typedef struct taskq_ent {
struct taskq_ent *tqent_next;
struct taskq_ent *tqent_prev;
task_func_t *tqent_func;
void *tqent_arg;
uintptr_t tqent_flags;
} taskq_ent_t;
#define TQENT_FLAG_PREALLOC 0x1 /* taskq_dispatch_ent used */
#define TASKQ_PREPOPULATE 0x0001
#define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
@ -378,6 +394,7 @@ typedef void (task_func_t)(void *);
#define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */
#define TQ_FRONT 0x08 /* Queue in front */
extern taskq_t *system_taskq;
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
@ -386,6 +403,8 @@ extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
#define taskq_create_sysdc(a, b, d, e, p, dc, f) \
(taskq_create(a, b, maxclsyspri, d, e, f))
extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
taskq_ent_t *);
extern void taskq_destroy(taskq_t *);
extern void taskq_wait(taskq_t *);
extern int taskq_member(taskq_t *, void *);
@ -539,7 +558,7 @@ extern void delay(clock_t ticks);
extern uint64_t physmem;
extern int highbit(ulong_t i);
extern int highbit64(uint64_t i);
extern int random_get_bytes(uint8_t *ptr, size_t len);
extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len);
@ -759,6 +778,38 @@ extern void cyclic_remove(cyclic_id_t);
extern int cyclic_reprogram(cyclic_id_t, hrtime_t);
#endif /* illumos */
#ifdef illumos
/*
* Buf structure
*/
#define B_BUSY 0x0001
#define B_DONE 0x0002
#define B_ERROR 0x0004
#define B_READ 0x0040 /* read when I/O occurs */
#define B_WRITE 0x0100 /* non-read pseudo-flag */
typedef struct buf {
int b_flags;
size_t b_bcount;
union {
caddr_t b_addr;
} b_un;
lldaddr_t _b_blkno;
#define b_lblkno _b_blkno._f
size_t b_resid;
size_t b_bufsize;
int (*b_iodone)(struct buf *);
int b_error;
void *b_private;
} buf_t;
extern void bioinit(buf_t *);
extern void biodone(buf_t *);
extern void bioerror(buf_t *, int);
extern int geterror(buf_t *);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -22,19 +22,15 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/zfs_context.h>
int taskq_now;
taskq_t *system_taskq;
typedef struct task {
struct task *task_next;
struct task *task_prev;
task_func_t *task_func;
void *task_arg;
} task_t;
#define TASKQ_ACTIVE 0x00010000
struct taskq {
@ -51,18 +47,18 @@ struct taskq {
int tq_maxalloc;
kcondvar_t tq_maxalloc_cv;
int tq_maxalloc_wait;
task_t *tq_freelist;
task_t tq_task;
taskq_ent_t *tq_freelist;
taskq_ent_t tq_task;
};
static task_t *
static taskq_ent_t *
task_alloc(taskq_t *tq, int tqflags)
{
task_t *t;
taskq_ent_t *t;
int rv;
again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
tq->tq_freelist = t->task_next;
tq->tq_freelist = t->tqent_next;
} else {
if (tq->tq_nalloc >= tq->tq_maxalloc) {
if (!(tqflags & KM_SLEEP))
@ -87,7 +83,7 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
}
mutex_exit(&tq->tq_lock);
t = kmem_alloc(sizeof (task_t), tqflags & KM_SLEEP);
t = kmem_alloc(sizeof (taskq_ent_t), tqflags & KM_SLEEP);
mutex_enter(&tq->tq_lock);
if (t != NULL)
@ -97,15 +93,15 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
}
static void
task_free(taskq_t *tq, task_t *t)
task_free(taskq_t *tq, taskq_ent_t *t)
{
if (tq->tq_nalloc <= tq->tq_minalloc) {
t->task_next = tq->tq_freelist;
t->tqent_next = tq->tq_freelist;
tq->tq_freelist = t;
} else {
tq->tq_nalloc--;
mutex_exit(&tq->tq_lock);
kmem_free(t, sizeof (task_t));
kmem_free(t, sizeof (taskq_ent_t));
mutex_enter(&tq->tq_lock);
}
@ -116,7 +112,7 @@ task_free(taskq_t *tq, task_t *t)
taskqid_t
taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
{
task_t *t;
taskq_ent_t *t;
if (taskq_now) {
func(arg);
@ -130,26 +126,58 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
return (0);
}
if (tqflags & TQ_FRONT) {
t->task_next = tq->tq_task.task_next;
t->task_prev = &tq->tq_task;
t->tqent_next = tq->tq_task.tqent_next;
t->tqent_prev = &tq->tq_task;
} else {
t->task_next = &tq->tq_task;
t->task_prev = tq->tq_task.task_prev;
t->tqent_next = &tq->tq_task;
t->tqent_prev = tq->tq_task.tqent_prev;
}
t->task_next->task_prev = t;
t->task_prev->task_next = t;
t->task_func = func;
t->task_arg = arg;
t->tqent_next->tqent_prev = t;
t->tqent_prev->tqent_next = t;
t->tqent_func = func;
t->tqent_arg = arg;
cv_signal(&tq->tq_dispatch_cv);
mutex_exit(&tq->tq_lock);
return (1);
}
void
taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
taskq_ent_t *t)
{
ASSERT(func != NULL);
ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC));
/*
* Mark it as a prealloc'd task. This is important
* to ensure that we don't free it later.
*/
t->tqent_flags |= TQENT_FLAG_PREALLOC;
/*
* Enqueue the task to the underlying queue.
*/
mutex_enter(&tq->tq_lock);
if (flags & TQ_FRONT) {
t->tqent_next = tq->tq_task.tqent_next;
t->tqent_prev = &tq->tq_task;
} else {
t->tqent_next = &tq->tq_task;
t->tqent_prev = tq->tq_task.tqent_prev;
}
t->tqent_next->tqent_prev = t;
t->tqent_prev->tqent_next = t;
t->tqent_func = func;
t->tqent_arg = arg;
cv_signal(&tq->tq_dispatch_cv);
mutex_exit(&tq->tq_lock);
}
void
taskq_wait(taskq_t *tq)
{
mutex_enter(&tq->tq_lock);
while (tq->tq_task.task_next != &tq->tq_task || tq->tq_active != 0)
while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
mutex_exit(&tq->tq_lock);
}
@ -158,27 +186,32 @@ static void *
taskq_thread(void *arg)
{
taskq_t *tq = arg;
task_t *t;
taskq_ent_t *t;
boolean_t prealloc;
mutex_enter(&tq->tq_lock);
while (tq->tq_flags & TASKQ_ACTIVE) {
if ((t = tq->tq_task.task_next) == &tq->tq_task) {
if ((t = tq->tq_task.tqent_next) == &tq->tq_task) {
if (--tq->tq_active == 0)
cv_broadcast(&tq->tq_wait_cv);
cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock);
tq->tq_active++;
continue;
}
t->task_prev->task_next = t->task_next;
t->task_next->task_prev = t->task_prev;
t->tqent_prev->tqent_next = t->tqent_next;
t->tqent_next->tqent_prev = t->tqent_prev;
t->tqent_next = NULL;
t->tqent_prev = NULL;
prealloc = t->tqent_flags & TQENT_FLAG_PREALLOC;
mutex_exit(&tq->tq_lock);
rw_enter(&tq->tq_threadlock, RW_READER);
t->task_func(t->task_arg);
t->tqent_func(t->tqent_arg);
rw_exit(&tq->tq_threadlock);
mutex_enter(&tq->tq_lock);
task_free(tq, t);
if (!prealloc)
task_free(tq, t);
}
tq->tq_nthreads--;
cv_broadcast(&tq->tq_wait_cv);
@ -217,8 +250,8 @@ taskq_create(const char *name, int nthreads, pri_t pri,
tq->tq_nthreads = nthreads;
tq->tq_minalloc = minalloc;
tq->tq_maxalloc = maxalloc;
tq->tq_task.task_next = &tq->tq_task;
tq->tq_task.task_prev = &tq->tq_task;
tq->tq_task.tqent_next = &tq->tq_task;
tq->tq_task.tqent_prev = &tq->tq_task;
tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP);
if (flags & TASKQ_PREPOPULATE) {

View File

@ -20,6 +20,7 @@
# CDDL HEADER END
#
# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2013 by Delphix. All rights reserved.
#
"""This module implements the "zfs allow" and "zfs unallow" subcommands.
@ -219,6 +220,7 @@ def decodeid(w, toidfunc, fmt):
hold=_("Allows adding a user hold to a snapshot"),
release=_("Allows releasing a user hold which\n\t\t\t\tmight destroy the snapshot"),
diff=_("Allows lookup of paths within a dataset,\n\t\t\t\tgiven an object number. Ordinary users need this\n\t\t\t\tin order to use zfs diff"),
bookmark="",
)
perms_other = dict(

View File

@ -96,9 +96,6 @@
#include "list.h"
#include "traverse.h"
/* The version of DWARF which we support. */
#define DWARF_VERSION 2
/*
* We need to define a couple of our own intrinsics, to smooth out some of the
* differences between the GCC and DevPro DWARF emitters. See the referenced
@ -271,7 +268,7 @@ die_off(dwarf_t *dw, Dwarf_Die die)
return (off);
terminate("failed to get offset for die: %s\n",
dwarf_errmsg(&dw->dw_err));
dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/
return (0);
}
@ -289,7 +286,7 @@ die_sibling(dwarf_t *dw, Dwarf_Die die)
return (NULL);
terminate("die %llu: failed to find type sibling: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/
return (NULL);
}
@ -306,7 +303,7 @@ die_child(dwarf_t *dw, Dwarf_Die die)
return (NULL);
terminate("die %llu: failed to find type child: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/
return (NULL);
}
@ -320,7 +317,7 @@ die_tag(dwarf_t *dw, Dwarf_Die die)
return (tag);
terminate("die %llu: failed to get tag for type: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/
return (0);
}
@ -343,7 +340,7 @@ die_attr(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, int req)
}
terminate("die %llu: failed to get attribute for type: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
/*NOTREACHED*/
return (NULL);
}
@ -353,10 +350,10 @@ die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp,
int req)
{
*valp = 0;
if (dwarf_attrval_signed(die, name, valp, &dw->dw_err) != DWARF_E_NONE) {
if (dwarf_attrval_signed(die, name, valp, &dw->dw_err) != DW_DLV_OK) {
if (req)
terminate("die %llu: failed to get signed: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
return (0);
}
@ -368,10 +365,10 @@ die_unsigned(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp,
int req)
{
*valp = 0;
if (dwarf_attrval_unsigned(die, name, valp, &dw->dw_err) != DWARF_E_NONE) {
if (dwarf_attrval_unsigned(die, name, valp, &dw->dw_err) != DW_DLV_OK) {
if (req)
terminate("die %llu: failed to get unsigned: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
return (0);
}
@ -383,10 +380,10 @@ die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req)
{
*valp = 0;
if (dwarf_attrval_flag(die, name, valp, &dw->dw_err) != DWARF_E_NONE) {
if (dwarf_attrval_flag(die, name, valp, &dw->dw_err) != DW_DLV_OK) {
if (req)
terminate("die %llu: failed to get flag: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
return (0);
}
@ -398,11 +395,11 @@ die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req)
{
const char *str = NULL;
if (dwarf_attrval_string(die, name, &str, &dw->dw_err) != DWARF_E_NONE ||
if (dwarf_attrval_string(die, name, &str, &dw->dw_err) != DW_DLV_OK ||
str == NULL) {
if (req)
terminate("die %llu: failed to get string: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
else
*strp = NULL;
return (0);
@ -417,9 +414,9 @@ die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name)
{
Dwarf_Off off;
if (dwarf_attrval_unsigned(die, name, &off, &dw->dw_err) != DWARF_E_NONE) {
if (dwarf_attrval_unsigned(die, name, &off, &dw->dw_err) != DW_DLV_OK) {
terminate("die %llu: failed to get ref: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
die_off(dw, die), dwarf_errmsg(dw->dw_err));
}
return (off);
@ -431,6 +428,8 @@ die_name(dwarf_t *dw, Dwarf_Die die)
char *str = NULL;
(void) die_string(dw, die, DW_AT_name, &str, 0);
if (str == NULL)
str = xstrdup("");
return (str);
}
@ -489,22 +488,74 @@ die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name,
{
Dwarf_Locdesc *loc = NULL;
Dwarf_Signed locnum = 0;
Dwarf_Attribute at;
Dwarf_Half form;
if (dwarf_locdesc(die, name, &loc, &locnum, &dw->dw_err) != DW_DLV_OK)
if (name != DW_AT_data_member_location)
terminate("die %llu: can only process attribute "
"DW_AT_data_member_location\n", die_off(dw, die));
if ((at = die_attr(dw, die, name, 0)) == NULL)
return (0);
if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) {
terminate("die %llu: cannot parse member offset\n",
die_off(dw, die));
if (dwarf_whatform(at, &form, &dw->dw_err) != DW_DLV_OK)
return (0);
switch (form) {
case DW_FORM_sec_offset:
case DW_FORM_block:
case DW_FORM_block1:
case DW_FORM_block2:
case DW_FORM_block4:
/*
* GCC in base and Clang (3.3 or below) generates
* DW_AT_data_member_location attribute with DW_FORM_block*
* form. The attribute contains one DW_OP_plus_uconst
* operator. The member offset stores in the operand.
*/
if (dwarf_loclist(at, &loc, &locnum, &dw->dw_err) != DW_DLV_OK)
return (0);
if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) {
terminate("die %llu: cannot parse member offset with "
"operator other than DW_OP_plus_uconst\n",
die_off(dw, die));
}
*valp = loc->ld_s->lr_number;
if (loc != NULL) {
dwarf_dealloc(dw->dw_dw, loc->ld_s, DW_DLA_LOC_BLOCK);
dwarf_dealloc(dw->dw_dw, loc, DW_DLA_LOCDESC);
}
break;
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
case DW_FORM_data8:
case DW_FORM_udata:
/*
* Clang 3.4 generates DW_AT_data_member_location attribute
* with DW_FORM_data* form (constant class). The attribute
* stores a contant value which is the member offset.
*
* However, note that DW_FORM_data[48] in DWARF version 2 or 3
* could be used as a section offset (offset into .debug_loc in
* this case). Here we assume the attribute always stores a
* constant because we know Clang 3.4 does this and GCC in
* base won't emit DW_FORM_data[48] for this attribute. This
* code will remain correct if future vesrions of Clang and
* GCC conform to DWARF4 standard and only use the form
* DW_FORM_sec_offset for section offset.
*/
if (dwarf_attrval_unsigned(die, name, valp, &dw->dw_err) !=
DW_DLV_OK)
return (0);
break;
default:
terminate("die %llu: cannot parse member offset with form "
"%u\n", die_off(dw, die), form);
}
*valp = loc->ld_s->lr_number;
if (loc != NULL)
if (dwarf_locdesc_free(loc, &dw->dw_err) != DW_DLV_OK)
terminate("die %llu: cannot free location descriptor: %s\n",
die_off(dw, die), dwarf_errmsg(&dw->dw_err));
return (1);
}
@ -885,6 +936,9 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
int type, const char *typename)
{
Dwarf_Unsigned sz, bitsz, bitoff, maxsz=0;
#if BYTE_ORDER == _LITTLE_ENDIAN
Dwarf_Unsigned bysz;
#endif
Dwarf_Die mem;
mlist_t *ml, **mlastp;
iidesc_t *ii;
@ -959,8 +1013,26 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp,
#if BYTE_ORDER == _BIG_ENDIAN
ml->ml_offset += bitoff;
#else
ml->ml_offset += tdesc_bitsize(ml->ml_type) - bitoff -
ml->ml_size;
/*
* Note that Clang 3.4 will sometimes generate
* member DIE before generating the DIE for the
* member's type. The code can not handle this
* properly so that tdesc_bitsize(ml->ml_type) will
* return 0 because ml->ml_type is unknown. As a
* result, a wrong member offset will be calculated.
* To workaround this, we can instead try to
* retrieve the value of DW_AT_byte_size attribute
* which stores the byte size of the space occupied
* by the type. If this attribute exists, its value
* should equal to tdesc_bitsize(ml->ml_type)/NBBY.
*/
if (die_unsigned(dw, mem, DW_AT_byte_size, &bysz, 0) &&
bysz > 0)
ml->ml_offset += bysz * NBBY - bitoff -
ml->ml_size;
else
ml->ml_offset += tdesc_bitsize(ml->ml_type) -
bitoff - ml->ml_size;
#endif
}
@ -1852,7 +1924,7 @@ int
dw_read(tdata_t *td, Elf *elf, char *filename __unused)
{
Dwarf_Unsigned abboff, hdrlen, nxthdr;
Dwarf_Half vers, addrsz;
Dwarf_Half vers, addrsz, offsz;
Dwarf_Die cu = 0;
Dwarf_Die child = 0;
dwarf_t dw;
@ -1869,7 +1941,7 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
dw.dw_enumhash = hash_new(TDESC_HASH_BUCKETS, tdesc_namehash,
tdesc_namecmp);
if ((rc = dwarf_elf_init(elf, DW_DLC_READ, &dw.dw_dw,
if ((rc = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dw.dw_dw,
&dw.dw_err)) == DW_DLV_NO_ENTRY) {
if (should_have_dwarf(elf)) {
errno = ENOENT;
@ -1878,7 +1950,7 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
return (0);
}
} else if (rc != DW_DLV_OK) {
if (dwarf_errno(&dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) {
if (dwarf_errno(dw.dw_err) == DW_DLE_DEBUG_INFO_NULL) {
/*
* There's no type data in the DWARF section, but
* libdwarf is too clever to handle that properly.
@ -1887,12 +1959,12 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
}
terminate("failed to initialize DWARF: %s\n",
dwarf_errmsg(&dw.dw_err));
dwarf_errmsg(dw.dw_err));
}
if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff,
&addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_OK)
terminate("rc = %d %s\n", rc, dwarf_errmsg(&dw.dw_err));
if ((rc = dwarf_next_cu_header_b(dw.dw_dw, &hdrlen, &vers, &abboff,
&addrsz, &offsz, NULL, &nxthdr, &dw.dw_err)) != DW_DLV_OK)
terminate("rc = %d %s\n", rc, dwarf_errmsg(dw.dw_err));
if ((cu = die_sibling(&dw, NULL)) == NULL ||
(((child = die_child(&dw, cu)) == NULL) &&
@ -1909,9 +1981,9 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
terminate("file contains too many types\n");
debug(1, "DWARF version: %d\n", vers);
if (vers != DWARF_VERSION) {
if (vers < 2 || vers > 4) {
terminate("file contains incompatible version %d DWARF code "
"(version 2 required)\n", vers);
"(version 2, 3 or 4 required)\n", vers);
}
if (die_string(&dw, cu, DW_AT_producer, &prod, 0)) {
@ -1930,11 +2002,11 @@ dw_read(tdata_t *td, Elf *elf, char *filename __unused)
if ((child = die_child(&dw, cu)) != NULL)
die_create(&dw, child);
if ((rc = dwarf_next_cu_header(dw.dw_dw, &hdrlen, &vers, &abboff,
&addrsz, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY)
if ((rc = dwarf_next_cu_header_b(dw.dw_dw, &hdrlen, &vers, &abboff,
&addrsz, &offsz, NULL, &nxthdr, &dw.dw_err)) != DW_DLV_NO_ENTRY)
terminate("multiple compilation units not supported\n");
(void) dwarf_finish(&dw.dw_dw, &dw.dw_err);
(void) dwarf_finish(dw.dw_dw, &dw.dw_err);
die_resolve(&dw);

View File

@ -11,7 +11,12 @@ SUBDIR= ${_drti} \
libuutil \
${_libzfs_core} \
${_libzfs} \
${_libzpool}
${_libzpool} \
${_tests}
.if ${MK_TESTS} != "no"
_tests= tests
.endif
.if ${MK_ZFS} != "no"
_libzfs_core= libzfs_core

View File

@ -27,5 +27,8 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris \
-I${OPENSOLARIS_USR_DISTDIR}/lib/libctf/common \
-I${OPENSOLARIS_SYS_DISTDIR}/uts/common
DPADD= ${LIBZ}
LDADD= -lz
.include <bsd.lib.mk>

View File

@ -69,9 +69,11 @@ CFLAGS+= -I${.OBJDIR} -I${.CURDIR} \
#CFLAGS+= -DYYDEBUG
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/dev/dtrace/x86
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel -DDIS_MEM
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/i386
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/${MACHINE_ARCH}
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/x86
.elif ${MACHINE_CPUARCH} == "sparc64"
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/sparc

View File

@ -57,7 +57,8 @@ translator psinfo_t < struct proc *T > {
pr_gid = T->p_ucred->cr_rgid;
pr_egid = T->p_ucred->cr_groups[0];
pr_addr = 0;
pr_psargs = stringof(T->p_args->ar_args);
pr_psargs = (T->p_args->ar_args == 0) ? "" :
memstr(T->p_args->ar_args, ' ', T->p_args->ar_length);
pr_arglen = T->p_args->ar_length;
pr_jailid = T->p_ucred->cr_prison->pr_id;
};

View File

@ -21,4 +21,13 @@ CFLAGS+= -I${.CURDIR}/../../../sys
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem
# This library uses macros to define fprintf behavior for several object types
# The compiler will see the non-string literal arguments to the fprintf calls and
# omit warnings for them. Quiesce these warnings in contrib code:
#
# cddl/contrib/opensolaris/lib/libnvpair/libnvpair.c:743:12: warning: format
# string is not a string literal (potentially insecure) [-Wformat-security]
# ARENDER(pctl, nvlist_array, nvl, name, val, nelem);
#
CFLAGS+= -Wno-format-security
.include <bsd.lib.mk>

View File

@ -60,7 +60,7 @@ DPADD= ${LIBMD} ${LIBPTHREAD} ${LIBZ}
LDADD= -lmd -lpthread -lz
# atomic.S doesn't like profiling.
NO_PROFILE=
MK_PROFILE= no
CSTD= c99

10
cddl/lib/tests/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $FreeBSD$
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/cddl/lib
.PATH: ${.CURDIR:H:H:H}/tests
KYUAFILE= yes
.include <bsd.test.mk>

View File

@ -2,7 +2,11 @@
.include <bsd.own.mk>
SUBDIR= ${_zfs} ${_zpool}
SUBDIR= ${_tests} ${_zfs} ${_zpool}
.if ${MK_TESTS} != "no"
_tests= tests
.endif
.if ${MK_ZFS} != "no"
_zfs= zfs

10
cddl/sbin/tests/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $FreeBSD$
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/cddl/sbin
.PATH: ${.CURDIR:H:H:H}/tests
KYUAFILE= yes
.include <bsd.test.mk>

10
cddl/tests/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $FreeBSD$
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/cddl
.PATH: ${.CURDIR:H:H}/tests
KYUAFILE= yes
.include <bsd.test.mk>

View File

@ -7,11 +7,16 @@ SUBDIR= \
ctfdump \
ctfmerge \
sgsmsg \
${_tests} \
${_zinject} \
${_zlook} \
${_zstreamdump} \
${_ztest}
.if ${MK_TESTS} != "no"
_tests= tests
.endif
.if ${MK_ZFS} != "no"
_zinject= zinject
#_zlook= zlook

View File

@ -5,7 +5,7 @@
# This program is required as a bootstrap tool for 'make buildworld'
PROG= sgsmsg
NO_MAN=
MAN=
SRCS= avl.c sgsmsg.c string_table.c findprime.c
WARNS?= 0

View File

@ -0,0 +1,10 @@
# $FreeBSD$
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/cddl/usr.bin
.PATH: ${.CURDIR:H:H:H}/tests
KYUAFILE= yes
.include <bsd.test.mk>

View File

@ -4,7 +4,7 @@
PROG= zinject
SRCS= zinject.c translate.c
NO_MAN=
MAN=
WARNS?= 0
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
@ -16,6 +16,7 @@ CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/lib/libnvpair
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs/
CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/head
CFLAGS+= -I${.CURDIR}/../../lib/libumem

View File

@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../contrib/opensolaris/cmd/zlook
PROG= zlook
NO_MAN=
MAN=
WARNS?= 0
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris

View File

@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../..//contrib/opensolaris/cmd/ztest
PROG= ztest
NO_MAN=
MAN=
WARNS?= 0
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris

View File

@ -5,9 +5,14 @@
SUBDIR= ${_dtrace} \
${_dtruss} \
${_lockstat} \
${_tests} \
${_zdb} \
${_zhack}
.if ${MK_TESTS} != "no"
_tests= tests
.endif
.if ${MK_ZFS} != "no"
.if ${MK_LIBTHR} != "no"
_zdb= zdb

View File

@ -3,7 +3,6 @@
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/lockstat
PROG= lockstat
NO_MAN=
SRCS= lockstat.c sym.c
BINDIR?= /usr/sbin

View File

@ -0,0 +1,10 @@
# $FreeBSD$
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/cddl/usr.sbin
.PATH: ${.CURDIR:H:H:H}/tests
KYUAFILE= yes
.include <bsd.test.mk>

View File

@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/zhack
PROG= zhack
NO_MAN=
MAN=
WARNS?= 0
CSTD= c99

View File

@ -32,8 +32,13 @@
SUBDIR_ORDERED= ${_csu} \
libc \
libc_nonshared \
libbsm \
libauditd \
libutil \
libpjdlog \
libnv \
${_libcapsicum} \
libcompiler_rt \
libcrypt \
libelf \
@ -48,7 +53,6 @@ SUBDIR_ORDERED= ${_csu} \
librpcsvc \
libsbuf \
libtacplus \
libutil \
${_libypclnt} \
${_libcxxrt} \
${_libcplusplus}
@ -65,9 +69,11 @@ SUBDIR= ${SUBDIR_ORDERED} \
libblocksruntime \
${_libbluetooth} \
${_libbsnmp} \
libbsdstat \
libbz2 \
libcalendar \
libcam \
${_libcasper} \
libcompat \
libdevinfo \
libdevstat \
@ -81,9 +87,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_libgpib} \
${_libgssapi} \
${_librpcsec_gss} \
${_libiconv_compat} \
libipsec \
${_libipx} \
libjail \
libkiconv \
liblzma \
@ -114,6 +118,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_libtelnet} \
${_libthr} \
libthread_db \
libucl \
libufs \
libugidfw \
libulog \
@ -124,10 +129,10 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_libvmmapi} \
libwrap \
liby \
libyaml \
libz \
${_atf} \
${_clang}
${_clang} \
${_tests}
.if exists(${.CURDIR}/csu/${MACHINE_ARCH}-elf)
_csu=csu/${MACHINE_ARCH}-elf
@ -141,10 +146,6 @@ _csu=csu
# NB: keep these sorted by MK_* knobs
.if ${MK_ATF} != "no"
_atf= atf
.endif
.if ${MK_ATM} != "no"
_libngatm= libngatm
.endif
@ -158,6 +159,11 @@ _libsdp= libsdp
_libbsnmp= libbsnmp
.endif
.if ${MK_CASPER} != "no"
_libcapsicum= libcapsicum
_libcasper= libcasper
.endif
.if ${MK_CLANG} != "no" && !defined(COMPAT_32BIT)
_clang= clang
.endif
@ -175,10 +181,6 @@ _librpcsec_gss= librpcsec_gss
_libiconv_modules= libiconv_modules
.endif
.if ${MK_IPX} != "no"
_libipx= libipx
.endif
.if ${MK_LDNS} != "no"
_libldns= libldns
.endif
@ -188,10 +190,6 @@ _libcxxrt= libcxxrt
_libcplusplus= libc++
.endif
.if ${MK_LIBICONV_COMPAT} != "no"
_libiconv_compat= libiconv_compat
.endif
.if ${MK_LIBTHR} != "no"
_libthr= libthr
.endif
@ -258,6 +256,11 @@ _libsmutil= libsmutil
_libtelnet= libtelnet
.endif
.if ${MK_TESTS} != "no"
_atf= atf
_tests= tests
.endif
.if ${MK_UNBOUND} != "no"
_libunbound= libunbound
.endif
@ -272,4 +275,8 @@ afterinstall:
${INSTALL_SYMLINK} ../include ${DESTDIR}/usr/lib/include
.endif
.if !make(install)
SUBDIR_PARALLEL=
.endif
.include <bsd.subdir.mk>

View File

@ -27,9 +27,13 @@
.include <bsd.own.mk>
SUBDIR= \
libatf-c \
libatf-c++
SUBDIR= libatf-c \
libatf-c++ \
${_tests}
.if ${MK_TESTS} != "no"
_tests= tests
.endif
.ORDER: ${SUBDIR}

View File

@ -25,8 +25,6 @@
#
# $FreeBSD$
ATF= ${.CURDIR}/../../../contrib/atf
_CFLAGS:= ${CFLAGS}
_CPPFLAGS:= ${CPPFLAGS}
_CXXFLAGS:= ${CXXFLAGS}
@ -40,6 +38,7 @@ CFLAGS+= -DATF_BUILD_CPPFLAGS='"${_CPPFLAGS}"'
CFLAGS+= -DATF_BUILD_CXX='"${CXX}"'
CFLAGS+= -DATF_BUILD_CXXFLAGS='"${_CXXFLAGS}"'
CFLAGS+= -DATF_CONFDIR='"${CONFDIR}/atf"'
CFLAGS+= -DATF_C_TESTS_BASE='"${TESTSBASE}/lib/atf/libatf-c"'
CFLAGS+= -DATF_INCLUDEDIR='"${INCLUDEDIR}"'
CFLAGS+= -DATF_LIBDIR='"${LIBDIR}"'
CFLAGS+= -DATF_LIBEXECDIR='"${LIBEXECDIR}"'

19
lib/atf/common.mk Normal file
View File

@ -0,0 +1,19 @@
# $FreeBSD$
#
# Common Makefile code for all components of ATF.
#
.if !defined(ATF)
.error "ATF must be defined and point to the contrib/atf directory"
.endif
# Depend on the atf-version target to generate a file that contains the
# version number of the currently imported ATF release and that only
# changes on new imports.
atf-version: atf-version-real
@cmp -s atf-version atf-version-real \
|| cp atf-version-real atf-version
atf-version-real: .PHONY
@grep 'define VERSION' ${ATF}/bconfig.h \
| cut -d '"' -f 2 >atf-version-real
CLEANFILES+= atf-version atf-version-real

View File

@ -28,7 +28,7 @@
.include <bsd.init.mk>
LIB= atf-c++
SHLIB_MAJOR= 1
SHLIB_MAJOR= 2
# libatf-c++ depends on the C version of the ATF library to build.
DPADD= ${LIBATFC}
@ -36,6 +36,7 @@ LDADD= -latf-c
LDFLAGS+= -L${.OBJDIR}/../libatf-c
ATF= ${.CURDIR:H:H:H}/contrib/atf
.PATH: ${ATF}
.PATH: ${ATF}/atf-c++
.PATH: ${ATF}/atf-c++/detail
@ -52,13 +53,11 @@ SRCS= application.cpp \
config.cpp \
env.cpp \
exceptions.cpp \
expand.cpp \
fs.cpp \
parser.cpp \
process.cpp \
tests.cpp \
text.cpp \
ui.cpp
utils.cpp
INCS= build.hpp \
check.hpp \
@ -73,4 +72,23 @@ INCSDIR_atf-c++.hpp= ${INCLUDEDIR}
MAN= atf-c++-api.3
all: atf-c++.pc
atf-c++.pc: atf-c++.pc.in atf-version
sed -e 's,__CXX__,${CXX},g' \
-e 's,__INCLUDEDIR__,${INCLUDEDIR},g' \
-e 's,__LIBDIR__,${LIBDIR},g' \
-e "s,__ATF_VERSION__,$$(cat atf-version),g" \
<${ATF}/atf-c++/atf-c++.pc.in >atf-c++.pc
beforeinstall:
${INSTALL} -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
atf-c++.pc ${DESTDIR}${LIBDATADIR}/pkgconfig
${INSTALL} -C -o ${SHAREOWN} -g ${SHAREGRP} -m ${SHAREMODE} \
${ATF}/atf-c++/atf-c++.m4 ${DESTDIR}${SHAREDIR}/aclocal
.if ${MK_TESTS} != "no"
SUBDIR= tests
.endif
.include "../common.mk"
.include <bsd.lib.mk>

View File

@ -0,0 +1,3 @@
# $FreeBSD$
.include "../Makefile.inc"

View File

@ -0,0 +1,31 @@
# $FreeBSD$
.include <bsd.init.mk>
TESTSDIR= ${TESTSBASE}/lib/atf/libatf-c++
TESTS_SUBDIRS= detail
ATF= ${.CURDIR:H:H:H:H}/contrib/atf
.PATH: ${ATF}/atf-c++
.PATH: ${ATF}/atf-c++/detail
CFLAGS+= -I${ATF}
FILESDIR= ${TESTSDIR}
FILES= macros_hpp_test.cpp
FILES+= unused_test.cpp
.for _T in atf_c++_test \
build_test \
check_test \
config_test \
macros_test \
tests_test \
utils_test
ATF_TESTS_CXX+= ${_T}
SRCS.${_T}= ${_T}.cpp test_helpers.cpp
.endfor
ATF_TESTS_SH= pkg_config_test
.include <bsd.test.mk>

View File

@ -0,0 +1,3 @@
# $FreeBSD$
.include "../Makefile.inc"

View File

@ -0,0 +1,32 @@
# $FreeBSD$
.include <bsd.init.mk>
TESTSDIR= ${TESTSBASE}/lib/atf/libatf-c++/detail
ATF= ${.CURDIR:H:H:H:H:H}/contrib/atf
.PATH: ${ATF}/atf-c++/detail
CFLAGS+= -I${ATF}
.for _T in application_test \
env_test \
exceptions_test \
fs_test \
process_test \
sanity_test \
text_test
ATF_TESTS_CXX+= ${_T}
SRCS.${_T}= ${_T}.cpp test_helpers.cpp
.endfor
.for p in version_helper
PROGS_CXX+= ${p}
SRCS.${p}= ${p}.cpp
MAN.${p}= # defined
BINDIR.${p}= ${TESTSDIR}
.endfor
version_helper.o: atf-version
.include "../../../common.mk"
.include <bsd.test.mk>

View File

@ -30,6 +30,7 @@
LIB= atf-c
SHLIB_MAJOR= 1
ATF= ${.CURDIR:H:H:H}/contrib/atf
.PATH: ${ATF}
.PATH: ${ATF}/atf-c
.PATH: ${ATF}/atf-c/detail
@ -73,4 +74,25 @@ INCSDIR_atf-c.h= ${INCLUDEDIR}
MAN= atf-c-api.3
all: atf-c.pc
atf-c.pc: atf-c.pc.in atf-version
sed -e 's,__CC__,${CC},g' \
-e 's,__INCLUDEDIR__,${INCLUDEDIR},g' \
-e 's,__LIBDIR__,${LIBDIR},g' \
-e "s,__ATF_VERSION__,$$(cat atf-version),g" \
<${ATF}/atf-c/atf-c.pc.in >atf-c.pc
beforeinstall:
${INSTALL} -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
atf-c.pc ${DESTDIR}${LIBDATADIR}/pkgconfig
${INSTALL} -C -o ${SHAREOWN} -g ${SHAREGRP} -m ${SHAREMODE} \
${ATF}/atf-c/atf-common.m4 ${DESTDIR}${SHAREDIR}/aclocal
${INSTALL} -C -o ${SHAREOWN} -g ${SHAREGRP} -m ${SHAREMODE} \
${ATF}/atf-c/atf-c.m4 ${DESTDIR}${SHAREDIR}/aclocal
.if ${MK_TESTS} != "no"
SUBDIR= tests
.endif
.include "../common.mk"
.include <bsd.lib.mk>

View File

@ -0,0 +1,3 @@
# $FreeBSD$
.include "../Makefile.inc"

View File

@ -0,0 +1,38 @@
# $FreeBSD$
.include <bsd.init.mk>
TESTSDIR= ${TESTSBASE}/lib/atf/libatf-c
TESTS_SUBDIRS= detail
ATF= ${.CURDIR:H:H:H:H}/contrib/atf
.PATH: ${ATF}/atf-c
.PATH: ${ATF}/atf-c/detail
CFLAGS+= -I${ATF}
# macros_test.c contains a double 'const const' which will be gone with
# the import of atf-0.18.
# TODO(jmmv): Remove this workaround once we do that update.
CFLAGS.clang+= -Wno-duplicate-decl-specifier
FILESDIR= ${TESTSDIR}
FILES= macros_h_test.c
FILES+= unused_test.c
.for _T in atf_c_test \
build_test \
check_test \
config_test \
error_test \
macros_test \
tc_test \
tp_test \
utils_test
ATF_TESTS_C+= ${_T}
SRCS.${_T}= ${_T}.c test_helpers.c
.endfor
ATF_TESTS_SH= pkg_config_test
.include <bsd.test.mk>

View File

@ -0,0 +1,3 @@
# $FreeBSD$
.include "../Makefile.inc"

View File

@ -0,0 +1,34 @@
# $FreeBSD$
.include <bsd.init.mk>
TESTSDIR= ${TESTSBASE}/lib/atf/libatf-c/detail
ATF= ${.CURDIR:H:H:H:H:H}/contrib/atf
.PATH: ${ATF}/atf-c/detail
CFLAGS+= -I${ATF}
.for _T in dynstr_test \
env_test \
fs_test \
list_test \
map_test \
process_test \
sanity_test \
text_test \
user_test
ATF_TESTS_C+= ${_T}
SRCS.${_T}= ${_T}.c test_helpers.c
.endfor
.for p in process_helpers version_helper
PROGS+= ${p}
SRCS.${p}= ${p}.c
MAN.${p}= # defined
BINDIR.${p}= ${TESTSDIR}
.endfor
version_helper.o: atf-version
.include "../../../common.mk"
.include <bsd.test.mk>

12
lib/atf/tests/Makefile Normal file
View File

@ -0,0 +1,12 @@
# $FreeBSD$
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/lib/atf
.PATH: ${.CURDIR:H:H:H}/tests
KYUAFILE= yes
SUBDIR= test-programs
.include <bsd.test.mk>

View File

@ -0,0 +1,24 @@
# $FreeBSD$
.include <bsd.init.mk>
TESTSDIR= ${TESTSBASE}/lib/atf/test-programs
KYUAFILE= yes
ATF= ${.CURDIR:H:H:H:H}/contrib/atf
.PATH: ${ATF}/test-programs
CFLAGS+= -I${ATF}
ATF_TESTS_C= c_helpers
ATF_TESTS_CXX= cpp_helpers
SRCS.cpp_helpers= cpp_helpers.cpp
ATF_TESTS_SH= sh_helpers
.for _T in config_test expect_test meta_data_test result_test srcdir_test
ATF_TESTS_SH+= ${_T}
ATF_TESTS_SH_SRC_${_T}= common.sh ${_T}.sh
.endfor
.include <bsd.test.mk>

View File

@ -123,7 +123,7 @@ static const struct {
char desc[sizeof(MACHINE_ARCH)];
} archtag __attribute__ ((section (NOTE_SECTION), aligned(4))) __used = {
.namesz = sizeof(NOTE_FREEBSD_VENDOR),
.descsz = sizeof(int32_t),
.descsz = sizeof(MACHINE_ARCH),
.type = ARCH_NOTETYPE,
.name = NOTE_FREEBSD_VENDOR,
.desc = MACHINE_ARCH

View File

@ -2,7 +2,7 @@
LIBARCHIVEDIR= ${.CURDIR}/../../../contrib/libarchive
NO_MAN=yes
MAN=
PROG=libarchive_test
INTERNALPROG=yes # Don't install this; it's just for testing

View File

@ -19,6 +19,6 @@ CFLAGS+= -I${OPENBSMDIR} -I${LIBBSMDIR}
WARNS?= 3
NO_MAN=
MAN=
.include <bsd.lib.mk>

10
lib/libbsdstat/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $FreeBSD$
LIB= bsdstat
SHLIB_MAJOR= 1
PRIVATELIB=
SRCS= bsdstat.c
INCS= bsdstat.h
.include <bsd.lib.mk>

Some files were not shown because too many files have changed in this diff Show More