Merge head
This commit is contained in:
commit
9d2ab4a62d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/bmake/; revision=265006
318
Makefile.inc1
318
Makefile.inc1
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
%a = genunix`kmem_alloc
|
||||
%a = kernel`malloc
|
||||
%c = a
|
||||
%d = 97
|
||||
%hd = 97
|
||||
|
@ -36,6 +36,6 @@
|
||||
|
||||
BEGIN
|
||||
{
|
||||
printf("sysname = %s", `utsname.sysname);
|
||||
printf("sysname = %s", `ostype);
|
||||
exit(0);
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
sysname = SunOS
|
||||
sysname = FreeBSD
|
||||
|
@ -38,6 +38,6 @@
|
||||
|
||||
BEGIN
|
||||
{
|
||||
printf("symbol = %a", &`kmem_alloc);
|
||||
printf("symbol = %a", &`malloc);
|
||||
exit(0);
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
symbol = kernel`kmem_alloc
|
||||
symbol = kernel`malloc
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,14 +111,15 @@ 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...]]"
|
||||
"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...]] poolname\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);
|
||||
@ -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),
|
||||
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(×tamp)));
|
||||
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,45 +2192,30 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
|
||||
bp, NULL, NULL, ZIO_FLAG_CANFAIL)), ==, 0);
|
||||
}
|
||||
|
||||
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)
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zdb_blkptr_done(zio_t *zio)
|
||||
{
|
||||
zdb_cb_t *zcb = arg;
|
||||
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];
|
||||
dmu_object_type_t type;
|
||||
boolean_t is_metadata;
|
||||
|
||||
if (bp == NULL)
|
||||
return (0);
|
||||
|
||||
type = BP_GET_TYPE(bp);
|
||||
|
||||
zdb_count_block(zcb, zilog, bp,
|
||||
(type & DMU_OT_NEWTYPE) ? ZDB_OT_OTHER : type);
|
||||
|
||||
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);
|
||||
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));
|
||||
|
||||
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);
|
||||
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
|
||||
else
|
||||
blkbuf[0] = '\0';
|
||||
|
||||
@ -2131,12 +2229,21 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
||||
(u_longlong_t)zb->zb_blkid,
|
||||
blkbuf);
|
||||
}
|
||||
}
|
||||
mutex_exit(&spa->spa_scrub_lock);
|
||||
}
|
||||
|
||||
zcb->zcb_readfails = 0;
|
||||
/* 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;
|
||||
dmu_object_type_t type;
|
||||
boolean_t is_metadata;
|
||||
|
||||
if (dump_opt['b'] >= 5) {
|
||||
sprintf_blkptr(blkbuf, bp);
|
||||
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,
|
||||
@ -2146,6 +2253,37 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
||||
blkbuf);
|
||||
}
|
||||
|
||||
if (BP_IS_HOLE(bp))
|
||||
return (0);
|
||||
|
||||
type = BP_GET_TYPE(bp);
|
||||
|
||||
zdb_count_block(zcb, zilog, bp,
|
||||
(type & DMU_OT_NEWTYPE) ? ZDB_OT_OTHER : type);
|
||||
|
||||
is_metadata = (BP_GET_LEVEL(bp) != 0 || DMU_OT_IS_METADATA(type));
|
||||
|
||||
if (dump_opt['c'] > 1 || (dump_opt['c'] && is_metadata)) {
|
||||
size_t size = BP_GET_PSIZE(bp);
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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 && 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 *),
|
||||
|
@ -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, "
|
||||
|
@ -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
|
||||
|
@ -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--;
|
||||
}
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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 (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"),
|
||||
"or bookmarks exist\n"),
|
||||
cbp->cb_target);
|
||||
(void) fprintf(stderr, gettext("use '-r' to "
|
||||
"force deletion of the following "
|
||||
"snapshots:\n"));
|
||||
"snapshots and bookmarks:\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) {
|
||||
rollback_check_dependent, 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"),
|
||||
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);
|
||||
}
|
||||
@ -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) {
|
||||
/*
|
||||
* 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("argument must be a snapshot\n"));
|
||||
usage(B_FALSE);
|
||||
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 '-?'
|
||||
*/
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,26 +298,40 @@ 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)
|
||||
break;
|
||||
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 (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, sec,
|
||||
&fixedprobes, dofstrtab);
|
||||
fixsymbol(e, dynsymdata, dynsymidx, nprobes, buf, dofprobes,
|
||||
&fixedprobes, dofstrtabraw);
|
||||
}
|
||||
if (fixedprobes != nprobes) {
|
||||
fprintf(stderr, "WARNING: number of probes "
|
||||
@ -319,6 +341,7 @@ dtrace_dof_init(void)
|
||||
fprintf(stderr, "WARNING: some probes might "
|
||||
"not fire or your program might crash\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
|
||||
dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
|
||||
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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]);
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
*/
|
||||
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,
|
||||
|
@ -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" },
|
||||
|
@ -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 },
|
||||
|
@ -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 },
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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__);
|
||||
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);
|
||||
}
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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,32 +3625,16 @@ 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(zfs_handle_t *zhp, void *data)
|
||||
rollback_destroy_dependent(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) {
|
||||
|
||||
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;
|
||||
|
||||
/* 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) {
|
||||
@ -3554,6 +3648,21 @@ rollback_destroy(zfs_handle_t *zhp, void *data)
|
||||
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 (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_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);
|
||||
}
|
||||
|
@ -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 **);
|
||||
|
||||
|
@ -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,10 +1613,17 @@ 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))
|
||||
(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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
if (literal) {
|
||||
(void) snprintf(buf, len, "%llu",
|
||||
(u_longlong_t)intval);
|
||||
} else {
|
||||
(void) zfs_nicenum(intval, buf, len);
|
||||
}
|
||||
break;
|
||||
|
||||
case ZPOOL_PROP_CAPACITY:
|
||||
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);
|
||||
|
@ -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"
|
||||
*/
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,26 +186,31 @@ 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);
|
||||
if (!prealloc)
|
||||
task_free(tq, t);
|
||||
}
|
||||
tq->tq_nthreads--;
|
||||
@ -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) {
|
||||
|
@ -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(
|
||||
|
@ -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,21 +488,73 @@ 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 (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\n",
|
||||
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;
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
||||
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 -
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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>
|
||||
|
@ -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
10
cddl/lib/tests/Makefile
Normal 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>
|
@ -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
10
cddl/sbin/tests/Makefile
Normal 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
10
cddl/tests/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/cddl
|
||||
|
||||
.PATH: ${.CURDIR:H:H}/tests
|
||||
KYUAFILE= yes
|
||||
|
||||
.include <bsd.test.mk>
|
@ -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
|
||||
|
@ -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
|
||||
|
10
cddl/usr.bin/tests/Makefile
Normal file
10
cddl/usr.bin/tests/Makefile
Normal 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>
|
@ -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
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
.PATH: ${.CURDIR}/../../contrib/opensolaris/cmd/zlook
|
||||
|
||||
PROG= zlook
|
||||
NO_MAN=
|
||||
MAN=
|
||||
|
||||
WARNS?= 0
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
||||
|
@ -3,7 +3,7 @@
|
||||
.PATH: ${.CURDIR}/../..//contrib/opensolaris/cmd/ztest
|
||||
|
||||
PROG= ztest
|
||||
NO_MAN=
|
||||
MAN=
|
||||
|
||||
WARNS?= 0
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
||||
|
@ -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
|
||||
|
@ -3,7 +3,6 @@
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/lockstat
|
||||
|
||||
PROG= lockstat
|
||||
NO_MAN=
|
||||
SRCS= lockstat.c sym.c
|
||||
BINDIR?= /usr/sbin
|
||||
|
||||
|
10
cddl/usr.sbin/tests/Makefile
Normal file
10
cddl/usr.sbin/tests/Makefile
Normal 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>
|
@ -3,7 +3,7 @@
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/zhack
|
||||
|
||||
PROG= zhack
|
||||
NO_MAN=
|
||||
MAN=
|
||||
|
||||
WARNS?= 0
|
||||
CSTD= c99
|
||||
|
41
lib/Makefile
41
lib/Makefile
@ -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>
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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
19
lib/atf/common.mk
Normal 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
|
@ -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>
|
||||
|
3
lib/atf/libatf-c++/Makefile.inc
Normal file
3
lib/atf/libatf-c++/Makefile.inc
Normal file
@ -0,0 +1,3 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include "../Makefile.inc"
|
31
lib/atf/libatf-c++/tests/Makefile
Normal file
31
lib/atf/libatf-c++/tests/Makefile
Normal 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>
|
3
lib/atf/libatf-c++/tests/Makefile.inc
Normal file
3
lib/atf/libatf-c++/tests/Makefile.inc
Normal file
@ -0,0 +1,3 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include "../Makefile.inc"
|
32
lib/atf/libatf-c++/tests/detail/Makefile
Normal file
32
lib/atf/libatf-c++/tests/detail/Makefile
Normal 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>
|
@ -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>
|
||||
|
3
lib/atf/libatf-c/Makefile.inc
Normal file
3
lib/atf/libatf-c/Makefile.inc
Normal file
@ -0,0 +1,3 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include "../Makefile.inc"
|
38
lib/atf/libatf-c/tests/Makefile
Normal file
38
lib/atf/libatf-c/tests/Makefile
Normal 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>
|
3
lib/atf/libatf-c/tests/Makefile.inc
Normal file
3
lib/atf/libatf-c/tests/Makefile.inc
Normal file
@ -0,0 +1,3 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include "../Makefile.inc"
|
34
lib/atf/libatf-c/tests/detail/Makefile
Normal file
34
lib/atf/libatf-c/tests/detail/Makefile
Normal 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
12
lib/atf/tests/Makefile
Normal 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>
|
24
lib/atf/tests/test-programs/Makefile
Normal file
24
lib/atf/tests/test-programs/Makefile
Normal 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>
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -19,6 +19,6 @@ CFLAGS+= -I${OPENBSMDIR} -I${LIBBSMDIR}
|
||||
|
||||
WARNS?= 3
|
||||
|
||||
NO_MAN=
|
||||
MAN=
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
10
lib/libbsdstat/Makefile
Normal file
10
lib/libbsdstat/Makefile
Normal 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
Loading…
Reference in New Issue
Block a user