Merge ^/head r323559 through r325504.

This commit is contained in:
Hans Petter Selasky 2017-11-07 08:39:14 +00:00
commit c2c014f24c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/bsd_rdma_4_9/; revision=325505
4519 changed files with 385049 additions and 263449 deletions

View File

@ -34,12 +34,16 @@
# for world and kernel targets.
# toolchains - Build a toolchain for all world and kernel targets.
# xdev - xdev-build + xdev-install for the architecture
# specified with XDEV and XDEV_ARCH.
# specified with TARGET and TARGET_ARCH.
# xdev-build - Build cross-development tools.
# xdev-install - Install cross-development tools.
# xdev-links - Create traditional links in /usr/bin for cc, etc
# native-xtools - Create host binaries that produce target objects
# for use in qemu user-mode jails.
# for use in qemu user-mode jails. TARGET and
# TARGET_ARCH should be defined.
# native-xtools-install
# - Install the files to the given DESTDIR/NXTP where
# NXTP defaults to /nxb-bin.
#
# "quick" way to test all kernel builds:
# _jflag=`sysctl -n hw.ncpu`
@ -118,6 +122,7 @@
TGTS= all all-man buildenv buildenvvars buildkernel buildworld \
check check-old check-old-dirs check-old-files check-old-libs \
checkdpadd checkworld clean cleandepend cleandir cleanworld \
cleanuniverse \
delete-old delete-old-dirs delete-old-files delete-old-libs \
depend distribute distributekernel distributekernel.debug \
distributeworld distrib-dirs distribution doxygen \
@ -130,11 +135,16 @@ TGTS= all all-man buildenv buildenvvars buildkernel buildworld \
_build-tools _build-metadata _cross-tools _includes _libraries \
build32 distribute32 install32 buildsoft distributesoft installsoft \
builddtb xdev xdev-build xdev-install \
xdev-links native-xtools stageworld stagekernel stage-packages \
xdev-links native-xtools native-xtools-install stageworld stagekernel \
stage-packages \
create-packages-world create-packages-kernel create-packages \
packages installconfig real-packages sign-packages package-pkg \
print-dir test-system-compiler
# These targets require a TARGET and TARGET_ARCH be defined.
XTGTS= native-xtools native-xtools-install xdev xdev-build xdev-install \
xdev-links
# XXX: r156740: This can't work since bsd.subdir.mk is not included ever.
# It will only work for SUBDIR_TARGETS in make.conf.
TGTS+= ${SUBDIR_TARGETS}
@ -179,7 +189,7 @@ META_TGT_WHITELIST+= \
PATH= /sbin:/bin:/usr/sbin:/usr/bin
MAKEOBJDIRPREFIX?= /usr/obj
_MAKEOBJDIRPREFIX!= /usr/bin/env -i PATH=${PATH} MK_AUTO_OBJ=no ${MAKE} \
_MAKEOBJDIRPREFIX!= /usr/bin/env -i PATH=${PATH} ${MAKE} MK_AUTO_OBJ=no \
${.MAKEFLAGS:MMAKEOBJDIRPREFIX=*} __MAKE_CONF=${__MAKE_CONF} \
-f /dev/null -V MAKEOBJDIRPREFIX dummy
.if !empty(_MAKEOBJDIRPREFIX)
@ -199,7 +209,7 @@ WANT_MAKE_VERSION= 20160604
# 20160220 - support .dinclude for FAST_DEPEND.
WANT_MAKE_VERSION= 20160220
.endif
MYMAKE= ${MAKEOBJDIRPREFIX}${.CURDIR}/make.${MACHINE}/${WANT_MAKE}
MYMAKE= ${OBJROOT}make.${MACHINE}/${WANT_MAKE}
.if defined(.PARSEDIR)
HAVE_MAKE= bmake
.else
@ -270,6 +280,11 @@ _TARGET= ${XDEV}
.if defined(XDEV_ARCH)
_TARGET_ARCH= ${XDEV_ARCH}
.endif
# Some targets require a set TARGET/TARGET_ARCH, check before the default
# MACHINE and after the compatibility handling.
.if !defined(_TARGET) || !defined(_TARGET_ARCH)
${XTGTS}: _assert_target
.endif
# Otherwise, default to current machine type and architecture.
_TARGET?= ${MACHINE}
_TARGET_ARCH?= ${MACHINE_ARCH}
@ -278,6 +293,14 @@ _TARGET_ARCH?= ${MACHINE_ARCH}
.SILENT:
.endif
_assert_target: .PHONY .MAKE
.for _tgt in ${XTGTS}
.if make(${_tgt})
@echo "*** Error: Both TARGET and TARGET_ARCH must be defined for \"${_tgt}\" target"
@false
.endif
.endfor
#
# Make sure we have an up-to-date make(1). Only world and buildworld
# should do this as those are the initial targets used for upgrades.
@ -384,10 +407,13 @@ upgrade_checks: .PHONY
# headers, libraries and tools. Also, allow the location of
# the system bsdmake-like utility to be overridden.
#
MMAKEENV= MAKEOBJDIRPREFIX=${MYMAKE:H} \
MMAKEENV= \
DESTDIR= \
INSTALL="sh ${.CURDIR}/tools/install.sh"
MMAKE= ${MMAKEENV} ${MAKE} \
OBJTOP=${MYMAKE:H}/obj \
OBJROOT='$${OBJTOP}/' \
MAKEOBJDIRPREFIX= \
MAN= -DNO_SHARED \
-DNO_CPU_CFLAGS -DNO_WERROR \
-DNO_SUBDIR \
@ -435,7 +461,7 @@ worlds: .PHONY
.if make(universe) || make(universe_kernels) || make(tinderbox) || make(targets)
TARGETS?=amd64 arm arm64 i386 mips powerpc riscv sparc64
_UNIVERSE_TARGETS= ${TARGETS}
TARGET_ARCHES_arm?= arm armeb armv6
TARGET_ARCHES_arm?= arm armeb armv6 armv7
TARGET_ARCHES_arm64?= aarch64
TARGET_ARCHES_mips?= mipsel mips mips64el mips64 mipsn32 mipselhf mipshf mips64elhf mips64hf
TARGET_ARCHES_powerpc?= powerpc powerpc64 powerpcspe

View File

@ -78,18 +78,11 @@ MK_CLANG_BOOTSTRAP= no
MK_GCC_BOOTSTRAP= no
.endif
MAKEOBJDIRPREFIX?= /usr/obj
.if ${MACHINE} == ${TARGET} && ${MACHINE_ARCH} == ${TARGET_ARCH} && !defined(CROSS_BUILD_TESTING)
OBJTREE= ${MAKEOBJDIRPREFIX}
.else
OBJTREE= ${MAKEOBJDIRPREFIX}/${TARGET}.${TARGET_ARCH}
.endif
# Pull in compiler metadata from buildworld/toolchain if possible to avoid
# running CC from bsd.compiler.mk.
.if make(installworld) || make(install) || make(distributeworld) || \
make(stageworld)
.-include "${OBJTREE}${.CURDIR}/compiler-metadata.mk"
.-include "${OBJTOP}/compiler-metadata.mk"
.endif
# Pull in COMPILER_TYPE and COMPILER_FREEBSD_VERSION early.
@ -133,7 +126,7 @@ WANT_COMPILER_VERSION!= \
# TARGET_ARCH!=MACHINE_ARCH.
.if ${MK_SYSTEM_COMPILER} == "yes" && \
(${MK_CLANG_BOOTSTRAP} == "yes" || ${MK_GCC_BOOTSTRAP} == "yes") && \
!make(showconfig) && !make(native-xtools) && !make(xdev*) && \
!make(showconfig) && !make(xdev*) && \
${WANT_COMPILER_TYPE} == ${COMPILER_TYPE} && \
(${COMPILER_TYPE} == "clang" || ${TARGET_ARCH} == ${MACHINE_ARCH}) && \
${COMPILER_VERSION} == ${WANT_COMPILER_VERSION} && \
@ -308,7 +301,7 @@ CLEANDIR= cleandir
.if defined(WORLDFAST)
NO_CLEAN= t
NO_OBJ= t
NO_OBJWALK= t
.endif
.if ${MK_META_MODE} == "yes"
@ -319,11 +312,11 @@ NO_OBJ= t
NO_CLEAN= t
.endif
.endif
.if defined(NO_OBJ) || ${MK_AUTO_OBJ} == "yes"
NO_OBJ= t
.if defined(NO_OBJWALK) || ${MK_AUTO_OBJ} == "yes"
NO_OBJWALK= t
NO_KERNELOBJ= t
.endif
.if !defined(NO_OBJ)
.if !defined(NO_OBJWALK)
_obj= obj
.endif
@ -365,11 +358,11 @@ OSRELDATE= 0
# Set VERSION for CTFMERGE to use via the default CTFFLAGS=-L VERSION.
.if !defined(_REVISION)
_REVISION!= MK_AUTO_OBJ=no ${MAKE} -C ${SRCDIR}/release -V REVISION
_REVISION!= ${MAKE} -C ${SRCDIR}/release MK_AUTO_OBJ=no -V REVISION
.export _REVISION
.endif
.if !defined(_BRANCH)
_BRANCH!= MK_AUTO_OBJ=no ${MAKE} -C ${SRCDIR}/release -V BRANCH
_BRANCH!= ${MAKE} -C ${SRCDIR}/release MK_AUTO_OBJ=no -V BRANCH
.export _BRANCH
.endif
.if !defined(SRCRELDATE)
@ -398,6 +391,7 @@ KNOWN_ARCHES?= aarch64/arm64 \
arm \
armeb/arm \
armv6/arm \
armv7/arm \
i386 \
mips \
mipsel/mips \
@ -438,8 +432,8 @@ _TARGET_CPUTYPE=${TARGET_CPUTYPE}
.else
_TARGET_CPUTYPE=dummy
.endif
_CPUTYPE!= MK_AUTO_OBJ=no MAKEFLAGS= CPUTYPE=${_TARGET_CPUTYPE} ${MAKE} \
-f /dev/null -m ${.CURDIR}/share/mk -V CPUTYPE
_CPUTYPE!= MAKEFLAGS= CPUTYPE=${_TARGET_CPUTYPE} ${MAKE} -f /dev/null \
-m ${.CURDIR}/share/mk MK_AUTO_OBJ=no -V CPUTYPE
.if ${_CPUTYPE} != ${_TARGET_CPUTYPE}
.error CPUTYPE global should be set with ?=.
.endif
@ -449,7 +443,7 @@ BUILD_ARCH!= uname -p
.error To cross-build, set TARGET_ARCH.
.endif
.endif
WORLDTMP= ${OBJTREE}${.CURDIR}/tmp
WORLDTMP?= ${OBJTOP}/tmp
BPATH= ${CCACHE_WRAPPER_PATH_PFX}${WORLDTMP}/legacy/usr/sbin:${WORLDTMP}/legacy/usr/bin:${WORLDTMP}/legacy/bin
XPATH= ${WORLDTMP}/usr/sbin:${WORLDTMP}/usr/bin
STRICTTMPPATH= ${BPATH}:${XPATH}
@ -507,7 +501,7 @@ MINIMUM_SUPPORTED_OSREL?= 900044
MINIMUM_SUPPORTED_REL?= 9.1
# Common environment for world related stages
CROSSENV+= MAKEOBJDIRPREFIX=${OBJTREE} \
CROSSENV+= \
MACHINE_ARCH=${TARGET_ARCH} \
MACHINE=${TARGET} \
CPUTYPE=${TARGET_CPUTYPE}
@ -527,6 +521,9 @@ BMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}"
# need to keep this in sync with targets/pseudo/bootstrap-tools/Makefile
BSARGS= DESTDIR= \
OBJTOP='${WORLDTMP}/obj-tools' \
OBJROOT='$${OBJTOP}/' \
MAKEOBJDIRPREFIX= \
BOOTSTRAPPING=${OSRELDATE} \
BWPHASE=${.TARGET:C,^_,,} \
SSP_CFLAGS= \
@ -537,12 +534,12 @@ BSARGS= DESTDIR= \
MK_LLDB=no MK_TESTS=no \
MK_INCLUDES=yes
BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \
BMAKE= \
${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
${BSARGS}
# build-tools stage
TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \
TMAKE= \
${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
DESTDIR= \
@ -555,7 +552,8 @@ TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \
MK_LLDB=no MK_TESTS=no
# cross-tools stage
XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \
# TOOLS_PREFIX set in BMAKE
XMAKE= ${BMAKE} \
TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
MK_GDB=no MK_LLD_IS_LD=${MK_LLD_BOOTSTRAP} MK_TESTS=no
@ -563,9 +561,12 @@ XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \
KTMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${BPATH}:${PATH} \
WORLDTMP=${WORLDTMP}
KTMAKE= TOOLS_PREFIX=${WORLDTMP} MAKEOBJDIRPREFIX=${WORLDTMP} \
KTMAKE= TOOLS_PREFIX=${WORLDTMP} \
${KTMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
DESTDIR= \
OBJTOP='${WORLDTMP}/obj-kernel-tools' \
OBJROOT='$${OBJTOP}/' \
MAKEOBJDIRPREFIX= \
BOOTSTRAPPING=${OSRELDATE} \
SSP_CFLAGS= \
MK_HTML=no -DNO_LINT MK_MAN=no \
@ -614,7 +615,7 @@ BFLAGS+= -B${CROSS_BINUTILS_PREFIX}
BFLAGS+= -B${WORLDTMP}/usr/bin
.endif
.if ${TARGET} == "arm"
.if ${TARGET_ARCH:Marmv6*} != "" && ${TARGET_CPUTYPE:M*soft*} == ""
.if ${TARGET_ARCH:Marmv[67]*} != "" && ${TARGET_CPUTYPE:M*soft*} == ""
TARGET_ABI= gnueabihf
.else
TARGET_ABI= gnueabi
@ -636,6 +637,8 @@ XCXXFLAGS+= -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 \
.endif
.elif ${WANT_COMPILER_TYPE} == clang || \
(defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == clang)
MACHINE_ABI?= unknown
MACHINE_TRIPLE?=${MACHINE_ARCH:C/amd64/x86_64/}-${MACHINE_ABI}-freebsd12.0
TARGET_ABI?= unknown
TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd12.0
XCFLAGS+= -target ${TARGET_TRIPLE}
@ -650,7 +653,7 @@ XCFLAGS+= ${BFLAGS}
${TARGET_ARCH} == "powerpc64" || ${TARGET_ARCH:Mmips64*} != "")
LIBCOMPAT= 32
.include "Makefile.libcompat"
.elif ${MK_LIBSOFT} != "no" && ${TARGET_ARCH} == "armv6"
.elif ${MK_LIBSOFT} != "no" && ${TARGET_ARCH:Marmv[67]*} != ""
LIBCOMPAT= SOFT
.include "Makefile.libcompat"
.endif
@ -666,11 +669,11 @@ LIBCOMPAT= SOFT
META_MODE_BAD_ABI_VERS+= 1200031
.if !defined(OBJDIR_HOST_OSRELDATE)
.if exists(${OBJTREE}${.CURDIR}/host-osreldate.h)
.if exists(${OBJTOP}/host-osreldate.h)
OBJDIR_HOST_OSRELDATE!= \
awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \
${OBJTREE}${.CURDIR}/host-osreldate.h
.else
${OBJTOP}/host-osreldate.h
.elif exists(${WORLDTMP}/usr/include/osreldate.h)
OBJDIR_HOST_OSRELDATE= 0
.endif
.export OBJDIR_HOST_OSRELDATE
@ -679,6 +682,7 @@ OBJDIR_HOST_OSRELDATE= 0
# Note that this logic is the opposite of normal BOOTSTRAP handling. We want
# to compare the WORLDTMP's OSRELDATE to the host's OSRELDATE. If the WORLDTMP
# is older than the ABI-breakage OSRELDATE of the HOST then we rebuild.
.if defined(OBJDIR_HOST_OSRELDATE)
.for _ver in ${META_MODE_BAD_ABI_VERS}
.if ${OSRELDATE} >= ${_ver} && ${OBJDIR_HOST_OSRELDATE} < ${_ver}
_meta_mode_need_rebuild= ${_ver}
@ -688,8 +692,9 @@ _meta_mode_need_rebuild= ${_ver}
.info META_MODE: Rebuilding host tools due to ABI breakage in __FreeBSD_version ${_meta_mode_need_rebuild}.
NO_META_IGNORE_HOST_HEADERS= 1
.export NO_META_IGNORE_HOST_HEADERS
.endif
.endif
.endif # defined(_meta_mode_need_rebuild)
.endif # defined(OBJDIR_HOST_OSRELDATE)
.endif # ${MK_META_MODE} == "yes" && defined(NO_CLEAN) ...
# This is only used for META_MODE+filemon to track what the oldest
# __FreeBSD_version is in WORLDTMP. This purposely does NOT have
# a make dependency on /usr/include/osreldate.h as the file should
@ -747,34 +752,76 @@ KMAKE= ${KMAKEENV} ${MAKE} ${.MAKEFLAGS} ${KERNEL_FLAGS} KERNEL=${INSTKERNNAME}
# Attempt to rebuild the entire system, with reasonable chance of
# success, regardless of how old your existing system is.
#
_worldtmp: .PHONY
_sanity_check: .PHONY .MAKE
.if ${.CURDIR:C/[^,]//g} != ""
# The m4 build of sendmail files doesn't like it if ',' is used
# anywhere in the path of it's files.
@echo
@echo "*** Error: path to source tree contains a comma ','"
@echo
false
@false
.elif ${.CURDIR:M*\:*} != ""
# Using ':' leaks into PATH and breaks finding cross-tools.
@echo
@echo "*** Error: path to source tree contains a colon ':'"
@echo
@false
.endif
# Our current approach to dependency tracking cannot cope with certain source
# tree changes, particularly with respect to removing source files and
# replacing generated files. Handle these cases here in an ad-hoc fashion.
_cleanobj_fast_depend_hack: .PHONY
# Syscall stubs rewritten in C
# Date SVN Rev Syscalls
# 20160829 r305012 ptrace
# 20170624 r320278 fstat fstatat fstatfs getdirentries getfsstat statfs
.for f in fstat fstatat fstatfs getdirentries getfsstat ptrace statfs
.if exists(${OBJTOP}/lib/libc/.depend.${f}.o)
@if egrep -qw '${f}\.[sS]' \
${OBJTOP}/lib/libc/.depend.${f}.o; then \
echo Removing stale dependencies for ${f} syscall wrappers; \
rm -f ${OBJTOP}/lib/libc/.depend.${f}.* \
${LIBCOMPAT:D${LIBCOMPAT_OBJTOP}/lib/libc/.depend.${f}.*}; \
fi
.endif
.endfor
# 20170607 remove stale dependencies for utimens* wrappers removed in r319663
.for f in futimens utimensat
.if exists(${OBJTOP}/lib/libc/.depend.${f}.o)
@if egrep -q '/${f}.c' \
${OBJTOP}/lib/libc/.depend.${f}.o; then \
echo Removing stale dependencies for ${f} syscall wrappers; \
rm -f ${OBJTOP}/lib/libc/.depend.${f}.* \
${LIBCOMPAT:D${LIBCOMPAT_OBJTOP}/lib/libc/.depend.${f}.*}; \
fi
.endif
.endfor
# 20170523 remove stale generated asm files for functions which are no longer
# syscalls after r302092 (pipe) and r318736 (others)
.for f in getdents lstat mknod pipe stat
.if exists(${OBJTOP}/lib/libc/${f}.s) || \
exists(${OBJTOP}/lib/libc/${f}.S)
@echo Removing stale generated ${f} syscall files
@rm -f ${OBJTOP}/lib/libc/${f}.* \
${OBJTOP}/lib/libc/.depend.${f}.* \
${LIBCOMPAT:D${LIBCOMPAT_OBJTOP}/lib/libc/${f}.*} \
${LIBCOMPAT:D${LIBCOMPAT_OBJTOP}/lib/libc/.depend.${f}.*}
.endif
.endfor
_worldtmp: .PHONY
@echo
@echo "--------------------------------------------------------------"
@echo ">>> Rebuilding the temporary build tree"
@echo "--------------------------------------------------------------"
.if !defined(NO_CLEAN)
rm -rf ${WORLDTMP}
.if defined(LIBCOMPAT)
rm -rf ${LIBCOMPATTMP}
.endif
.else
.if exists(${WORLDTMP})
@echo ">>> Deleting stale files in build tree..."
${_+_}cd ${.CURDIR}; ${WMAKE} -DBATCH_DELETE_OLD_FILES \
delete-old delete-old-libs >/dev/null
.endif
.if defined(LIBCOMPAT) && exists(${LIBCOMPATTMP})
${_+_}cd ${.CURDIR}; ${WMAKE} -DBATCH_DELETE_OLD_FILES \
DESTDIR=${LIBCOMPATTMP} \
delete-old delete-old-libs >/dev/null
.endif
rm -rf ${WORLDTMP}/legacy/usr/include
.if ${USING_SYSTEM_COMPILER} == "yes"
@ -785,50 +832,9 @@ _worldtmp: .PHONY
fi
.endfor
.endif # ${USING_SYSTEM_COMPILER} == "yes"
# Our current approach to dependency tracking cannot cope with certain source
# tree changes, particularly with respect to removing source files and
# replacing generated files. Handle these cases here in an ad-hoc fashion.
#
# Syscall stubs rewritten in C
# Date SVN Rev Syscalls
# 20160829 r305012 ptrace
# 20170624 r320278 fstat fstatat fstatfs getdirentries getfsstat statfs
.for f in fstat fstatat fstatfs getdirentries getfsstat ptrace statfs
.if exists(${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.o)
@if egrep -qw '${f}\.[sS]' \
${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.o; then \
echo Removing stale dependencies for ${f} syscall wrappers; \
rm -f ${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.* \
${OBJTREE}${.CURDIR}/world32/${.CURDIR}/lib/libc/.depend.${f}.*; \
fi
.endif
.endfor
# 20170607 remove stale dependencies for utimens* wrappers removed in r319663
.for f in futimens utimensat
.if exists(${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.o)
@if egrep -q '/${f}.c' \
${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.o; then \
echo Removing stale dependencies for ${f} syscall wrappers; \
rm -f ${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.* \
${OBJTREE}${.CURDIR}/world32/${.CURDIR}/lib/libc/.depend.${f}.*; \
fi
.endif
.endfor
# 20170523 remove stale generated asm files for functions which are no longer
# syscalls after r302092 (pipe) and r318736 (others)
.for f in getdents lstat mknod pipe stat
.if exists(${OBJTREE}${.CURDIR}/lib/libc/${f}.s) || \
exists(${OBJTREE}${.CURDIR}/lib/libc/${f}.S)
@echo Removing stale generated ${f} syscall files
@rm -f ${OBJTREE}${.CURDIR}/lib/libc/${f}.* \
${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.* \
${OBJTREE}${.CURDIR}/world32/${.CURDIR}/lib/libc/${f}.* \
${OBJTREE}${.CURDIR}/world32/${.CURDIR}/lib/libc/.depend.${f}.*
.endif
.endfor
.endif # !defined(NO_CLEAN)
@mkdir -p ${WORLDTMP}
@touch ${WORLDTMP}/${.TARGET}
.for _dir in \
lib lib/casper usr legacy/bin legacy/usr
@ -844,32 +850,11 @@ _worldtmp: .PHONY
-p ${WORLDTMP}/usr/include >/dev/null
ln -sf ${.CURDIR}/sys ${WORLDTMP}
.if ${MK_DEBUG_FILES} != "no"
# We could instead disable debug files for these build stages
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
-p ${WORLDTMP}/legacy/usr/lib >/dev/null
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
-p ${WORLDTMP}/usr/lib >/dev/null
.endif
.if defined(LIBCOMPAT)
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib${libcompat}.dist \
-p ${WORLDTMP}/usr >/dev/null
.if ${MK_DEBUG_FILES} != "no"
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib${libcompat}.dist \
-p ${WORLDTMP}/legacy/usr/lib/debug/usr >/dev/null
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib${libcompat}.dist \
-p ${WORLDTMP}/usr/lib/debug/usr >/dev/null
.endif
.endif
.if ${MK_TESTS} != "no"
mkdir -p ${WORLDTMP}${TESTSBASE}
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
-p ${WORLDTMP}${TESTSBASE} >/dev/null
.if ${MK_DEBUG_FILES} != "no"
mkdir -p ${WORLDTMP}/usr/lib/debug/${TESTSBASE}
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
-p ${WORLDTMP}/usr/lib/debug/${TESTSBASE} >/dev/null
.endif
.endif
.for _mtree in ${LOCAL_MTREE}
mtree -deU -f ${.CURDIR}/${_mtree} -p ${WORLDTMP} > /dev/null
.endfor
@ -895,7 +880,9 @@ _cleanobj:
.if defined(LIBCOMPAT)
${_+_}cd ${.CURDIR}; ${LIBCOMPATWMAKE} -f Makefile.inc1 ${CLEANDIR}
.endif
.endif
.else
${_+_}cd ${.CURDIR}; ${WMAKE} _cleanobj_fast_depend_hack
.endif # !defined(NO_CLEAN)
_obj:
@echo
@echo "--------------------------------------------------------------"
@ -913,7 +900,7 @@ _cross-tools:
@echo "--------------------------------------------------------------"
@echo ">>> stage 3: cross tools"
@echo "--------------------------------------------------------------"
@rm -f ${OBJTREE}${.CURDIR}/compiler-metadata.mk
@rm -f ${OBJTOP}/compiler-metadata.mk
${_+_}cd ${.CURDIR}; ${XMAKE} cross-tools
${_+_}cd ${.CURDIR}; ${XMAKE} kernel-tools
_build-metadata:
@ -952,12 +939,12 @@ everything: .PHONY
WMAKE_TGTS=
.if !defined(WORLDFAST)
WMAKE_TGTS+= _worldtmp _legacy
WMAKE_TGTS+= _sanity_check _worldtmp _legacy
.if empty(SUBDIR_OVERRIDE)
WMAKE_TGTS+= _bootstrap-tools
.endif
WMAKE_TGTS+= _cleanobj
.if !defined(NO_OBJ)
.if !defined(NO_OBJWALK)
WMAKE_TGTS+= _obj
.endif
WMAKE_TGTS+= _build-tools _cross-tools
@ -1006,12 +993,15 @@ buildenv: .PHONY
.if ${BUILDENV_SHELL:M*zsh*}
@echo For ZSH you must run: export CPUTYPE=${TARGET_CPUTYPE}
.endif
@cd ${BUILDENV_DIR} && env ${WMAKEENV} BUILDENV=1 ${BUILDENV_SHELL} \
|| true
@cd ${BUILDENV_DIR} && env ${WMAKEENV} BUILDENV=1 ${BUILDENV_SHELL}
TOOLCHAIN_TGTS= ${WMAKE_TGTS:Neverything:Nbuild${libcompat}}
toolchain: ${TOOLCHAIN_TGTS} .PHONY
kernel-toolchain: ${TOOLCHAIN_TGTS:N_includes:N_libraries} .PHONY
KERNEL_TOOLCHAIN_TGTS= ${TOOLCHAIN_TGTS:N_obj:N_cleanobj:N_includes:N_libraries}
.if make(kernel-toolchain)
.ORDER: ${KERNEL_TOOLCHAIN_TGTS}
.endif
kernel-toolchain: ${KERNEL_TOOLCHAIN_TGTS} .PHONY
#
# installcheck
@ -1082,7 +1072,7 @@ __installcheck_UGID: .PHONY
(empty(DESTDIR) || ${DESTDIR} == "/") && empty(BYPASS_INSTALLCHECK_SH)
_installcheck_world: __installcheck_sh_check
__installcheck_sh_check: .PHONY
@if [ "`${OBJTREE}${.CURDIR}/rescue/rescue/rescue sh -c 'echo OK'`" != \
@if [ "`${OBJTOP}/rescue/rescue/rescue sh -c 'echo OK'`" != \
OK ]; then \
echo "rescue/sh check failed, installation aborted" >&2; \
false; \
@ -1344,7 +1334,7 @@ INSTKERNNAME?= kernel
KERNSRCDIR?= ${.CURDIR}/sys
KRNLCONFDIR= ${KERNSRCDIR}/${TARGET}/conf
KRNLOBJDIR= ${OBJTREE}${KERNSRCDIR}
KRNLOBJDIR= ${OBJTOP}${KERNSRCDIR:C,^${.CURDIR},,}
KERNCONFDIR?= ${KRNLCONFDIR}
BUILDKERNELS=
@ -1359,6 +1349,10 @@ BUILDKERNELS+= ${_kernel}
.if empty(INSTALLKERNEL) && !defined(NO_INSTALLKERNEL)
INSTALLKERNEL= ${_kernel}
.endif
.else
.if make(buildkernel)
.error Missing KERNCONF ${KERNCONFDIR}/${_kernel}
.endif
.endif
.endfor
@ -1548,9 +1542,9 @@ stagekernel: .PHONY
${_+_}${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} distributekernel
PORTSDIR?= /usr/ports
WSTAGEDIR?= ${MAKEOBJDIRPREFIX}${.CURDIR}/${TARGET}.${TARGET_ARCH}/worldstage
KSTAGEDIR?= ${MAKEOBJDIRPREFIX}${.CURDIR}/${TARGET}.${TARGET_ARCH}/kernelstage
REPODIR?= ${MAKEOBJDIRPREFIX}${.CURDIR}/repo
WSTAGEDIR?= ${OBJTOP}/worldstage
KSTAGEDIR?= ${OBJTOP}/kernelstage
REPODIR?= ${OBJROOT}repo
PKGSIGNKEY?= # empty
.ORDER: stage-packages create-packages
@ -1812,11 +1806,11 @@ legacy: .PHONY
.for _tool in tools/build ${_elftoolchain_libs}
${_+_}@${ECHODIR} "===> ${_tool} (obj,includes,all,install)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy includes; \
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${WORLDTMP}/legacy includes; \
${MAKE} DIRPRFX=${_tool}/ MK_INCLUDES=no all; \
${MAKE} DIRPRFX=${_tool}/ MK_INCLUDES=no \
DESTDIR=${MAKEOBJDIRPREFIX}/legacy install
DESTDIR=${WORLDTMP}/legacy install
.endfor
#
@ -1840,7 +1834,6 @@ _vtfontcvt= usr.bin/vtfontcvt
.endif
.if ${BOOTSTRAPPING} < 1000033
_libopenbsd= lib/libopenbsd
_m4= usr.bin/m4
_lex= usr.bin/lex
@ -1926,9 +1919,6 @@ _kerberos5_bootstrap_tools= \
.ORDER: ${_kerberos5_bootstrap_tools:C/^/${_bt}-/g}
.endif
# r283777 makewhatis(1) replaced with mandoc version which builds a database.
_libopenbsd?= lib/libopenbsd
_makewhatis= usr.bin/mandoc
${_bt}-usr.bin/mandoc: ${_bt}-lib/libopenbsd
bootstrap-tools: .PHONY
@ -1945,8 +1935,8 @@ bootstrap-tools: .PHONY
${_cat} \
${_kbdcontrol} \
usr.bin/lorder \
${_libopenbsd} \
${_makewhatis} \
lib/libopenbsd \
usr.bin/mandoc \
usr.bin/rpcgen \
${_yacc} \
${_m4} \
@ -1962,9 +1952,9 @@ bootstrap-tools: .PHONY
${_bt}-${_tool}: .PHONY .MAKE
${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
${MAKE} DIRPRFX=${_tool}/ all; \
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${WORLDTMP}/legacy install
bootstrap-tools: ${_bt}-${_tool}
.endfor
@ -1989,6 +1979,12 @@ _rescue=rescue/rescue
_tcsh=bin/csh
.endif
# kernel-toolchain skips _cleanobj, so handle cleaning up previous
# build-tools directories if needed.
.if !defined(NO_CLEAN) && make(kernel-toolchain)
_bt_clean= ${CLEANDIR}
.endif
.for _tool in \
${_tcsh} \
bin/sh \
@ -2001,21 +1997,14 @@ _tcsh=bin/csh
lib/libmagic \
usr.bin/mkesdb_static \
usr.bin/mkcsmapper_static \
usr.bin/vi/catalog
build-tools_${_tool}: .PHONY
${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
${MAKE} DIRPRFX=${_tool}/ build-tools
build-tools: build-tools_${_tool}
.endfor
.for _tool in \
usr.bin/vi/catalog \
${_gcc_tools}
build-tools_${_tool}: .PHONY
${_+_}@${ECHODIR} "===> ${_tool} (obj,all)"; \
${_+_}@${ECHODIR} "===> ${_tool} (${_bt_clean:D${_bt_clean},}obj,build-tools)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
${MAKE} DIRPRFX=${_tool}/ all
if [ -n "${_bt_clean}" ]; then ${MAKE} DIRPRFX=${_tool}/ ${_bt_clean}; fi; \
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
${MAKE} DIRPRFX=${_tool}/ build-tools
build-tools: build-tools_${_tool}
.endfor
@ -2023,9 +2012,9 @@ build-tools: build-tools_${_tool}
# kernel-tools: Build kernel-building tools
#
kernel-tools: .PHONY
mkdir -p ${MAKEOBJDIRPREFIX}/usr
mkdir -p ${WORLDTMP}/usr
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
-p ${MAKEOBJDIRPREFIX}/usr >/dev/null
-p ${WORLDTMP}/usr >/dev/null
#
# cross-tools: All the tools needed to build the rest of the system after
@ -2099,52 +2088,30 @@ cross-tools: .MAKE .PHONY
${_usb_tools}
${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
${MAKE} DIRPRFX=${_tool}/ all; \
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX} install
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${WORLDTMP} install
.endfor
NXBDESTDIR= ${OBJTREE}/nxb-bin
NXBENV= MAKEOBJDIRPREFIX=${OBJTREE}/nxb \
TOOLS_PREFIX= \
INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${PATH}:${OBJTREE}/gperf_for_gcc/usr/bin
NXBMAKE= ${NXBENV} ${MAKE} \
LLVM_TBLGEN=${NXBDESTDIR}/usr/bin/llvm-tblgen \
CLANG_TBLGEN=${NXBDESTDIR}/usr/bin/clang-tblgen \
MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH} \
MK_GDB=no MK_TESTS=no \
SSP_CFLAGS= \
MK_HTML=no NO_LINT=yes MK_MAN=no MK_MAN_UTILS=yes \
-DNO_PIC MK_PROFILE=no -DNO_SHARED \
-DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \
MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \
MK_LLDB=no MK_DEBUG_FILES=no
#
# native-xtools is the current target for qemu-user cross builds of ports
# via poudriere and the imgact_binmisc kernel module.
# For non-clang enabled targets that are still using the in tree gcc
# we must build a gperf binary for one instance of its Makefiles. On
# clang-enabled systems, the gperf binary is obsolete.
native-xtools: .PHONY
.if ${MK_GCC_BOOTSTRAP} != "no"
mkdir -p ${OBJTREE}/gperf_for_gcc/usr/bin
${_+_}@${ECHODIR} "===> ${_gperf} (obj,all,install)"; \
cd ${.CURDIR}/${_gperf}; \
if [ -z "${NO_OBJ}" ]; then ${NXBMAKE} DIRPRFX=${_gperf}/ obj; fi; \
${NXBMAKE} DIRPRFX=${_gperf}/ all; \
${NXBMAKE} DIRPRFX=${_gperf}/ DESTDIR=${OBJTREE}/gperf_for_gcc install
# This target merely builds a toolchan/sysroot, then builds the tools it wants
# with the options it wants in a special MAKEOBJDIRPREFIX, using the toolchain
# already built. It then installs the static tools to NXBDESTDIR for Poudriere
# to pickup.
#
NXBOBJROOT= ${OBJROOT}${MACHINE}.${MACHINE_ARCH}/nxb/
NXBOBJTOP= ${NXBOBJROOT}${TARGET}.${TARGET_ARCH}
NXTP?= /nxb-bin
.if ${NXTP:N/*}
.error NXTP variable should be an absolute path
.endif
mkdir -p ${NXBDESTDIR}/bin ${NXBDESTDIR}/sbin ${NXBDESTDIR}/usr
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
-p ${NXBDESTDIR}/usr >/dev/null
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
-p ${NXBDESTDIR}/usr/include >/dev/null
.if ${MK_DEBUG_FILES} != "no"
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
-p ${NXBDESTDIR}/usr/lib >/dev/null
.endif
.for _tool in \
NXBDESTDIR?= ${DESTDIR}${NXTP}
# This is the list of tools to be built/installed as static and where
# appropriate to build for the given TARGET.TARGET_ARCH.
NXBDIRS+= \
bin/cat \
bin/chmod \
bin/cp \
@ -2162,24 +2129,18 @@ native-xtools: .PHONY
bin/rmdir \
bin/sh \
bin/sleep \
${_clang_tblgen} \
usr.bin/ar \
${_binutils} \
${_elftctools} \
${_gcc} \
${_gcc_tools} \
${_clang_libs} \
${_clang} \
${_lld} \
sbin/md5 \
sbin/sysctl \
usr.bin/diff \
usr.bin/addr2line \
usr.bin/ar \
usr.bin/awk \
usr.bin/basename \
usr.bin/bmake \
usr.bin/bzip2 \
usr.bin/cmp \
usr.bin/diff \
usr.bin/dirname \
usr.bin/elfcopy \
usr.bin/env \
usr.bin/fetch \
usr.bin/find \
@ -2189,14 +2150,16 @@ native-xtools: .PHONY
usr.bin/lex \
usr.bin/limits \
usr.bin/lorder \
${_libopenbsd} \
${_makewhatis} \
usr.bin/mandoc \
usr.bin/mktemp \
usr.bin/mt \
usr.bin/nm \
usr.bin/patch \
usr.bin/readelf \
usr.bin/sed \
usr.bin/size \
usr.bin/sort \
usr.bin/strings \
usr.bin/tar \
usr.bin/touch \
usr.bin/tr \
@ -2208,12 +2171,82 @@ native-xtools: .PHONY
usr.bin/xz \
usr.bin/yacc \
usr.sbin/chown
${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJ}" ]; then ${NXBMAKE} DIRPRFX=${_tool}/ obj; fi; \
${NXBMAKE} DIRPRFX=${_tool}/ all; \
${NXBMAKE} DIRPRFX=${_tool}/ DESTDIR=${NXBDESTDIR} install
.endfor
.if ${MK_CLANG} != "no"
NXBDIRS+= lib/clang
SUBDIR_DEPEND_usr.bin/clang= lib/clang
NXBDIRS+= usr.bin/clang
.elif ${MK_GCC} != "no"
NXBDIRS+= gnu/usr.bin/cc
.endif
.if ${MK_BINUTILS} != "no"
NXBDIRS+= gnu/usr.bin/binutils
.endif
NXBMAKEARGS+= \
OBJTOP=${NXBOBJTOP:Q} \
OBJROOT=${NXBOBJROOT:Q} \
-DNO_SHARED \
-DNO_CPU_CFLAGS \
-DNO_PIC \
SSP_CFLAGS= \
MK_CLANG_EXTRAS=no \
MK_CLANG_FULL=no \
MK_CTF=no \
MK_DEBUG_FILES=no \
MK_GDB=no \
MK_HTML=no \
MK_LLDB=no \
MK_MAN=no \
MK_MAN_UTILS=yes \
MK_OFED=no \
MK_OPENSSH=no \
MK_PROFILE=no \
MK_SENDMAIL=no \
MK_SVNLITE=no \
MK_TESTS=no \
MK_WARNS=no \
MK_ZFS=no
# For 'toolchain' we want to produce native binaries that themselves generate
# native binaries.
NXBTMAKE= ${NXBMAKEENV} ${MAKE} ${NXBMAKEARGS:N-DNO_PIC:N-DNO_SHARED} \
TARGET=${MACHINE} TARGET_ARCH=${MACHINE_ARCH}
# For 'everything' we want to produce native binaries (hence -target to
# be MACHINE) that themselves generate TARGET.TARGET_ARCH binaries.
# TARGET/TARGET_ARCH are still passed along from user.
NXBMAKE= ${NXBMAKEENV} ${MAKE} ${NXBMAKEARGS} \
TARGET_TRIPLE=${MACHINE_TRIPLE:Q}
native-xtools: .PHONY
# Build the bootstrap/host/cross tools that produce native binaries
${_+_}cd ${.CURDIR}; ${NXBTMAKE} kernel-toolchain
# Populate includes/libraries sysroot that produce native binaries.
# This is split out from 'toolchain' above mostly so that target LLVM
# libraries have a proper LLVM_DEFAULT_TARGET_TRIPLE without
# polluting the cross-compiler build. The LLVM/GCC libs are skipped
# here to avoid the problem but are kept in 'toolchain' so that
# needed build tools are built.
${_+_}cd ${.CURDIR}; ${NXBTMAKE} _includes MK_CLANG=no MK_GCC=no
${_+_}cd ${.CURDIR}; ${NXBTMAKE} _libraries MK_CLANG=no MK_GCC=no
.if !defined(NO_OBJWALK)
${_+_}cd ${.CURDIR}; ${NXBMAKE} SUBDIR_OVERRIDE="${NXBDIRS:M*}" _obj
.endif
${_+_}cd ${.CURDIR}; ${NXBMAKE} SUBDIR_OVERRIDE="${NXBDIRS:M*}" \
everything
@echo ">> native-xtools done. Use 'make native-xtools-install' to install to a given DESTDIR"
native-xtools-install: .PHONY
mkdir -p ${NXBDESTDIR}/bin ${NXBDESTDIR}/sbin ${NXBDESTDIR}/usr
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
-p ${NXBDESTDIR}/usr >/dev/null
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
-p ${NXBDESTDIR}/usr/include >/dev/null
${_+_}cd ${.CURDIR}; ${NXBMAKE} -f Makefile.inc1 \
DESTDIR=${NXBDESTDIR} \
SUBDIR_OVERRIDE="${NXBDIRS:M*}" \
-DNO_ROOT \
install
#
# hierarchy - ensure that all the needed directories are present
@ -2473,7 +2506,7 @@ ${_lib}__PL: .PHONY .MAKE
.if exists(${.CURDIR}/${_lib})
${_+_}@${ECHODIR} "===> ${_lib} (obj,all,install)"; \
cd ${.CURDIR}/${_lib}; \
if [ -z "${NO_OBJ}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; fi; \
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; fi; \
${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \
DIRPRFX=${_lib}/ all; \
${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \
@ -2486,7 +2519,7 @@ ${_lib}__L: .PHONY .MAKE
.if exists(${.CURDIR}/${_lib})
${_+_}@${ECHODIR} "===> ${_lib} (obj,all,install)"; \
cd ${.CURDIR}/${_lib}; \
if [ -z "${NO_OBJ}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; fi; \
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; fi; \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ all; \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ install
.endif
@ -2559,7 +2592,7 @@ delete-old-files: .PHONY
done
# Remove catpages without corresponding manpages.
@exec 3<&0; \
find ${DESTDIR}/usr/share/man/cat* ! -type d | \
find ${DESTDIR}/usr/share/man/cat* ! -type d 2>/dev/null | \
sed -ep -e's:${DESTDIR}/usr/share/man/cat:${DESTDIR}/usr/share/man/man:' | \
while read catpage; do \
read manpage; \
@ -2585,7 +2618,7 @@ check-old-files: .PHONY
done; \
done
# Check for catpages without corresponding manpages.
@find ${DESTDIR}/usr/share/man/cat* ! -type d | \
@find ${DESTDIR}/usr/share/man/cat* ! -type d 2>/dev/null | \
sed -ep -e's:${DESTDIR}/usr/share/man/cat:${DESTDIR}/usr/share/man/man:' | \
while read catpage; do \
read manpage; \
@ -2723,21 +2756,29 @@ builddtb: .PHONY
#
# It is expected that BW_CANONICALOBJDIR == the CANONICALOBJDIR as would be
# created by bsd.obj.mk, except that we don't want to .include that file
# in this makefile.
# in this makefile. We don't do a cleandir walk if MK_AUTO_OBJ is yes
# since it is not possible for files to land in the wrong place.
#
BW_CANONICALOBJDIR:=${OBJTREE}${.CURDIR}
cleanworld: .PHONY
.if exists(${BW_CANONICALOBJDIR}/)
-rm -rf ${BW_CANONICALOBJDIR}/*
-chflags -R 0 ${BW_CANONICALOBJDIR}
rm -rf ${BW_CANONICALOBJDIR}/*
.if make(cleanworld)
BW_CANONICALOBJDIR:=${OBJTOP}/
.elif make(cleanuniverse)
BW_CANONICALOBJDIR:=${OBJROOT}
.if ${MK_UNIFIED_OBJDIR} == "no"
.error ${.TARGETS} only supported with WITH_UNIFIED_OBJDIR enabled.
.endif
.endif
cleanworld cleanuniverse: .PHONY
.if !empty(BW_CANONICALOBJDIR) && exists(${BW_CANONICALOBJDIR})
-rm -rf ${BW_CANONICALOBJDIR}*
-chflags -R 0 ${BW_CANONICALOBJDIR}
rm -rf ${BW_CANONICALOBJDIR}*
.endif
.if make(cleanworld) && ${MK_AUTO_OBJ} == "no"
.if ${.CURDIR} == ${.OBJDIR} || ${.CURDIR}/obj == ${.OBJDIR}
# To be safe in this case, fall back to a 'make cleandir'
${_+_}@cd ${.CURDIR}; ${MAKE} cleandir
.endif
.if defined(TARGET) && defined(TARGET_ARCH)
.endif
.if ${TARGET} == ${MACHINE} && ${TARGET_ARCH} == ${MACHINE_ARCH}
XDEV_CPUTYPE?=${CPUTYPE}
@ -2757,10 +2798,16 @@ XDTP?=/usr/${XDDIR}
.error XDTP variable should be an absolute path
.endif
CDBENV=MAKEOBJDIRPREFIX=${MAKEOBJDIRPREFIX}/${XDDIR} \
CDBOBJROOT= ${OBJROOT}${MACHINE}.${MACHINE_ARCH}/xdev/
CDBOBJTOP= ${CDBOBJROOT}${XDDIR}
CDBENV= \
INSTALL="sh ${.CURDIR}/tools/install.sh"
CDENV= ${CDBENV} \
TOOLS_PREFIX=${XDTP}
CDMAKEARGS= \
OBJTOP=${CDBOBJTOP:Q} \
OBJROOT=${CDBOBJROOT:Q}
CD2MAKEARGS= ${CDMAKEARGS}
.if ${WANT_COMPILER_TYPE} == gcc || \
(defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc)
@ -2782,14 +2829,15 @@ CD2ENV=${CDENV} CC="${CC} ${CD2CFLAGS}" CXX="${CXX} ${CD2CXXFLAGS} ${CD2CFLAGS}"
CPP="${CPP} ${CD2CFLAGS}" \
MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH}
CDTMP= ${MAKEOBJDIRPREFIX}/${XDDIR}/${.CURDIR}/tmp
CDMAKE=${CDENV} PATH=${CDTMP}/usr/bin:${PATH} ${MAKE} ${NOFUN}
CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDDESTDIR}/usr/bin:${PATH} ${MAKE} ${NOFUN}
CDTMP= ${OBJTOP}/${XDDIR}/tmp
CDMAKE=${CDENV} PATH=${CDTMP}/usr/bin:${PATH} ${MAKE} ${CDMAKEARGS} ${NOFUN}
CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDDESTDIR}/usr/bin:${PATH} \
${MAKE} ${CD2MAKEARGS} ${NOFUN}
.if ${MK_META_MODE} != "no"
# Don't rebuild build-tools targets during normal build.
CD2MAKE+= BUILD_TOOLS_META=.NOMETA
.endif
XDDESTDIR=${DESTDIR}/${XDTP}
XDDESTDIR=${DESTDIR}${XDTP}
.ORDER: xdev-build xdev-install xdev-links
xdev: xdev-build xdev-install .PHONY
@ -2809,26 +2857,29 @@ _xb-bootstrap-tools: .PHONY
${_yacc}
${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJ}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ obj; fi; \
if [ -z "${NO_OBJWALK}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ obj; fi; \
${CDMAKE} DIRPRFX=${_tool}/ all; \
${CDMAKE} DIRPRFX=${_tool}/ DESTDIR=${CDTMP} install
.endfor
_xb-build-tools: .PHONY
${_+_}@cd ${.CURDIR}; \
${CDBENV} ${MAKE} -f Makefile.inc1 ${NOFUN} build-tools
${CDBENV} ${MAKE} ${CDMAKEARGS} -f Makefile.inc1 ${NOFUN} build-tools
_xb-cross-tools: .PHONY
.for _tool in \
XDEVDIRS= \
${_clang_libs} \
${_lld} \
${_binutils} \
${_elftctools} \
usr.bin/ar \
${_clang_libs} \
${_clang} \
${_gcc}
_xb-cross-tools: .PHONY
.for _tool in ${XDEVDIRS}
${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,all)"; \
cd ${.CURDIR}/${_tool}; \
if [ -z "${NO_OBJ}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ obj; fi; \
if [ -z "${NO_OBJWALK}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ obj; fi; \
${CDMAKE} DIRPRFX=${_tool}/ all
.endfor
@ -2856,19 +2907,17 @@ xdev-install: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries .P
_xi-cross-tools: .PHONY
@echo "_xi-cross-tools"
.for _tool in \
${_binutils} \
${_elftctools} \
usr.bin/ar \
${_clang_libs} \
${_clang} \
${_gcc}
.for _tool in ${XDEVDIRS}
${_+_}@${ECHODIR} "===> xdev ${_tool} (install)"; \
cd ${.CURDIR}/${_tool}; \
${CDMAKE} DIRPRFX=${_tool}/ install DESTDIR=${XDDESTDIR}
.endfor
_xi-includes: .PHONY
.if !defined(NO_OBJWALK)
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 _obj \
DESTDIR=${XDDESTDIR}
.endif
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 includes \
DESTDIR=${XDDESTDIR}
@ -2885,7 +2934,3 @@ xdev-links: .PHONY
ln -sf ../../${XDTP}/usr/bin/$$i \
../../../../usr/bin/${XDDIR}${_REVISION}-$$i; \
done
.else
xdev xdev-build xdev-install xdev-links: .PHONY
@echo "*** Error: Both TARGET and TARGET_ARCH must be defined for \"${.TARGET}\" target"
.endif

View File

@ -59,10 +59,10 @@ LIB32WMAKEFLAGS+= -DCOMPAT_32BIT
# -------------------------------------------------------------------
# soft-fp world
.if ${TARGET_ARCH} == "armv6"
.if ${TARGET_ARCH:Marmv[67]*} != ""
LIBSOFTCFLAGS= -DCOMPAT_SOFTFP
LIBSOFTCPUFLAGS= -mfloat-abi=softfp
LIBSOFTWMAKEENV= CPUTYPE=soft MACHINE=arm MACHINE_ARCH=armv6
LIBSOFTWMAKEENV= CPUTYPE=soft MACHINE=arm MACHINE_ARCH=${TARGET_ARCH}
LIBSOFTWMAKEFLAGS= -DCOMPAT_SOFTFP
.endif
@ -70,7 +70,7 @@ LIBSOFTWMAKEFLAGS= -DCOMPAT_SOFTFP
# Generic code for each type.
# Set defaults based on type.
libcompat= ${LIBCOMPAT:tl}
_LIBCOMPAT_MAKEVARS= _OBJTREE TMP CPUFLAGS CFLAGS CXXFLAGS WMAKEENV \
_LIBCOMPAT_MAKEVARS= _OBJTOP TMP CPUFLAGS CFLAGS CXXFLAGS WMAKEENV \
WMAKEFLAGS WMAKE
.for _var in ${_LIBCOMPAT_MAKEVARS}
.if !empty(LIB${LIBCOMPAT}${_var})
@ -79,8 +79,8 @@ LIBCOMPAT${_var}?= ${LIB${LIBCOMPAT}${_var}}
.endfor
# Shared flags
LIBCOMPAT_OBJTREE?= ${OBJTREE}${.CURDIR}/world${libcompat}
LIBCOMPATTMP?= ${OBJTREE}${.CURDIR}/lib${libcompat}
LIBCOMPAT_OBJTOP?= ${OBJTOP}/obj-lib${libcompat}
LIBCOMPATTMP?= ${LIBCOMPAT_OBJTOP}/tmp
LIBCOMPATCFLAGS+= ${LIBCOMPATCPUFLAGS} \
-L${LIBCOMPATTMP}/usr/lib${libcompat} \
@ -107,7 +107,7 @@ LIBCOMPATCXXFLAGS+= -isystem ${LIBCOMPATTMP}/usr/include/c++/v1 -std=c++11 \
.endif
# Yes, the flags are redundant.
LIBCOMPATWMAKEENV+= MAKEOBJDIRPREFIX=${LIBCOMPAT_OBJTREE} \
LIBCOMPATWMAKEENV+= \
INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${TMPPATH} \
SYSROOT=${LIBCOMPATTMP} \
@ -127,6 +127,9 @@ LIBCOMPATWMAKEFLAGS+= CC="${XCC} ${LIBCOMPATCFLAGS}" \
-DNO_LINT \
MK_TESTS=no
LIBCOMPATWMAKE+= ${LIBCOMPATWMAKEENV} ${MAKE} ${LIBCOMPATWMAKEFLAGS} \
OBJTOP=${LIBCOMPAT_OBJTOP} \
OBJROOT='$${OBJTOP}/' \
MAKEOBJDIRPREFIX= \
MK_MAN=no MK_HTML=no
LIBCOMPATIMAKE+= ${LIBCOMPATWMAKE:NINSTALL=*:NDESTDIR=*} \
MK_TOOLCHAIN=no ${IMAKE_INSTALL} \
@ -148,6 +151,16 @@ build${libcompat}: .PHONY
@echo "--------------------------------------------------------------"
@echo ">>> stage 5.1: building lib${libcompat} shim libraries"
@echo "--------------------------------------------------------------"
.if !defined(NO_CLEAN)
rm -rf ${LIBCOMPATTMP}
.else
.if exists(${LIBCOMPATTMP})
${_+_}cd ${.CURDIR}; ${WMAKE} -DBATCH_DELETE_OLD_FILES \
DESTDIR=${LIBCOMPATTMP} \
delete-old delete-old-libs >/dev/null
.endif
.endif # !defined(NO_CLEAN)
mkdir -p ${LIBCOMPATTMP}/usr/include
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
-p ${LIBCOMPATTMP}/usr >/dev/null
@ -173,16 +186,21 @@ build${libcompat}: .PHONY
${_+_}cd ${.CURDIR}/${_dir}; \
WORLDTMP=${WORLDTMP} \
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \
MAKEOBJDIRPREFIX=${LIBCOMPAT_OBJTREE} ${MAKE} SSP_CFLAGS= DESTDIR= \
${MAKE} SSP_CFLAGS= DESTDIR= \
OBJTOP=${LIBCOMPAT_OBJTOP} \
OBJROOT='$${OBJTOP}/' \
MAKEOBJDIRPREFIX= \
DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \
build-tools
.endfor
${_+_}cd ${.CURDIR}; \
${LIBCOMPATWMAKE} -f Makefile.inc1 -DNO_FSCHG libraries
.if ${libcompat} == "32" && !defined(NO_RTLD)
.if ${libcompat} == "32"
.for _t in ${_obj} all
.if !defined(NO_RTLD)
${_+_}cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIBCOMPATWMAKE} \
-DNO_FSCHG DIRPRFX=libexec/rtld-elf/ ${_t}
.endif
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIBCOMPATWMAKE} \
DIRPRFX=usr.bin/ldd ${_t}
.endfor
@ -192,9 +210,11 @@ distribute${libcompat} install${libcompat}: .PHONY
.for _dir in ${_LC_LIBDIRS.yes}
${_+_}cd ${.CURDIR}/${_dir}; ${LIBCOMPATIMAKE} ${.TARGET:S/${libcompat}$//}
.endfor
.if ${libcompat} == "32" && !defined(NO_RTLD)
.if ${libcompat} == "32"
.if !defined(NO_RTLD)
${_+_}cd ${.CURDIR}/libexec/rtld-elf; \
PROG=ld-elf32.so.1 ${LIBCOMPATIMAKE} ${.TARGET:S/32$//}
.endif
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIBCOMPATIMAKE} \
${.TARGET:S/32$//}
.endif

View File

@ -38,16 +38,205 @@
# xargs -n1 | sort | uniq -d;
# done
# 20171108: badsect(8) removal
OLD_FILES+=sbin/badsect
OLD_FILES+=rescue/badsect
OLD_FILES+=usr/share/man/man8/badsect.8.gz
# 20171105: fixing lib/libclang_rt CRTARCH for arm:armv[67].
.if ${MACHINE} == "arm"
.if ${MACHINE_ARCH:Marmv[67]*} != "" && ${CPUTYPE:M*soft*} == ""
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.asan-preinit-arm.a
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.asan-arm.a
OLD_LIBS+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.asan-arm.so
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.asan_cxx-arm.a
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.profile-arm.a
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.safestack-arm.a
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.stats-arm.a
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.stats_client-arm.a
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.ubsan_standalone-arm.a
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.ubsan_standalone_cxx-arm.a
.endif
.endif
# 20171104: libcap_random should be in /lib not in /usr/lib
OLD_LIBS+=usr/lib/libcap_random.so.0
# 20171104: Casper can work only as shared library
OLD_FILES+=usr/lib/libcasper.a
OLD_FILES+=usr/lib/libcasper_p.a
OLD_FILES+=usr/lib/libcap_dns.a
OLD_FILES+=usr/lib/libcap_dns_p.a
OLD_FILES+=usr/lib/libcap_grp.a
OLD_FILES+=usr/lib/libcap_grp_p.a
OLD_FILES+=usr/lib/libcap_pwd.a
OLD_FILES+=usr/lib/libcap_pwd_p.a
OLD_FILES+=usr/lib/libcap_random.a
OLD_FILES+=usr/lib/libcap_random_p.a
OLD_FILES+=usr/lib/libcap_sysctl.a
OLD_FILES+=usr/lib/libcap_sysctl_p.a
# 20171031: Removal of obsolete man files
OLD_FILES+=usr/share/man/man7/adding_user.7.gz
# 20171031: Disconnected libpathconv tests
OLD_DIRS+=usr/tests/lib/libpathconv
# 20171017: Removal of mbpool(9)
OLD_FILES+=usr/include/sys/mbpool.h
OLD_FILES+=usr/share/man/man9/mbpool.9.gz
OLD_FILES+=usr/share/man/man9/mbp_destroy.9.gz
OLD_FILES+=usr/share/man/man9/mbp_alloc.9.gz
OLD_FILES+=usr/share/man/man9/mbp_ext_free.9.gz
OLD_FILES+=usr/share/man/man9/mbp_count.9.gz
OLD_FILES+=usr/share/man/man9/mbp_card_free.9.gz
OLD_FILES+=usr/share/man/man9/mbp_get_keep.9.gz
OLD_FILES+=usr/share/man/man9/mbp_free.9.gz
OLD_FILES+=usr/share/man/man9/mbp_get.9.gz
OLD_FILES+=usr/share/man/man9/mbp_create.9.gz
OLD_FILES+=usr/share/man/man9/mbp_sync.9.gz
# 20171010: Remove libstand
OLD_FILES+=usr/lib/libstand.a
OLD_FILES+=usr/lib/libstand_p.a
OLD_FILES+=usr/include/stand.h
OLD_FILES+=usr/share/man/man3/libstand.3
# 20171003: remove RCMDS
OLD_FILES+=bin/rcp
OLD_FILES+=rescue/rcp
OLD_FILES+=usr/bin/rlogin
OLD_FILES+=usr/bin/rsh
OLD_FILES+=usr/libexec/rlogind
OLD_FILES+=usr/libexec/rshd
OLD_FILES+=usr/share/man/man1/rcp.1.gz
OLD_FILES+=usr/share/man/man1/rlogin.1.gz
OLD_FILES+=usr/share/man/man1/rsh.1.gz
OLD_FILES+=usr/share/man/man8/rlogind.8.gz
OLD_FILES+=usr/share/man/man8/rshd.8.gz
# 20170927: crshared
OLD_FILES+=usr/share/man/man9/crshared.9.gz
# 20170927: procctl
OLD_FILES+=usr/share/man/man8/procctl.8.gz
OLD_FILES+=usr/sbin/procctl
# 20170926: remove unneeded man aliases and locales directory
OLD_FILES+=usr/share/man/en.ISO8859-1/man1
OLD_FILES+=usr/share/man/en.ISO8859-1/man2
OLD_FILES+=usr/share/man/en.ISO8859-1/man3
OLD_FILES+=usr/share/man/en.ISO8859-1/man4
OLD_FILES+=usr/share/man/en.ISO8859-1/man5
OLD_FILES+=usr/share/man/en.ISO8859-1/man6
OLD_FILES+=usr/share/man/en.ISO8859-1/man7
OLD_FILES+=usr/share/man/en.ISO8859-1/man8
OLD_FILES+=usr/share/man/en.ISO8859-1/man9
OLD_DIRS+=usr/share/man/en.ISO8859-1
OLD_FILES+=usr/share/man/en.ISO8859-1/mandoc.db
OLD_FILES+=usr/share/man/en.UTF-8/man1
OLD_FILES+=usr/share/man/en.UTF-8/man2
OLD_FILES+=usr/share/man/en.UTF-8/man3
OLD_FILES+=usr/share/man/en.UTF-8/man4
OLD_FILES+=usr/share/man/en.UTF-8/man5
OLD_FILES+=usr/share/man/en.UTF-8/man6
OLD_FILES+=usr/share/man/en.UTF-8/man7
OLD_FILES+=usr/share/man/en.UTF-8/man8
OLD_FILES+=usr/share/man/en.UTF-8/man9
OLD_FILES+=usr/share/man/en.UTF-8/mandoc.db
OLD_DIRS+=usr/share/man/en.UTF-8
OLD_FILES+=usr/share/man/en.ISO8859-15
OLD_FILES+=usr/share/openssl/man/en.ISO8859-1/man1
OLD_FILES+=usr/share/openssl/man/en.ISO8859-1/man3
OLD_FILES+=usr/share/openssl/man/en.ISO8859-1/mandoc.db
OLD_DIRS+=usr/share/openssl/man/en.ISO8859-1
OLD_FILES+=usr/share/openssl/man/en.ISO8859-15
OLD_DIRS+=usr/share/man/ja/man1
OLD_DIRS+=usr/share/man/ja/man2
OLD_DIRS+=usr/share/man/ja/man3
OLD_DIRS+=usr/share/man/ja/man4
OLD_DIRS+=usr/share/man/ja/man5
OLD_DIRS+=usr/share/man/ja/man6
OLD_DIRS+=usr/share/man/ja/man7
OLD_DIRS+=usr/share/man/ja/man8
OLD_DIRS+=usr/share/man/ja/man9
OLD_DIRS+=usr/share/man/ja
# 20170913: remove unneeded catman utility
OLD_FILES+=etc/periodic/weekly/330.catman
OLD_FILES+=usr/bin/catman
OLD_FILES+=usr/libexec/catman.local
OLD_FILES+=usr/share/man/man1/catman.1.gz
OLD_FILES+=usr/share/man/man8/catman.local.8.gz
OLD_DIRS+=usr/share/man/cat1
OLD_DIRS+=usr/share/man/cat2
OLD_DIRS+=usr/share/man/cat3
OLD_DIRS+=usr/share/man/cat4/amd64
OLD_DIRS+=usr/share/man/cat4/arm
OLD_DIRS+=usr/share/man/cat4/i386
OLD_DIRS+=usr/share/man/cat4/powerpc
OLD_DIRS+=usr/share/man/cat4/sparc64
OLD_DIRS+=usr/share/man/cat4
OLD_DIRS+=usr/share/man/cat5
OLD_DIRS+=usr/share/man/cat6
OLD_DIRS+=usr/share/man/cat7
OLD_DIRS+=usr/share/man/cat8/amd64
OLD_DIRS+=usr/share/man/cat8/arm
OLD_DIRS+=usr/share/man/cat8/i386
OLD_DIRS+=usr/share/man/cat8/powerpc
OLD_DIRS+=usr/share/man/cat8/sparc64
OLD_DIRS+=usr/share/man/cat8
OLD_DIRS+=usr/share/man/cat9
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat1
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat2
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat3
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/amd64
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/arm
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/i386
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/powerpc
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/sparc64
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat5
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat6
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat7
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/amd64
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/arm
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/i386
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/powerpc
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/sparc64
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat9
OLD_DIRS+=usr/share/man/en.UTF-8/cat1
OLD_DIRS+=usr/share/man/en.UTF-8/cat2
OLD_DIRS+=usr/share/man/en.UTF-8/cat3
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/amd64
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/arm
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/i386
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/powerpc
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/sparc64
OLD_DIRS+=usr/share/man/en.UTF-8/cat4
OLD_DIRS+=usr/share/man/en.UTF-8/cat5
OLD_DIRS+=usr/share/man/en.UTF-8/cat6
OLD_DIRS+=usr/share/man/en.UTF-8/cat7
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/amd64
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/arm
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/i386
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/powerpc
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/sparc64
OLD_DIRS+=usr/share/man/en.UTF-8/cat8
OLD_DIRS+=usr/share/man/en.UTF-8/cat9
OLD_DIRS+=usr/share/man/ja/cat1
OLD_DIRS+=usr/share/man/ja/cat2
OLD_DIRS+=usr/share/man/ja/cat3
OLD_DIRS+=usr/share/man/ja/cat4/amd64
OLD_DIRS+=usr/share/man/ja/cat4/arm
OLD_DIRS+=usr/share/man/ja/cat4/i386
OLD_DIRS+=usr/share/man/ja/cat4/powerpc
OLD_DIRS+=usr/share/man/ja/cat4/sparc64
OLD_DIRS+=usr/share/man/ja/cat4
OLD_DIRS+=usr/share/man/ja/cat5
OLD_DIRS+=usr/share/man/ja/cat6
OLD_DIRS+=usr/share/man/ja/cat7
OLD_DIRS+=usr/share/man/ja/cat8/amd64
OLD_DIRS+=usr/share/man/ja/cat8/arm
OLD_DIRS+=usr/share/man/ja/cat8/powerpc
OLD_DIRS+=usr/share/man/ja/cat8/sparc64
OLD_DIRS+=usr/share/man/ja/cat8
OLD_DIRS+=usr/share/man/ja/cat9
OLD_DIRS+=usr/share/openssl/man/cat1
OLD_DIRS+=usr/share/openssl/man/cat3
OLD_DIRS+=usr/share/openssl/man/en.ISO8859-1/cat1
OLD_DIRS+=usr/share/openssl/man/en.ISO8859-1/cat3
# 20170802: ksyms(4) ioctl interface was removed
OLD_FILES+=usr/include/sys/ksyms.h
# 20170722: new clang import which bumps version from 4.0.0 to 5.0.0.
OLD_FILES+=usr/lib/clang/4.0.0/include/sanitizer/allocator_interface.h
OLD_FILES+=usr/lib/clang/4.0.0/include/sanitizer/asan_interface.h

6
README
View File

@ -9,7 +9,7 @@ more information).
The Makefile in this directory supports a number of targets for
building components (or all) of the FreeBSD source tree. See build(7)
and http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
and https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
for more information, including setting make(1) variables.
The `buildkernel` and `installkernel` targets build and install
@ -18,7 +18,7 @@ the Makefile in this directory for more information on the
standard build targets and compile-time flags.
Building a kernel is a somewhat more involved process. See build(7), config(8),
and http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
and https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
for more information.
Note: If you want to build and install the kernel with the
@ -81,4 +81,4 @@ usr.sbin System administration commands.
For information on synchronizing your source tree with one or more of
the FreeBSD Project's development branches, please see:
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/updating-src.html
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/current-stable.html

View File

@ -11,7 +11,7 @@ more information).
The Makefile in this directory supports a number of targets for
building components (or all) of the FreeBSD source tree. See build(7)
and http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
and https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
for more information, including setting make(1) variables.
The `buildkernel` and `installkernel` targets build and install
@ -20,7 +20,7 @@ the Makefile in this directory for more information on the
standard build targets and compile-time flags.
Building a kernel is a somewhat more involved process. See build(7), config(8),
and http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
and https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
for more information.
Note: If you want to build and install the kernel with the
@ -83,4 +83,4 @@ usr.sbin System administration commands.
For information on synchronizing your source tree with one or more of
the FreeBSD Project's development branches, please see:
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/synching.html
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/current-stable.html

View File

@ -6,7 +6,7 @@ COMMON ITEMS: section later in the file. These instructions assume that you
basically know what you are doing. If not, then please consult the FreeBSD
handbook:
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/updating-src.html
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/current-stable.html
Items affecting the ports and packages system can be found in
/usr/ports/UPDATING. Please read that file before running portupgrade.
@ -51,6 +51,60 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
****************************** SPECIAL WARNING: ******************************
20171106:
The naive and non-compliant support of posix_fallocate(2) in ZFS
has been removed as of r325320. The system call now returns EINVAL
when used on a ZFS file. Although the new behavior complies with the
standard, some consumers are not prepared to cope with it.
One known victim is lld prior to r325420.
20171102:
Building in a FreeBSD src checkout will automatically create object
directories now rather than store files in the current directory if
'make obj' was not ran. Calling 'make obj' is no longer necesarry.
This feature can be disabled by setting WITHOUT_AUTO_OBJ=yes in
/etc/src-env.conf (not /etc/src.conf), or passing the option in the
environment.
20171101:
The default MAKEOBJDIR has changed from /usr/obj/<srcdir> for native
builds, and /usr/obj/<arch>/<srcdir> for cross-builds, to a unified
/usr/obj/<srcdir>/<arch>. This behavior can be changed to the old
format by setting WITHOUT_UNIFIED_OBJDIR=yes in /etc/src-env.conf,
the environment, or with -DWITHOUT_UNIFIED_OBJDIR when building.
The UNIFIED_OBJDIR option is a transitional feature that will be
removed for 12.0 release; please migrate to the new format for any
tools by looking up the OBJDIR used by 'make -V .OBJDIR' means rather
than hardcoding paths.
20171028:
The native-xtools target no longer installs the files by default to the
OBJDIR. Use the native-xtools-install target with a DESTDIR to install
to ${DESTDIR}/${NXTP} where NXTP defaults to /nxb-bin.
20171021:
As part of the boot loader infrastructure cleanup, LOADER_*_SUPPORT
options are changing from controlling the build if defined / undefined
to controlling the build with explicit 'yes' or 'no' values. They will
shift to WITH/WITHOUT options to match other options in the system.
20171010:
libstand has turned into a private library for sys/boot use only.
It is no longer supported as a public interface outside of sys/boot.
20171005:
The arm port has split armv6 into armv6 and armv7. armv7 is now
a valid TARGET_ARCH/MACHINE_ARCH setting. If you have an armv7 system
and are running a kernel from before r324363, you will need to add
MACHINE_ARCH=armv7 to 'make buildworld' to do a native build.
20171003:
When building multiple kernels using KERNCONF, non-existent KERNCONF
files will produce an error and buildkernel will fail. Previously
missing KERNCONF files silently failed giving no indication as to
why, only to subsequently discover during installkernel that the
desired kernel was never built in the first place.
20170912:
The default serial number format for CTL LUNs has changed. This will
affect users who use /dev/diskid/* device nodes, or whose FibreChannel
@ -66,8 +120,8 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
soft-float everything else should be affected.
20170826:
During boot the geli passphrase will be hidden. To restore previous
behavior see geli(8) configuration options.
The geli password typed at boot is now hidden. To restore the previous
behavior, see geli(8) for configuration options.
20170825:
Move PMTUD blackhole counters to TCPSTATS and remove them from bare
@ -1815,21 +1869,6 @@ COMMON ITEMS:
make installkernel KERNCONF=YOUR_KERNEL_HERE KODIR=/boot/testkernel
nextboot -k testkernel
To just build a kernel when you know that it won't mess you up
--------------------------------------------------------------
This assumes you are already running a CURRENT system. Replace
${arch} with the architecture of your machine (e.g. "i386",
"arm", "amd64", "ia64", "pc98", "sparc64", "powerpc", "mips", etc).
cd src/sys/${arch}/conf
config KERNEL_NAME_HERE
cd ../compile/KERNEL_NAME_HERE
make depend
make
make install
If this fails, go to the "To build a kernel" section.
To rebuild everything and install it on the current system.
-----------------------------------------------------------
# Note: sometimes if you are running current you gotta do more than
@ -1837,7 +1876,8 @@ COMMON ITEMS:
<make sure you have good level 0 dumps>
make buildworld
make kernel KERNCONF=YOUR_KERNEL_HERE
make buildkernel KERNCONF=YOUR_KERNEL_HERE
make installkernel KERNCONF=YOUR_KERNEL_HERE
[1]
<reboot in single user> [3]
mergemaster -Fp [5]
@ -1937,10 +1977,7 @@ COMMON ITEMS:
Make sure that you merge any new devices from GENERIC since the
last time you updated your kernel config file.
[9] When checking out sources, you must include the -P flag to have
cvs prune empty directories.
If CPUTYPE is defined in your /etc/make.conf, make sure to use the
[9] If CPUTYPE is defined in your /etc/make.conf, make sure to use the
"?=" instead of the "=" assignment operator, so that buildworld can
override the CPUTYPE if it needs to.

View File

@ -40,7 +40,6 @@ SUBDIR= cat \
test \
uuidgen
SUBDIR.${MK_RCMDS}+= rcp
SUBDIR.${MK_SENDMAIL}+= rmail
SUBDIR.${MK_TCSH}+= csh
SUBDIR.${MK_TESTS}+= tests

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -226,10 +226,16 @@ cook_cat(FILE *fp)
} else
gobble = 0;
}
if (nflag && (!bflag || ch != '\n')) {
(void)fprintf(stdout, "%6d\t", ++line);
if (ferror(stdout))
break;
if (nflag) {
if (!bflag || ch != '\n') {
(void)fprintf(stdout, "%6d\t", ++line);
if (ferror(stdout))
break;
} else if (eflag) {
(void)fprintf(stdout, "%6s\t", "");
if (ferror(stdout))
break;
}
}
}
if (ch == '\n') {

View File

@ -17,10 +17,4 @@ ${PACKAGE}FILES+= d_vt_output.out
.include <netbsd-tests.test.mk>
d_align.out: ${TESTSRC}/d_align.out
sed -E -e 's,^[[:space:]]{7}\$$$$,\$$,' < ${.ALLSRC} > ${.TARGET}.tmp
mv ${.TARGET}.tmp ${.TARGET}
CLEANFILES+= d_align.out d_align.out.tmp
.include <bsd.test.mk>

View File

@ -1,6 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
.include <src.opts.mk>
PACKAGE=runtime
PROG= chflags

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/arpa \
include/xlocale \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/protocols \
include/xlocale \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -1,6 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 5/31/93
# $FreeBSD$
.include <src.opts.mk>
PACKAGE=runtime
PROG= mkdir

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -199,7 +199,8 @@ static VAR var[] = {
{"tdaddr", "TDADDR", NULL, "thread-address", 0, kvar, KOFF(ki_tdaddr),
KPTR, "lx", 0},
{"tdev", "TDEV", NULL, "terminal-device", 0, tdev, 0, CHAR, NULL, 0},
{"tdnam", "TDNAM", NULL, "terminal-device-name", LJUST, tdnam, 0, CHAR,
{"tdnam", "", "tdname", NULL, 0, NULL, 0, CHAR, NULL, 0},
{"tdname", "TDNAME", NULL, "thread-name", LJUST, tdnam, 0, CHAR,
NULL, 0},
{"time", "TIME", NULL, "cpu-time", USER, cputime, 0, CHAR, NULL, 0},
{"tpgid", "TPGID", NULL, "terminal-process-gid", 0, kvar,

View File

@ -29,7 +29,7 @@
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
.Dd September 7, 2017
.Dd October 9, 2017
.Dt PS 1
.Os
.Sh NAME
@ -675,6 +675,8 @@ saved UID from a setuid executable
accumulated system CPU time
.It Cm tdaddr
thread address
.It Cm tdname
thread name
.It Cm tdev
control terminal device number
.It Cm time

View File

@ -523,7 +523,11 @@ main(int argc, char *argv[])
*/
nentries = -1;
kp = kvm_getprocs(kd, what, flag, &nentries);
if ((kp == NULL && nentries > 0) || (kp != NULL && nentries < 0))
/*
* Ignore ESRCH to preserve behaviour of "ps -p nonexistent-pid"
* not reporting an error.
*/
if ((kp == NULL && errno != ESRCH) || (kp != NULL && nentries < 0))
xo_errx(1, "%s", kvm_geterr(kd));
nkept = 0;
if (nentries > 0) {

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -1,17 +0,0 @@
# @(#)Makefile 8.1 (Berkeley) 7/19/93
# $FreeBSD$
PACKAGE=rcmds
PROG= rcp
SRCS= rcp.c util.c
CFLAGS+=-DBINDIR=${BINDIR}
PACKAGE=rcmds
BINOWN= root
BINMODE=4555
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
.include <bsd.prog.mk>

View File

@ -1,160 +0,0 @@
.\"-
.\" Copyright (c) 1983, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)rcp.1 8.1 (Berkeley) 5/31/93
.\" $FreeBSD$
.\"
.Dd July 3, 2017
.Dt RCP 1
.Os
.Sh NAME
.Nm rcp
.Nd remote file copy
.Sh SYNOPSIS
.Nm
.Op Fl 46p
.Ar file1 file2
.Nm
.Op Fl 46pr
.Ar
.Ar directory
.Sh DEPRECATION NOTICE
.Nm
is deprecated and will be removed from future versions of the
.Fx
base system.
If
.Nm
is still required, it can be installed from ports or packages
(net/bsdrcmds).
.Sh DESCRIPTION
The
.Nm
utility copies files between machines.
Each
.Ar file
or
.Ar directory
argument is either a remote file name of the
form
.Dq ruser@rhost:path ,
or a local file name (containing no
.Ql :\&
characters,
or a
.Ql /
before any
.Ql :\& Ns
s).
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl 4
Use IPv4 addresses only.
.It Fl 6
Use IPv6 addresses only.
.It Fl p
Cause
.Nm
to attempt to preserve (duplicate) in its copies the modification
times and modes of the source files, ignoring the
.Xr umask 2 .
By default, the mode and owner of
.Ar file2
are preserved if it already existed; otherwise the mode of the source file
modified by the
.Xr umask 2
on the destination host is used.
.It Fl r
If any of the source files are directories,
.Nm
copies each subtree rooted at that name; in this case
the destination must be a directory.
.El
.Pp
If
.Ar path
is not a full path name, it is interpreted relative to
the login directory of the specified user
.Ar ruser
on
.Ar rhost ,
or your current user name if no other remote user name is specified.
A
.Ar path
on a remote host may be quoted (using
.Ql \e ,
.Ql \&" ,
or
.Ql \(aa )
so that the metacharacters are interpreted remotely.
.Pp
The
.Nm
utility does not prompt for passwords; it performs remote execution
via
.Xr rsh 1 ,
and requires the same authorization.
.Pp
The
.Nm
utility handles third party copies, where neither source nor target files
are on the current machine.
.Sh SEE ALSO
.Xr cp 1 ,
.Xr ftp 1 ,
.Xr rlogin 1 ,
.Xr rsh 1 ,
.Xr hosts.equiv 5
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.2 .
The version of
.Nm
described here
has been reimplemented with Kerberos in
.Bx 4.3 Reno .
.Sh BUGS
Does not detect all cases where the target of a copy might
be a file in cases where only a directory should be legal.
.Pp
Is confused by any output generated by commands in a
.Pa .login ,
.Pa .profile ,
or
.Pa .cshrc
file on the remote host.
.Pp
The destination user and hostname may have to be specified as
.Dq rhost.ruser
when the destination machine is running the
.Bx 4.2
version of
.Nm .

View File

@ -1,791 +0,0 @@
/*-
* Copyright (c) 1983, 1990, 1992, 1993
* The Regents of the University of California. All rights reserved.
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* Portions of this software were developed for the FreeBSD Project by
* ThinkSec AS and NAI Labs, the Security Research Division of Network
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
* ("CBOSS"), as part of the DARPA CHATS research program.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
static char const copyright[] =
"@(#) Copyright (c) 1983, 1990, 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)rcp.c 8.2 (Berkeley) 4/2/94";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
#include <paths.h>
#include <pwd.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
#define OPTIONS "46dfprt"
static struct passwd *pwd;
static u_short port;
static uid_t userid;
static int errs, rem;
int iamremote;
static int pflag, iamrecursive, targetshouldbedirectory;
static int family = PF_UNSPEC;
static int argc_copy;
static const char **argv_copy;
static char period[] = ".";
#define CMDNEEDS 64
static char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
int response(void);
void rsource(char *, struct stat *);
void sink(int, char *[]);
void source(int, char *[]);
void tolocal(int, char *[]);
void toremote(char *, int, char *[]);
void usage(void);
int
main(int argc, char *argv[])
{
struct servent *sp;
int ch, fflag, i, tflag;
char *targ;
/*
* Prepare for execing ourselves.
*/
argc_copy = argc + 1;
argv_copy = malloc((argc_copy + 1) * sizeof(*argv_copy));
if (argv_copy == NULL)
err(1, "malloc");
argv_copy[0] = argv[0];
argv_copy[1] = "-K";
for (i = 1; i < argc; ++i) {
argv_copy[i + 1] = strdup(argv[i]);
if (argv_copy[i + 1] == NULL)
errx(1, "strdup: out of memory");
}
argv_copy[argc + 1] = NULL;
fflag = tflag = 0;
while ((ch = getopt(argc, argv, OPTIONS)) != -1)
switch(ch) { /* User-visible flags. */
case '4':
family = PF_INET;
break;
case '6':
family = PF_INET6;
break;
case 'p':
pflag = 1;
break;
case 'r':
iamrecursive = 1;
break;
/* Server options. */
case 'd':
targetshouldbedirectory = 1;
break;
case 'f': /* "from" */
iamremote = 1;
fflag = 1;
break;
case 't': /* "to" */
iamremote = 1;
tflag = 1;
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
sp = getservbyname("shell", "tcp");
if (sp == NULL)
errx(1, "shell/tcp: unknown service");
port = sp->s_port;
if ((pwd = getpwuid(userid = getuid())) == NULL)
errx(1, "unknown user %d", (int)userid);
rem = STDIN_FILENO; /* XXX */
if (fflag) { /* Follow "protocol", send data. */
(void)response();
(void)setuid(userid);
source(argc, argv);
exit(errs);
}
if (tflag) { /* Receive data. */
(void)setuid(userid);
sink(argc, argv);
exit(errs);
}
if (argc < 2)
usage();
if (argc > 2)
targetshouldbedirectory = 1;
rem = -1;
/* Command to be executed on remote system using "rsh". */
(void)snprintf(cmd, sizeof(cmd), "rcp%s%s%s",
iamrecursive ? " -r" : "", pflag ? " -p" : "",
targetshouldbedirectory ? " -d" : "");
(void)signal(SIGPIPE, lostconn);
if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
toremote(targ, argc, argv);
else {
tolocal(argc, argv); /* Dest is local host. */
if (targetshouldbedirectory)
verifydir(argv[argc - 1]);
}
exit(errs);
}
void
toremote(char *targ, int argc, char *argv[])
{
int i, tos;
char *bp, *host, *src, *suser, *thost, *tuser;
*targ++ = 0;
if (*targ == 0)
targ = period;
if ((thost = strchr(argv[argc - 1], '@'))) {
/* user@host */
*thost++ = 0;
tuser = argv[argc - 1];
if (*tuser == '\0')
tuser = NULL;
else if (!okname(tuser))
exit(1);
} else {
thost = argv[argc - 1];
tuser = NULL;
}
for (i = 0; i < argc - 1; i++) {
src = colon(argv[i]);
if (src) { /* remote to remote */
*src++ = 0;
if (*src == 0)
src = period;
host = strchr(argv[i], '@');
if (host) {
*host++ = 0;
suser = argv[i];
if (*suser == '\0')
suser = pwd->pw_name;
else if (!okname(suser)) {
++errs;
continue;
}
if (asprintf(&bp,
"%s %s -l %s -n %s %s '%s%s%s:%s'",
_PATH_RSH, host, suser, cmd, src,
tuser ? tuser : "", tuser ? "@" : "",
thost, targ) == -1)
err(1, "asprintf");
} else
if (asprintf(&bp,
"exec %s %s -n %s %s '%s%s%s:%s'",
_PATH_RSH, argv[i], cmd, src,
tuser ? tuser : "", tuser ? "@" : "",
thost, targ) == -1)
err(1, "asprintf");
(void)susystem(bp, userid);
(void)free(bp);
} else { /* local to remote */
if (rem == -1) {
if (asprintf(&bp, "%s -t %s", cmd, targ)
== -1)
err(1, "asprintf");
host = thost;
rem = rcmd_af(&host, port,
pwd->pw_name,
tuser ? tuser : pwd->pw_name,
bp, 0, family);
if (rem < 0)
exit(1);
if (family == PF_INET) {
tos = IPTOS_THROUGHPUT;
if (setsockopt(rem, IPPROTO_IP, IP_TOS,
&tos, sizeof(int)) < 0)
warn("TOS (ignored)");
}
if (response() < 0)
exit(1);
(void)free(bp);
(void)setuid(userid);
}
source(1, argv+i);
}
}
}
void
tolocal(int argc, char *argv[])
{
int i, len, tos;
char *bp, *host, *src, *suser;
for (i = 0; i < argc - 1; i++) {
if (!(src = colon(argv[i]))) { /* Local to local. */
len = strlen(_PATH_CP) + strlen(argv[i]) +
strlen(argv[argc - 1]) + 20;
if (!(bp = malloc(len)))
err(1, "malloc");
(void)snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP,
iamrecursive ? " -PR" : "", pflag ? " -p" : "",
argv[i], argv[argc - 1]);
if (susystem(bp, userid))
++errs;
(void)free(bp);
continue;
}
*src++ = 0;
if (*src == 0)
src = period;
if ((host = strchr(argv[i], '@')) == NULL) {
host = argv[i];
suser = pwd->pw_name;
} else {
*host++ = 0;
suser = argv[i];
if (*suser == '\0')
suser = pwd->pw_name;
else if (!okname(suser)) {
++errs;
continue;
}
}
len = strlen(src) + CMDNEEDS + 20;
if ((bp = malloc(len)) == NULL)
err(1, "malloc");
(void)snprintf(bp, len, "%s -f %s", cmd, src);
rem = rcmd_af(&host, port, pwd->pw_name, suser, bp, 0,
family);
(void)free(bp);
if (rem < 0) {
++errs;
continue;
}
(void)seteuid(userid);
if (family == PF_INET) {
tos = IPTOS_THROUGHPUT;
if (setsockopt(rem, IPPROTO_IP, IP_TOS, &tos,
sizeof(int)) < 0)
warn("TOS (ignored)");
}
sink(1, argv + argc - 1);
(void)seteuid(0);
(void)close(rem);
rem = -1;
}
}
void
source(int argc, char *argv[])
{
struct stat stb;
static BUF buffer;
BUF *bp;
off_t i;
int amt, fd, haderr, indx, result;
char *last, *name, buf[BUFSIZ];
for (indx = 0; indx < argc; ++indx) {
name = argv[indx];
if ((fd = open(name, O_RDONLY, 0)) < 0)
goto syserr;
if (fstat(fd, &stb)) {
syserr: run_err("%s: %s", name, strerror(errno));
goto next;
}
switch (stb.st_mode & S_IFMT) {
case S_IFREG:
break;
case S_IFDIR:
if (iamrecursive) {
rsource(name, &stb);
goto next;
}
/* FALLTHROUGH */
default:
run_err("%s: not a regular file", name);
goto next;
}
if ((last = strrchr(name, '/')) == NULL)
last = name;
else
++last;
if (pflag) {
/*
* Make it compatible with possible future
* versions expecting microseconds.
*/
(void)snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n",
(long)stb.st_mtim.tv_sec,
(long)stb.st_atim.tv_sec);
(void)write(rem, buf, strlen(buf));
if (response() < 0)
goto next;
}
#define MODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
(void)snprintf(buf, sizeof(buf), "C%04o %jd %s\n",
stb.st_mode & MODEMASK, (intmax_t)stb.st_size, last);
(void)write(rem, buf, strlen(buf));
if (response() < 0)
goto next;
if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) {
next: if (fd >= 0)
(void)close(fd);
continue;
}
/* Keep writing after an error so that we stay sync'd up. */
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
amt = bp->cnt;
if (i + amt > stb.st_size)
amt = stb.st_size - i;
if (!haderr) {
result = read(fd, bp->buf, amt);
if (result != amt)
haderr = result >= 0 ? EIO : errno;
}
if (haderr)
(void)write(rem, bp->buf, amt);
else {
result = write(rem, bp->buf, amt);
if (result != amt)
haderr = result >= 0 ? EIO : errno;
}
}
if (close(fd) && !haderr)
haderr = errno;
if (!haderr)
(void)write(rem, "", 1);
else
run_err("%s: %s", name, strerror(haderr));
(void)response();
}
}
void
rsource(char *name, struct stat *statp)
{
DIR *dirp;
struct dirent *dp;
char *last, *vect[1], path[PATH_MAX];
if (!(dirp = opendir(name))) {
run_err("%s: %s", name, strerror(errno));
return;
}
last = strrchr(name, '/');
if (last == NULL)
last = name;
else
last++;
if (pflag) {
(void)snprintf(path, sizeof(path), "T%ld 0 %ld 0\n",
(long)statp->st_mtim.tv_sec,
(long)statp->st_atim.tv_sec);
(void)write(rem, path, strlen(path));
if (response() < 0) {
closedir(dirp);
return;
}
}
(void)snprintf(path, sizeof(path),
"D%04o %d %s\n", statp->st_mode & MODEMASK, 0, last);
(void)write(rem, path, strlen(path));
if (response() < 0) {
closedir(dirp);
return;
}
while ((dp = readdir(dirp))) {
if (dp->d_ino == 0)
continue;
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
continue;
if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path)) {
run_err("%s/%s: name too long", name, dp->d_name);
continue;
}
(void)snprintf(path, sizeof(path), "%s/%s", name, dp->d_name);
vect[0] = path;
source(1, vect);
}
(void)closedir(dirp);
(void)write(rem, "E\n", 2);
(void)response();
}
void
sink(int argc, char *argv[])
{
static BUF buffer;
struct stat stb;
struct timeval tv[2];
enum { YES, NO, DISPLAYED } wrerr;
BUF *bp;
off_t i, j, size;
int amt, exists, first, mask, mode, ofd, omode;
size_t count;
int setimes, targisdir, wrerrno = 0;
char ch, *cp, *np, *targ, *vect[1], buf[BUFSIZ], path[PATH_MAX];
const char *why;
#define atime tv[0]
#define mtime tv[1]
#define SCREWUP(str) { why = str; goto screwup; }
setimes = targisdir = 0;
mask = umask(0);
if (!pflag)
(void)umask(mask);
if (argc != 1) {
run_err("ambiguous target");
exit(1);
}
targ = *argv;
if (targetshouldbedirectory)
verifydir(targ);
(void)write(rem, "", 1);
if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
targisdir = 1;
for (first = 1;; first = 0) {
cp = buf;
if (read(rem, cp, 1) <= 0)
return;
if (*cp++ == '\n')
SCREWUP("unexpected <newline>");
do {
if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
SCREWUP("lost connection");
*cp++ = ch;
} while (cp < &buf[BUFSIZ - 1] && ch != '\n');
*cp = 0;
if (buf[0] == '\01' || buf[0] == '\02') {
if (iamremote == 0)
(void)write(STDERR_FILENO,
buf + 1, strlen(buf + 1));
if (buf[0] == '\02')
exit(1);
++errs;
continue;
}
if (buf[0] == 'E') {
(void)write(rem, "", 1);
return;
}
if (ch == '\n')
*--cp = 0;
cp = buf;
if (*cp == 'T') {
setimes++;
cp++;
mtime.tv_sec = strtol(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("mtime.sec not delimited");
mtime.tv_usec = strtol(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("mtime.usec not delimited");
atime.tv_sec = strtol(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("atime.sec not delimited");
atime.tv_usec = strtol(cp, &cp, 10);
if (!cp || *cp++ != '\0')
SCREWUP("atime.usec not delimited");
(void)write(rem, "", 1);
continue;
}
if (*cp != 'C' && *cp != 'D') {
/*
* Check for the case "rcp remote:foo\* local:bar".
* In this case, the line "No match." can be returned
* by the shell before the rcp command on the remote is
* executed so the ^Aerror_message convention isn't
* followed.
*/
if (first) {
run_err("%s", cp);
exit(1);
}
SCREWUP("expected control record");
}
mode = 0;
for (++cp; cp < buf + 5; cp++) {
if (*cp < '0' || *cp > '7')
SCREWUP("bad mode");
mode = (mode << 3) | (*cp - '0');
}
if (*cp++ != ' ')
SCREWUP("mode not delimited");
for (size = 0; isdigit(*cp);)
size = size * 10 + (*cp++ - '0');
if (*cp++ != ' ')
SCREWUP("size not delimited");
if (targisdir) {
if (strlen(targ) + (*targ ? 1 : 0) + strlen(cp)
>= sizeof(path)) {
run_err("%s%s%s: name too long", targ,
*targ ? "/" : "", cp);
exit(1);
}
(void)snprintf(path, sizeof(path), "%s%s%s", targ,
*targ ? "/" : "", cp);
np = path;
} else
np = targ;
exists = stat(np, &stb) == 0;
if (buf[0] == 'D') {
int mod_flag = pflag;
if (exists) {
if (!S_ISDIR(stb.st_mode)) {
errno = ENOTDIR;
goto bad;
}
if (pflag)
(void)chmod(np, mode);
} else {
/* Handle copying from a read-only directory */
mod_flag = 1;
if (mkdir(np, mode | S_IRWXU) < 0)
goto bad;
}
vect[0] = np;
sink(1, vect);
if (setimes) {
setimes = 0;
if (utimes(np, tv) < 0)
run_err("%s: set times: %s",
np, strerror(errno));
}
if (mod_flag)
(void)chmod(np, mode);
continue;
}
omode = mode;
mode |= S_IWRITE;
if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
bad: run_err("%s: %s", np, strerror(errno));
continue;
}
(void)write(rem, "", 1);
if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) {
(void)close(ofd);
continue;
}
cp = bp->buf;
wrerr = NO;
for (count = i = 0; i < size; i += BUFSIZ) {
amt = BUFSIZ;
if (i + amt > size)
amt = size - i;
count += amt;
do {
j = read(rem, cp, amt);
if (j <= 0) {
run_err("%s", j ? strerror(errno) :
"dropped connection");
exit(1);
}
amt -= j;
cp += j;
} while (amt > 0);
if (count == bp->cnt) {
/* Keep reading so we stay sync'd up. */
if (wrerr == NO) {
j = write(ofd, bp->buf, count);
if (j != (off_t)count) {
wrerr = YES;
wrerrno = j >= 0 ? EIO : errno;
}
}
count = 0;
cp = bp->buf;
}
}
if (count != 0 && wrerr == NO &&
(j = write(ofd, bp->buf, count)) != (off_t)count) {
wrerr = YES;
wrerrno = j >= 0 ? EIO : errno;
}
if (ftruncate(ofd, size)) {
run_err("%s: truncate: %s", np, strerror(errno));
wrerr = DISPLAYED;
}
if (pflag) {
if (exists || omode != mode)
if (fchmod(ofd, omode))
run_err("%s: set mode: %s",
np, strerror(errno));
} else {
if (!exists && omode != mode)
if (fchmod(ofd, omode & ~mask))
run_err("%s: set mode: %s",
np, strerror(errno));
}
(void)close(ofd);
(void)response();
if (setimes && wrerr == NO) {
setimes = 0;
if (utimes(np, tv) < 0) {
run_err("%s: set times: %s",
np, strerror(errno));
wrerr = DISPLAYED;
}
}
switch(wrerr) {
case YES:
run_err("%s: %s", np, strerror(wrerrno));
break;
case NO:
(void)write(rem, "", 1);
break;
case DISPLAYED:
break;
}
}
screwup:
run_err("protocol error: %s", why);
exit(1);
}
int
response(void)
{
char ch, *cp, resp, rbuf[BUFSIZ];
if (read(rem, &resp, sizeof(resp)) != sizeof(resp))
lostconn(0);
cp = rbuf;
switch(resp) {
case 0: /* ok */
return (0);
default:
*cp++ = resp;
/* FALLTHROUGH */
case 1: /* error, followed by error msg */
case 2: /* fatal error, "" */
do {
if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
lostconn(0);
*cp++ = ch;
} while (cp < &rbuf[BUFSIZ] && ch != '\n');
if (!iamremote)
(void)write(STDERR_FILENO, rbuf, cp - rbuf);
++errs;
if (resp == 1)
return (-1);
exit(1);
}
/* NOTREACHED */
}
void
usage(void)
{
(void)fprintf(stderr, "%s\n%s\n",
"usage: rcp [-46p] file1 file2",
" rcp [-46pr] file ... directory");
exit(1);
}
#include <stdarg.h>
void
run_err(const char *fmt, ...)
{
static FILE *fp;
va_list ap;
++errs;
if (fp == NULL && !(fp = fdopen(rem, "w")))
return;
(void)fprintf(fp, "%c", 0x01);
(void)fprintf(fp, "rcp: ");
va_start(ap, fmt);
(void)vfprintf(fp, fmt, ap);
va_end(ap);
(void)fprintf(fp, "\n");
(void)fflush(fp);
if (!iamremote) {
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
}
}

View File

@ -1,5 +0,0 @@
# $FreeBSD$
ATF_TESTS_SH+= rcp_test
.include <bsd.test.mk>

View File

@ -1,60 +0,0 @@
#
# Copyright 2017 Shivansh Rai
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
usage_output='usage: rcp'
atf_test_case invalid_usage
invalid_usage_head()
{
atf_set "descr" "Verify that an invalid usage with a supported option produces a valid error message"
}
invalid_usage_body()
{
atf_check -s not-exit:0 -e match:"$usage_output" rcp -4
atf_check -s not-exit:0 -e match:"$usage_output" rcp -6
atf_check -s not-exit:0 -e match:"$usage_output" rcp -p
atf_check -s not-exit:0 -e match:"$usage_output" rcp -r
}
atf_test_case no_arguments
no_arguments_head()
{
atf_set "descr" "Verify that rcp(1) fails and generates a valid usage message when no arguments are supplied"
}
no_arguments_body()
{
atf_check -s not-exit:0 -e match:"$usage_output" rcp
}
atf_init_test_cases()
{
atf_add_test_case invalid_usage
atf_add_test_case no_arguments
}

View File

@ -1,159 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static const char sccsid[] = "@(#)util.c 8.2 (Berkeley) 4/2/94";
#endif
#endif /* not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
char *
colon(char *cp)
{
if (*cp == ':') /* Leading colon is part of file name. */
return (0);
for (; *cp; ++cp) {
if (*cp == ':')
return (cp);
if (*cp == '/')
return (0);
}
return (0);
}
void
verifydir(char *cp)
{
struct stat stb;
if (!stat(cp, &stb)) {
if (S_ISDIR(stb.st_mode))
return;
errno = ENOTDIR;
}
run_err("%s: %s", cp, strerror(errno));
exit(1);
}
int
okname(char *cp0)
{
int c;
char *cp;
cp = cp0;
do {
c = *cp;
if (c & 0200)
goto bad;
if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
goto bad;
} while (*++cp);
return (1);
bad: warnx("%s: invalid user name", cp0);
return (0);
}
int
susystem(char *s, int userid)
{
sig_t istat, qstat;
int status;
pid_t pid;
pid = vfork();
switch (pid) {
case -1:
return (127);
case 0:
(void)setuid(userid);
execl(_PATH_BSHELL, "sh", "-c", s, (char *)NULL);
_exit(127);
}
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
if (waitpid(pid, &status, 0) < 0)
status = -1;
(void)signal(SIGINT, istat);
(void)signal(SIGQUIT, qstat);
return (status);
}
BUF *
allocbuf(BUF *bp, int fd, int blksize)
{
struct stat stb;
size_t size;
if (fstat(fd, &stb) < 0) {
run_err("fstat: %s", strerror(errno));
return (0);
}
size = roundup(stb.st_blksize, blksize);
if (size == 0)
size = blksize;
if (bp->cnt >= size)
return (bp);
if ((bp->buf = realloc(bp->buf, size)) == NULL) {
bp->cnt = 0;
run_err("%s", strerror(errno));
return (0);
}
bp->cnt = size;
return (bp);
}
void
lostconn(int signo __unused)
{
if (!iamremote)
warnx("lost connection");
exit(1);
}

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
lib/${CSU_DIR} \
lib/libc \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -515,7 +515,7 @@ check(const char *path, const char *name, struct stat *sp)
"%s: -P was specified, but file is not writable",
path);
(void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
modep + 1, modep[9] == ' ' ? "" : " ",
modep + 1, modep[10] == ' ' ? "" : " ",
user_from_uid(sp->st_uid, 0),
group_from_gid(sp->st_gid, 0),
*flagsp ? flagsp : "", *flagsp ? " " : "",

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -1,9 +1,10 @@
# @(#)Makefile 8.1 (Berkeley) 5/31/93
# $FreeBSD$
.include <src.opts.mk>
PACKAGE=runtime
PROG= rmdir
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
lib/${CSU_DIR} \
lib/libc \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
lib/${CSU_DIR} \
lib/libc \

View File

@ -35,13 +35,13 @@ main(int argc, char **argv)
sigset_t ss;
(void) sigemptyset(&ss);
(void) sigaddset(&ss, SIGINT);
(void) sigaddset(&ss, SIGUSR1);
(void) sigprocmask(SIG_BLOCK, &ss, NULL);
do {
(void) getpid();
(void) sigpending(&ss);
} while (!sigismember(&ss, SIGINT));
} while (!sigismember(&ss, SIGUSR1));
return (0);
}

View File

@ -47,7 +47,7 @@ syscall::getpid:entry
/pid == $1/
{
trace("raised");
raise(SIGINT);
raise(SIGUSR1);
/*
* Wait no more than half a second for the process to die.
*/
@ -55,6 +55,7 @@ syscall::getpid:entry
}
syscall::exit:entry
/pid == $1/
{
exit(0);
}

View File

@ -45,7 +45,7 @@ main(int argc, char **argv)
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
(void) sigaction(SIGINT, &sa, NULL);
(void) sigaction(SIGUSR1, &sa, NULL);
for (;;) {
(void) getpid();

View File

@ -47,7 +47,7 @@ syscall::getpid:return
/pid == $1/
{
trace("raised");
raise(SIGINT);
raise(SIGUSR1);
/*
* Wait no more than half a second for the process to die.
*/
@ -55,6 +55,7 @@ syscall::getpid:return
}
syscall::exit:entry
/pid == $1/
{
exit(0);
}

View File

@ -45,7 +45,7 @@ main(int argc, char **argv)
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
(void) sigaction(SIGINT, &sa, NULL);
(void) sigaction(SIGUSR1, &sa, NULL);
for (;;) {
(void) getpid();

View File

@ -47,7 +47,7 @@ syscall::getpid:entry
/pid == $1/
{
trace("raised");
raise(SIGINT);
raise(SIGUSR1);
/*
* Wait no more than half a second for the process to die.
*/
@ -55,6 +55,7 @@ syscall::getpid:entry
}
syscall::exit:entry
/pid == $1/
{
exit(0);
}

View File

@ -1,6 +1,3 @@
'\" te
.\" Copyright (c) 2012, Martin Matuska <mm@FreeBSD.org>.
.\" All Rights Reserved.
.\"
.\" This file and its contents are supplied under the terms of the
.\" Common Development and Distribution License ("CDDL"), version 1.0.
@ -13,71 +10,75 @@
.\"
.\"
.\" Copyright 2012, Richard Lowe.
.\" Copyright (c) 2012, Marcelo Araujo <araujo@FreeBSD.org>.
.\" Copyright (c) 2012, 2014 by Delphix. All rights reserved.
.\" All Rights Reserved.
.\" Copyright (c) 2012, 2017 by Delphix. All rights reserved.
.\" Copyright 2017 Nexenta Systems, Inc.
.\"
.\" $FreeBSD$
.\"
.Dd July 26, 2014
.Dd October 06, 2017
.Dt ZDB 8
.Os
.Sh NAME
.Nm zdb
.Nd Display zpool debugging and consistency information
.Nd display zpool debugging and consistency information
.Sh SYNOPSIS
.Nm
.Op Fl CumdibcsDvhLMXFPA
.Op Fl e Op Fl p Ar path...
.Op Fl t Ar txg
.Op Fl U Ar cache
.Op Fl AbcdDFGhiLMPsvX
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl I Ar inflight I/Os
.Op Fl x Ar dumpdir
.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 MLXFPA
.Oo Fl o Ar var Ns = Ns Ar value Oc Ns ...
.Op Fl t Ar txg
.Op Fl e Op Fl p Ar path...
.Op Fl U Ar cache
.Ar poolname
.Op Fl x Ar dumpdir
.Op Ar poolname Op Ar object ...
.Nm
.Fl R Op Fl A
.Op Fl e Op Fl p Ar path...
.Op Fl AdiPv
.Op Fl e Oo Fl V Oc 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
.Op Fl uA
.Ar device
.Ar dataset Op Ar object ...
.Nm
.Fl C
.Op Fl A
.Op Fl U Ar cache
.Nm
.Fl E
.Op Fl A
.Ar word0 Ns \&: Ns Ar word1 Ns :...: Ns Ar word15
.Nm
.Fl l
.Op Fl Aqu
.Ar device
.Nm
.Fl m
.Op Fl AFLPX
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl t Ar txg
.Op Fl U Ar cache
.Ar poolname Op Ar vdev Op Ar metaslab ...
.Nm
.Fl O
.Ar dataset path
.Nm
.Fl R
.Op Fl A
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl U Ar cache
.Ar poolname vdev Ns \&: Ns Ar offset Ns \&: Ns Ar size Ns Op : Ns Ar flags
.Nm
.Fl S
.Op Fl AP
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl U Ar cache
.Ar poolname
.Sh DESCRIPTION
The
.Nm
utility displays information about a ZFS pool useful for debugging and
performs some amount of consistency checking.
It is a not a general purpose tool and options (and facilities) may change.
utility displays information about a ZFS pool useful for debugging and performs
some amount of consistency checking.
It is a not a general purpose tool and options
.Pq and facilities
may change.
This is neither a
.Xr fsck 8
nor a
nor an
.Xr fsdb 8
utility.
.Pp
@ -89,73 +90,96 @@ internals is assumed.
If the
.Ar dataset
argument does not contain any
.Sy /
.Qq Sy /
or
.Sy @
.Qq Sy @
characters, it is interpreted as a pool name.
The root dataset can be specified as
.Pa pool Ns Sy /
(pool name followed by a slash).
.Ar pool Ns /
.Pq pool name followed by a slash .
.Pp
When operating on an imported and active pool it is possible, though unlikely,
that zdb may interpret inconsistent pool data and behave erratically.
.Sh OPTIONS
Display options:
.Bl -tag -width indent
.Bl -tag -width Ds
.It Fl b
Display statistics regarding the number, size (logical, physical and
allocated) and deduplication of blocks.
Display statistics regarding the number, size
.Pq logical, physical and allocated
and deduplication of blocks.
.It Fl c
Verify the checksum of all metadata blocks while printing block statistics
(see
.Fl b Ns ).
.Po see
.Fl b
.Pc .
.Pp
If specified multiple times, verify the checksums of all blocks.
.It Fl C
Display information about the configuration. If specified with no other
options, instead display information about the cache file
.Po Pa /etc/zfs/zpool.cache Pc .
Display information about the configuration.
If specified with no other options, instead display information about the cache
file
.Pq Pa /boot/zfs/zpool.cache .
To specify the cache file to display, see
.Fl U
.Fl U .
.Pp
If specified multiple times, and a pool name is also specified display both
the cached configuration and the on-disk configuration.
If specified multiple times, and a pool name is also specified display both the
cached configuration and the on-disk configuration.
If specified multiple times with
.Fl e
also display the configuration that would be used were the pool to be
imported.
also display the configuration that would be used were the pool to be imported.
.It Fl d
Display information about datasets. Specified once, displays basic dataset
information: ID, create transaction, size, and object count.
Display information about datasets.
Specified once, displays basic dataset information: ID, create transaction,
size, and object count.
.Pp
If specified multiple times provides greater and greater verbosity.
.Pp
If object IDs are specified, display information about those specific objects only.
If object IDs are specified, display information about those specific objects
only.
.It Fl D
Display deduplication statistics, including the deduplication ratio (dedup),
compression ratio (compress), inflation due to the zfs copies property
(copies), and an overall effective ratio (dedup * compress / copies).
.Pp
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.
Display deduplication statistics, including the deduplication ratio
.Pq Sy dedup ,
compression ratio
.Pq Sy compress ,
inflation due to the zfs copies property
.Pq Sy copies ,
and an overall effective ratio
.Pq Sy dedup No * Sy compress No / Sy copies .
.It Fl DD
Display a histogram of deduplication statistics, showing the allocated
.Pq physically present on disk
and referenced
.Pq logically referenced in the pool
block counts and sizes by reference count.
.It Fl DDD
Display the statistics independently for each deduplication table.
.It Fl DDDD
Dump the contents of the deduplication tables describing duplicate blocks.
.It Fl DDDDD
Also dump the contents of the deduplication tables describing unique blocks.
.It Fl E Ar word0 Ns \&: Ns Ar word1 Ns :...: Ns Ar word15
Decode and display block from an embedded block pointer specified by the
.Ar word
arguments.
.It Fl h
Display pool history similar to
.Cm zpool history ,
.Nm zpool Cm history ,
but include internal changes, transaction, and dataset information.
.It Fl i
Display information about intent log (ZIL) entries relating to each
dataset.
If specified multiple times, display counts of each intent log transaction
type.
Display information about intent log
.Pq ZIL
entries relating to each dataset.
If specified multiple times, display counts of each intent log transaction type.
.It Fl l Ar device
Display the vdev labels from the specified device.
Read the vdev labels from the specified device.
.Nm Fl l
will return 0 if valid label was found, 1 if error occurred, and 2 if no valid
labels were found.
.Pp
If the
.Fl q
option is also specified, don't print the labels.
.Pp
If the
.Fl u
option is also specified, also display the uberblocks on this device.
@ -166,36 +190,55 @@ By default,
verifies that all non-free blocks are referenced, which can be very expensive.
.It Fl m
Display the offset, spacemap, and free space of each metaslab.
When specified twice, also display information about the on-disk free
space histogram associated with each metaslab. When specified three time,
display the maximum contiguous free space, the in-core free space histogram,
and the percentage of free space in each space map. When specified
four times display every spacemap record.
.It Fl mm
Also display information about the on-disk free space histogram associated with
each metaslab.
.It Fl mmm
Display the maximum contiguous free space, the in-core free space histogram, and
the percentage of free space in each space map.
.It Fl mmmm
Display every spacemap record.
.It Fl M
Display the offset, spacemap, and free space of each metaslab.
When specified twice, also display information about the maximum contiguous
free space and the percentage of free space in each space map.
When specified three times display every spacemap record.
.It Fl MM
Also display information about the maximum contiguous free space and the
percentage of free space in each space map.
.It Fl MMM
Display every spacemap record.
.It Fl O Ar dataset path
Look up the specified
.Ar path
inside of the
.Ar dataset
and display its metadata and indirect blocks.
Specified
.Ar path
must be relative to the root of
.Ar dataset .
This option can be combined with
.Fl v
for increasing verbosity.
.It Xo
.Fl R Ar poolname
.Ar vdev Ns : Ns Ar offset Ns : Ns Ar size Ns Op Ns : Ns Ar flags
.Fl R Ar poolname vdev Ns \&: Ns Ar offset Ns \&: Ns Ar size Ns Op : Ns Ar flags
.Xc
Read and display a block from the specified device. By default the block is
displayed as a hex dump, but see the description of the
.Fl r
Read and display a block from the specified device.
By default the block is displayed as a hex dump, but see the description of the
.Sy r
flag, below.
.Pp
The block is specified in terms of a colon-separated tuple
.Ar vdev
(an integer vdev identifier)
.Pq an integer vdev identifier
.Ar offset
(the offset within the vdev)
.Pq the offset within the vdev
.Ar size
(the size of the block to read) and, optionally,
.Pq the size of the block to read
and, optionally,
.Ar flags
(a set of flags, described below).
.Bl -tag -width indent
.It Sy b offset
.Pq a set of flags, described below .
.Pp
.Bl -tag -compact -width "b offset"
.It Sy b Ar offset
Print block pointer
.It Sy d
Decompress the block
@ -210,19 +253,20 @@ Dump raw uninterpreted block data
.El
.It Fl s
Report statistics on
.Nm Ns 's
.Nm zdb
I/O.
Display operation counts, bandwidth, and error counts of I/O to the pool from
.Nm .
.It Fl S
Simulate the effects of deduplication, constructing a DDT and then display
that DDT as with \fB-DD\fR.
that DDT as with
.Fl DD .
.It Fl u
Display the current uberblock.
.El
.Pp
Other options:
.Bl -tag -width indent
.Bl -tag -width Ds
.It Fl A
Do not abort should any assertion fail.
.It Fl AA
@ -230,28 +274,41 @@ Enable panic recovery, certain errors which would otherwise be fatal are
demoted to warnings.
.It Fl AAA
Do not abort if asserts fail and also enable panic recovery.
.It Fl e Op Fl p Ar path...
.It Fl e Op Fl p Ar path ...
Operate on an exported pool, not present in
.Pa /etc/zfs/zpool.cache .
.Pa /boot/zfs/zpool.cache .
The
.Fl p
flag specifies the path under which devices are to be searched.
.It Fl x Ar dumpdir
All blocks accessed will be copied to files in the specified directory.
The blocks will be placed in sparse files whose name is the same as
that of the file or device read. zdb can be then run on the generated files.
that of the file or device read.
.Nm
can be then run on the generated files.
Note that the
.Fl bbc
flags are sufficient to access (and thus copy)
flags are sufficient to access
.Pq and thus copy
all metadata on the pool.
.It Fl F
Attempt to make an unreadable pool readable by trying progressively older
transactions.
.It Fl G
Dump the contents of the zfs_dbgmsg buffer before exiting
.Nm .
zfs_dbgmsg is a buffer used by ZFS to dump advanced debug information.
.It Fl I 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
The default value is 200.
This option affects the performance of the
.Fl c
option.
.It Fl o Ar var Ns = Ns Ar value ...
Set the given global libzpool variable to the provided value.
The value must be an unsigned 32-bit integer.
Currently only little-endian systems are supported to avoid accidentally setting
the high 32 bits of 64-bit variables.
.It Fl P
Print numbers in an unscaled form more amenable to parsing, eg. 1000000 rather
than 1M.
@ -269,9 +326,14 @@ Use a cache file other than
.It Fl v
Enable verbosity.
Specify multiple times for increased verbosity.
.It Fl V
Attempt verbatim import.
This mimics the behavior of the kernel when loading a pool from a cachefile.
Only usable with
.Fl e .
.It Fl X
Attempt
.Ql extreme
.Qq extreme
transaction rewind, that is attempt the same recovery as
.Fl F
but read transactions otherwise deemed too old.
@ -283,46 +345,58 @@ option, with more occurrences enabling more verbosity.
If no options are specified, all information about the named pool will be
displayed at default verbosity.
.Sh EXAMPLES
.Bl -tag -width 0n
.It Sy Example 1 Display the configuration of imported pool 'rpool'
.Bd -literal -offset 2n
.Li # Ic zdb -C rpool
.Bl -tag -width Ds
.It Xo
.Sy Example 1
Display the configuration of imported pool
.Pa rpool
.Xc
.Bd -literal
# zdb -C rpool
MOS Configuration:
version: 28
name: 'rpool'
...
.Ed
.It Sy Example 2 Display basic dataset information about 'rpool'
.Bd -literal -offset 2n
.Li # Ic zdb -d rpool
.It Xo
.Sy Example 2
Display basic dataset information about
.Pa rpool
.Xc
.Bd -literal
# zdb -d rpool
Dataset mos [META], ID 0, cr_txg 4, 26.9M, 1051 objects
Dataset rpool/swap [ZVOL], ID 59, cr_txg 356, 486M, 2 objects
...
.Ed
.It Xo Sy Example 3 Display basic information about object 0 in
.Sy 'rpool/export/home'
.It Xo
.Sy Example 3
Display basic information about object 0 in
.Pa rpool/export/home
.Xc
.Bd -literal -offset 2n
.Li # Ic zdb -d rpool/export/home 0
.Bd -literal
# zdb -d rpool/export/home 0
Dataset rpool/export/home [ZPL], ID 137, cr_txg 1546, 32K, 8 objects
Object lvl iblk dblk dsize lsize %full type
0 7 16K 16K 15.0K 16K 25.00 DMU dnode
.Ed
.It Xo Sy Example 4 Display the predicted effect of enabling deduplication on
.Sy 'rpool'
.It Xo
.Sy Example 4
Display the predicted effect of enabling deduplication on
.Pa rpool
.Xc
.Bd -literal -offset 2n
.Li # Ic zdb -S rpool
.Bd -literal
# zdb -S rpool
Simulated DDT histogram:
bucket allocated referenced
______ ______________________________ ______________________________
refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE
------ ------ ----- ----- ----- ------ ----- ----- -----
1 694K 27.1G 15.0G 15.0G 694K 27.1G 15.0G 15.0G
2 35.0K 1.33G 699M 699M 74.7K 2.79G 1.45G 1.45G
bucket allocated referenced
______ ______________________________ ______________________________
refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE
------ ------ ----- ----- ----- ------ ----- ----- -----
1 694K 27.1G 15.0G 15.0G 694K 27.1G 15.0G 15.0G
2 35.0K 1.33G 699M 699M 74.7K 2.79G 1.45G 1.45G
...
dedup = 1.11, compress = 1.80, copies = 1.00, dedup * compress / copies = 2.00
.Ed
@ -330,22 +404,3 @@ dedup = 1.11, compress = 1.80, copies = 1.00, dedup * compress / copies = 2.00
.Sh SEE ALSO
.Xr zfs 8 ,
.Xr zpool 8
.Sh AUTHORS
This manual page is a
.Xr mdoc 7
reimplementation of the
.Tn illumos
manual page
.Em zdb(1M) ,
modified and customized for
.Fx
and licensed under the
Common Development and Distribution License
.Pq Tn CDDL .
.Pp
The
.Xr mdoc 7
implementation of this manual page was initially written by
.An Martin Matuska Aq mm@FreeBSD.org
and
.An Marcelo Araujo Aq araujo@FreeBSD.org .

View File

@ -23,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 Nexenta Systems, Inc.
*/
#include <stdio.h>
@ -60,7 +61,9 @@
#include <sys/ddt.h>
#include <sys/zfeature.h>
#include <sys/abd.h>
#include <sys/blkptr.h>
#include <zfs_comutil.h>
#include <libcmdutils.h>
#undef verify
#include <libzfs.h>
@ -120,18 +123,24 @@ static void
usage(void)
{
(void) fprintf(stderr,
"Usage: %s [-CumMdibcsDvhLXFPAG] [-t txg] [-e [-p path...]] "
"[-U config] [-I inflight I/Os] [-x dumpdir] poolname [object...]\n"
" %s [-divPA] [-e -p path...] [-U config] dataset "
"[object...]\n"
" %s -mM [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
"poolname [vdev [metaslab...]]\n"
" %s -R [-A] [-e [-p path...]] poolname "
"vdev:offset:size[:flags]\n"
" %s -S [-PA] [-e [-p path...]] [-U config] poolname\n"
" %s -l [-uA] device\n"
" %s -C [-A] [-U config]\n\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
"Usage:\t%s [-AbcdDFGhiLMPsvX] [-e [-V] [-p <path> ...]] "
"[-I <inflight I/Os>]\n"
"\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
"\t\t[<poolname> [<object> ...]]\n"
"\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>] <dataset> "
"[<object> ...]\n"
"\t%s -C [-A] [-U <cache>]\n"
"\t%s -l [-Aqu] <device>\n"
"\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] "
"[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
"\t%s -O <dataset> <path>\n"
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
"\t%s -E [-A] word0:word1:...:word15\n"
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
"<poolname>\n\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
cmdname, cmdname);
(void) fprintf(stderr, " Dataset name must include at least one "
"separator character '/' or '@'\n");
@ -140,49 +149,57 @@ usage(void)
(void) fprintf(stderr, " If object numbers are specified, only "
"those objects are dumped\n\n");
(void) fprintf(stderr, " Options to control amount of output:\n");
(void) fprintf(stderr, " -u uberblock\n");
(void) fprintf(stderr, " -d dataset(s)\n");
(void) fprintf(stderr, " -i intent logs\n");
(void) fprintf(stderr, " -C config (or cachefile if alone)\n");
(void) fprintf(stderr, " -h pool history\n");
(void) fprintf(stderr, " -b block statistics\n");
(void) fprintf(stderr, " -m metaslabs\n");
(void) fprintf(stderr, " -M metaslab groups\n");
(void) fprintf(stderr, " -c checksum all metadata (twice for "
"all data) blocks\n");
(void) fprintf(stderr, " -s report stats on zdb's I/O\n");
(void) fprintf(stderr, " -C config (or cachefile if alone)\n");
(void) fprintf(stderr, " -d dataset(s)\n");
(void) fprintf(stderr, " -D dedup statistics\n");
(void) fprintf(stderr, " -S simulate dedup to measure effect\n");
(void) fprintf(stderr, " -v verbose (applies to all others)\n");
(void) fprintf(stderr, " -l dump label contents\n");
(void) fprintf(stderr, " -E decode and display block from an "
"embedded block pointer\n");
(void) fprintf(stderr, " -h pool history\n");
(void) fprintf(stderr, " -i intent logs\n");
(void) fprintf(stderr, " -l read label contents\n");
(void) fprintf(stderr, " -L disable leak tracking (do not "
"load spacemaps)\n");
(void) fprintf(stderr, " -m metaslabs\n");
(void) fprintf(stderr, " -M metaslab groups\n");
(void) fprintf(stderr, " -O perform object lookups by path\n");
(void) fprintf(stderr, " -R read and display block from a "
"device\n\n");
"device\n");
(void) fprintf(stderr, " -s report stats on zdb's I/O\n");
(void) fprintf(stderr, " -S simulate dedup to measure effect\n");
(void) fprintf(stderr, " -v verbose (applies to all "
"others)\n\n");
(void) fprintf(stderr, " Below options are intended for use "
"with other options:\n");
(void) fprintf(stderr, " -A ignore assertions (-A), enable "
"panic recovery (-AA) or both (-AAA)\n");
(void) fprintf(stderr, " -F attempt automatic rewind within "
"safe range of transaction groups\n");
(void) fprintf(stderr, " -U <cachefile_path> -- use alternate "
"cachefile\n");
(void) fprintf(stderr, " -X attempt extreme rewind (does not "
"work with dataset)\n");
(void) fprintf(stderr, " -e pool is exported/destroyed/"
"has altroot/not in a cachefile\n");
(void) fprintf(stderr, " -p <path> -- use one or more with "
"-e to specify path to vdev dir\n");
(void) fprintf(stderr, " -x <dumpdir> -- "
"dump all read blocks into specified directory\n");
(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, " -F attempt automatic rewind within "
"safe range of transaction groups\n");
(void) fprintf(stderr, " -G dump zfs_dbgmsg buffer before "
"exiting\n");
(void) fprintf(stderr, " -I <number of inflight I/Os> -- "
"specify the maximum number of "
"checksumming I/Os [default is 200]\n");
(void) fprintf(stderr, " -G dump zfs_dbgmsg buffer before "
"exiting\n");
(void) fprintf(stderr, " -o <variable>=<value> set global "
"variable to an unsigned 32-bit integer value\n");
(void) fprintf(stderr, " -p <path> -- use one or more with "
"-e to specify path to vdev dir\n");
(void) fprintf(stderr, " -P print numbers in parseable form\n");
(void) fprintf(stderr, " -q don't print label contents\n");
(void) fprintf(stderr, " -t <txg> -- highest txg to use when "
"searching for uberblocks\n");
(void) fprintf(stderr, " -u uberblock\n");
(void) fprintf(stderr, " -U <cachefile_path> -- use alternate "
"cachefile\n");
(void) fprintf(stderr, " -V do verbatim import\n");
(void) fprintf(stderr, " -x <dumpdir> -- "
"dump all read blocks into specified directory\n");
(void) fprintf(stderr, " -X attempt extreme rewind (does not "
"work with dataset)\n\n");
(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");
@ -260,12 +277,12 @@ dump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
}
static void
zdb_nicenum(uint64_t num, char *buf)
zdb_nicenum(uint64_t num, char *buf, size_t buflen)
{
if (dump_opt['P'])
(void) sprintf(buf, "%llu", (longlong_t)num);
(void) snprintf(buf, buflen, "%llu", (longlong_t)num);
else
nicenum(num, buf);
nicenum(num, buf, sizeof (buf));
}
const char histo_stars[] = "****************************************";
@ -442,12 +459,17 @@ dump_bpobj(objset_t *os, uint64_t object, void *data, size_t size)
bpobj_phys_t *bpop = data;
char bytes[32], comp[32], uncomp[32];
/* make sure the output won't get truncated */
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
if (bpop == NULL)
return;
zdb_nicenum(bpop->bpo_bytes, bytes);
zdb_nicenum(bpop->bpo_comp, comp);
zdb_nicenum(bpop->bpo_uncomp, uncomp);
zdb_nicenum(bpop->bpo_bytes, bytes, sizeof (bytes));
zdb_nicenum(bpop->bpo_comp, comp, sizeof (comp));
zdb_nicenum(bpop->bpo_uncomp, uncomp, sizeof (uncomp));
(void) printf("\t\tnum_blkptrs = %llu\n",
(u_longlong_t)bpop->bpo_num_blkptrs);
@ -740,7 +762,10 @@ dump_metaslab_stats(metaslab_t *msp)
avl_tree_t *t = &msp->ms_size_tree;
int free_pct = range_tree_space(rt) * 100 / msp->ms_size;
zdb_nicenum(metaslab_block_maxsize(msp), maxbuf);
/* max sure nicenum has enough space */
CTASSERT(sizeof (maxbuf) >= NN_NUMBUF_SZ);
zdb_nicenum(metaslab_block_maxsize(msp), maxbuf, sizeof (maxbuf));
(void) printf("\t %25s %10lu %7s %6s %4s %4d%%\n",
"segments", avl_numnodes(t), "maxsize", maxbuf,
@ -757,7 +782,8 @@ dump_metaslab(metaslab_t *msp)
space_map_t *sm = msp->ms_sm;
char freebuf[32];
zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf);
zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf,
sizeof (freebuf));
(void) printf(
"\tmetaslab %6llu offset %12llx spacemap %6llu free %5s\n",
@ -1340,6 +1366,9 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
time_t crtime;
char nice[32];
/* make sure nicenum has enough space */
CTASSERT(sizeof (nice) >= NN_NUMBUF_SZ);
if (dd == NULL)
return;
@ -1355,15 +1384,15 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(u_longlong_t)dd->dd_origin_obj);
(void) printf("\t\tchild_dir_zapobj = %llu\n",
(u_longlong_t)dd->dd_child_dir_zapobj);
zdb_nicenum(dd->dd_used_bytes, nice);
zdb_nicenum(dd->dd_used_bytes, nice, sizeof (nice));
(void) printf("\t\tused_bytes = %s\n", nice);
zdb_nicenum(dd->dd_compressed_bytes, nice);
zdb_nicenum(dd->dd_compressed_bytes, nice, sizeof (nice));
(void) printf("\t\tcompressed_bytes = %s\n", nice);
zdb_nicenum(dd->dd_uncompressed_bytes, nice);
zdb_nicenum(dd->dd_uncompressed_bytes, nice, sizeof (nice));
(void) printf("\t\tuncompressed_bytes = %s\n", nice);
zdb_nicenum(dd->dd_quota, nice);
zdb_nicenum(dd->dd_quota, nice, sizeof (nice));
(void) printf("\t\tquota = %s\n", nice);
zdb_nicenum(dd->dd_reserved, nice);
zdb_nicenum(dd->dd_reserved, nice, sizeof (nice));
(void) printf("\t\treserved = %s\n", nice);
(void) printf("\t\tprops_zapobj = %llu\n",
(u_longlong_t)dd->dd_props_zapobj);
@ -1373,7 +1402,8 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(u_longlong_t)dd->dd_flags);
#define DO(which) \
zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \
zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice, \
sizeof (nice)); \
(void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
DO(HEAD);
DO(SNAP);
@ -1392,15 +1422,22 @@ dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
char used[32], compressed[32], uncompressed[32], unique[32];
char blkbuf[BP_SPRINTF_LEN];
/* make sure nicenum has enough space */
CTASSERT(sizeof (used) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (compressed) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (uncompressed) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (unique) >= NN_NUMBUF_SZ);
if (ds == NULL)
return;
ASSERT(size == sizeof (*ds));
crtime = ds->ds_creation_time;
zdb_nicenum(ds->ds_referenced_bytes, used);
zdb_nicenum(ds->ds_compressed_bytes, compressed);
zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed);
zdb_nicenum(ds->ds_unique_bytes, unique);
zdb_nicenum(ds->ds_referenced_bytes, used, sizeof (used));
zdb_nicenum(ds->ds_compressed_bytes, compressed, sizeof (compressed));
zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed,
sizeof (uncompressed));
zdb_nicenum(ds->ds_unique_bytes, unique, sizeof (unique));
snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp);
(void) printf("\t\tdir_obj = %llu\n",
@ -1459,12 +1496,15 @@ dump_bptree(objset_t *os, uint64_t obj, char *name)
bptree_phys_t *bt;
dmu_buf_t *db;
/* make sure nicenum has enough space */
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
if (dump_opt['d'] < 3)
return;
VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db));
bt = db->db_data;
zdb_nicenum(bt->bt_bytes, bytes);
zdb_nicenum(bt->bt_bytes, bytes, sizeof (bytes));
(void) printf("\n %s: %llu datasets, %s\n",
name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes);
dmu_buf_rele(db, FTAG);
@ -1496,13 +1536,18 @@ dump_full_bpobj(bpobj_t *bpo, char *name, int indent)
char comp[32];
char uncomp[32];
/* make sure nicenum has enough space */
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
if (dump_opt['d'] < 3)
return;
zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes);
zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes, sizeof (bytes));
if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) {
zdb_nicenum(bpo->bpo_phys->bpo_comp, comp);
zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp);
zdb_nicenum(bpo->bpo_phys->bpo_comp, comp, sizeof (comp));
zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp, sizeof (uncomp));
(void) printf(" %*s: object %llu, %llu local blkptrs, "
"%llu subobjs in object %llu, %s (%s/%s comp)\n",
indent * 8, name,
@ -1556,6 +1601,11 @@ dump_deadlist(dsl_deadlist_t *dl)
char comp[32];
char uncomp[32];
/* make sure nicenum has enough space */
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
if (dump_opt['d'] < 3)
return;
@ -1564,9 +1614,9 @@ dump_deadlist(dsl_deadlist_t *dl)
return;
}
zdb_nicenum(dl->dl_phys->dl_used, bytes);
zdb_nicenum(dl->dl_phys->dl_comp, comp);
zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp);
zdb_nicenum(dl->dl_phys->dl_used, bytes, sizeof (bytes));
zdb_nicenum(dl->dl_phys->dl_comp, comp, sizeof (comp));
zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp, sizeof (uncomp));
(void) printf("\n Deadlist: %s (%s/%s comp)\n",
bytes, comp, uncomp);
@ -1582,8 +1632,9 @@ dump_deadlist(dsl_deadlist_t *dl)
dle = AVL_NEXT(&dl->dl_tree, dle)) {
if (dump_opt['d'] >= 5) {
char buf[128];
(void) snprintf(buf, sizeof (buf), "mintxg %llu -> "
"obj %llu", (longlong_t)dle->dle_mintxg,
(void) snprintf(buf, sizeof (buf),
"mintxg %llu -> obj %llu",
(longlong_t)dle->dle_mintxg,
(longlong_t)dle->dle_bpobj.bpo_object);
dump_full_bpobj(&dle->dle_bpobj, buf, 0);
} else {
@ -1597,8 +1648,55 @@ dump_deadlist(dsl_deadlist_t *dl)
static avl_tree_t idx_tree;
static avl_tree_t domain_tree;
static boolean_t fuid_table_loaded;
static boolean_t sa_loaded;
sa_attr_type_t *sa_attr_table;
static objset_t *sa_os = NULL;
static sa_attr_type_t *sa_attr_table = NULL;
static int
open_objset(const char *path, dmu_objset_type_t type, void *tag, objset_t **osp)
{
int err;
uint64_t sa_attrs = 0;
uint64_t version = 0;
VERIFY3P(sa_os, ==, NULL);
err = dmu_objset_own(path, type, B_TRUE, tag, osp);
if (err != 0) {
(void) fprintf(stderr, "failed to own dataset '%s': %s\n", path,
strerror(err));
return (err);
}
if (dmu_objset_type(*osp) == DMU_OST_ZFS) {
(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZPL_VERSION_STR,
8, 1, &version);
if (version >= ZPL_VERSION_SA) {
(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
8, 1, &sa_attrs);
}
err = sa_setup(*osp, sa_attrs, zfs_attr_table, ZPL_END,
&sa_attr_table);
if (err != 0) {
(void) fprintf(stderr, "sa_setup failed: %s\n",
strerror(err));
dmu_objset_disown(*osp, tag);
*osp = NULL;
}
}
sa_os = *osp;
return (0);
}
static void
close_objset(objset_t *os, void *tag)
{
VERIFY3P(os, ==, sa_os);
if (os->os_sa != NULL)
sa_tear_down(os);
dmu_objset_disown(os, tag);
sa_attr_table = NULL;
sa_os = NULL;
}
static void
fuid_table_destroy()
@ -1670,25 +1768,7 @@ dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
int idx = 0;
int error;
if (!sa_loaded) {
uint64_t sa_attrs = 0;
uint64_t version;
VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR,
8, 1, &version) == 0);
if (version >= ZPL_VERSION_SA) {
VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
8, 1, &sa_attrs) == 0);
}
if ((error = sa_setup(os, sa_attrs, zfs_attr_table,
ZPL_END, &sa_attr_table)) != 0) {
(void) printf("sa_setup failed errno %d, can't "
"display znode contents\n", error);
return;
}
sa_loaded = B_TRUE;
}
VERIFY3P(os, ==, sa_os);
if (sa_handle_get(os, object, NULL, SA_HDL_PRIVATE, &hdl)) {
(void) printf("Failed to get handle for SA znode\n");
return;
@ -1837,6 +1917,13 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
char aux[50];
int error;
/* make sure nicenum has enough space */
CTASSERT(sizeof (iblk) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (dblk) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (lsize) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (asize) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (bonus_size) >= NN_NUMBUF_SZ);
if (*print_header) {
(void) printf("\n%10s %3s %5s %5s %5s %5s %6s %s\n",
"Object", "lvl", "iblk", "dblk", "dsize", "lsize",
@ -1857,11 +1944,11 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
}
dmu_object_info_from_dnode(dn, &doi);
zdb_nicenum(doi.doi_metadata_block_size, iblk);
zdb_nicenum(doi.doi_data_block_size, dblk);
zdb_nicenum(doi.doi_max_offset, lsize);
zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize);
zdb_nicenum(doi.doi_bonus_size, bonus_size);
zdb_nicenum(doi.doi_metadata_block_size, iblk, sizeof (iblk));
zdb_nicenum(doi.doi_data_block_size, dblk, sizeof (dblk));
zdb_nicenum(doi.doi_max_offset, lsize, sizeof (lsize));
zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize, sizeof (asize));
zdb_nicenum(doi.doi_bonus_size, bonus_size, sizeof (bonus_size));
(void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
doi.doi_max_offset);
@ -1924,6 +2011,8 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
for (;;) {
char segsize[32];
/* make sure nicenum has enough space */
CTASSERT(sizeof (segsize) >= NN_NUMBUF_SZ);
error = dnode_next_offset(dn,
0, &start, minlvl, blkfill, 0);
if (error)
@ -1931,7 +2020,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
end = start;
error = dnode_next_offset(dn,
DNODE_FIND_HOLE, &end, minlvl, blkfill, 0);
zdb_nicenum(end - start, segsize);
zdb_nicenum(end - start, segsize, sizeof (segsize));
(void) printf("\t\tsegment [%016llx, %016llx)"
" size %5s\n", (u_longlong_t)start,
(u_longlong_t)end, segsize);
@ -1962,6 +2051,9 @@ dump_dir(objset_t *os)
int print_header = 1;
int i, error;
/* make sure nicenum has enough space */
CTASSERT(sizeof (numbuf) >= NN_NUMBUF_SZ);
dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
dmu_objset_fast_stat(os, &dds);
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
@ -1980,7 +2072,7 @@ dump_dir(objset_t *os)
ASSERT3U(usedobjs, ==, BP_GET_FILL(os->os_rootbp));
zdb_nicenum(refdbytes, numbuf);
zdb_nicenum(refdbytes, numbuf, sizeof (numbuf));
if (verbosity >= 4) {
(void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp ");
@ -2156,44 +2248,154 @@ dump_label_uberblocks(vdev_label_t *lbl, uint64_t ashift)
}
}
static void
static char curpath[PATH_MAX];
/*
* Iterate through the path components, recursively passing
* current one's obj and remaining path until we find the obj
* for the last one.
*/
static int
dump_path_impl(objset_t *os, uint64_t obj, char *name)
{
int err;
int header = 1;
uint64_t child_obj;
char *s;
dmu_buf_t *db;
dmu_object_info_t doi;
if ((s = strchr(name, '/')) != NULL)
*s = '\0';
err = zap_lookup(os, obj, name, 8, 1, &child_obj);
(void) strlcat(curpath, name, sizeof (curpath));
if (err != 0) {
(void) fprintf(stderr, "failed to lookup %s: %s\n",
curpath, strerror(err));
return (err);
}
child_obj = ZFS_DIRENT_OBJ(child_obj);
err = sa_buf_hold(os, child_obj, FTAG, &db);
if (err != 0) {
(void) fprintf(stderr,
"failed to get SA dbuf for obj %llu: %s\n",
(u_longlong_t)child_obj, strerror(err));
return (EINVAL);
}
dmu_object_info_from_db(db, &doi);
sa_buf_rele(db, FTAG);
if (doi.doi_bonus_type != DMU_OT_SA &&
doi.doi_bonus_type != DMU_OT_ZNODE) {
(void) fprintf(stderr, "invalid bonus type %d for obj %llu\n",
doi.doi_bonus_type, (u_longlong_t)child_obj);
return (EINVAL);
}
if (dump_opt['v'] > 6) {
(void) printf("obj=%llu %s type=%d bonustype=%d\n",
(u_longlong_t)child_obj, curpath, doi.doi_type,
doi.doi_bonus_type);
}
(void) strlcat(curpath, "/", sizeof (curpath));
switch (doi.doi_type) {
case DMU_OT_DIRECTORY_CONTENTS:
if (s != NULL && *(s + 1) != '\0')
return (dump_path_impl(os, child_obj, s + 1));
/*FALLTHROUGH*/
case DMU_OT_PLAIN_FILE_CONTENTS:
dump_object(os, child_obj, dump_opt['v'], &header);
return (0);
default:
(void) fprintf(stderr, "object %llu has non-file/directory "
"type %d\n", (u_longlong_t)obj, doi.doi_type);
break;
}
return (EINVAL);
}
/*
* Dump the blocks for the object specified by path inside the dataset.
*/
static int
dump_path(char *ds, char *path)
{
int err;
objset_t *os;
uint64_t root_obj;
err = open_objset(ds, DMU_OST_ZFS, FTAG, &os);
if (err != 0)
return (err);
err = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, &root_obj);
if (err != 0) {
(void) fprintf(stderr, "can't lookup root znode: %s\n",
strerror(err));
dmu_objset_disown(os, FTAG);
return (EINVAL);
}
(void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds);
err = dump_path_impl(os, root_obj, path);
close_objset(os, FTAG);
return (err);
}
static int
dump_label(const char *dev)
{
int fd;
vdev_label_t label;
char *path, *buf = label.vl_vdev_phys.vp_nvlist;
char path[MAXPATHLEN];
char *buf = label.vl_vdev_phys.vp_nvlist;
size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist);
struct stat64 statbuf;
uint64_t psize, ashift;
int len = strlen(dev) + 1;
boolean_t label_found = B_FALSE;
if (strncmp(dev, ZFS_DISK_ROOTD, strlen(ZFS_DISK_ROOTD)) == 0) {
len++;
path = malloc(len);
(void) snprintf(path, len, "%s%s", ZFS_RDISK_ROOTD,
dev + strlen(ZFS_DISK_ROOTD));
} else {
path = strdup(dev);
(void) strlcpy(path, dev, sizeof (path));
if (dev[0] == '/') {
if (strncmp(dev, ZFS_DISK_ROOTD,
strlen(ZFS_DISK_ROOTD)) == 0) {
(void) snprintf(path, sizeof (path), "%s%s",
ZFS_RDISK_ROOTD, dev + strlen(ZFS_DISK_ROOTD));
}
} else if (stat64(path, &statbuf) != 0) {
char *s;
(void) snprintf(path, sizeof (path), "%s%s", ZFS_RDISK_ROOTD,
dev);
if (((s = strrchr(dev, 's')) == NULL &&
(s = strchr(dev, 'p')) == NULL) ||
!isdigit(*(s + 1)))
(void) strlcat(path, "s0", sizeof (path));
}
if ((fd = open64(path, O_RDONLY)) < 0) {
(void) printf("cannot open '%s': %s\n", path, strerror(errno));
free(path);
(void) fprintf(stderr, "cannot open '%s': %s\n", path,
strerror(errno));
exit(1);
}
if (fstat64(fd, &statbuf) != 0) {
(void) printf("failed to stat '%s': %s\n", path,
(void) fprintf(stderr, "failed to stat '%s': %s\n", path,
strerror(errno));
free(path);
(void) close(fd);
exit(1);
}
if (S_ISBLK(statbuf.st_mode)) {
(void) printf("cannot use '%s': character device required\n",
path);
free(path);
(void) fprintf(stderr,
"cannot use '%s': character device required\n", path);
(void) close(fd);
exit(1);
}
@ -2204,36 +2406,43 @@ dump_label(const char *dev)
for (int l = 0; l < VDEV_LABELS; l++) {
nvlist_t *config = NULL;
(void) printf("--------------------------------------------\n");
(void) printf("LABEL %d\n", l);
(void) printf("--------------------------------------------\n");
if (!dump_opt['q']) {
(void) printf("------------------------------------\n");
(void) printf("LABEL %d\n", l);
(void) printf("------------------------------------\n");
}
if (pread64(fd, &label, sizeof (label),
vdev_label_offset(psize, l, 0)) != sizeof (label)) {
(void) printf("failed to read label %d\n", l);
if (!dump_opt['q'])
(void) printf("failed to read label %d\n", l);
continue;
}
if (nvlist_unpack(buf, buflen, &config, 0) != 0) {
(void) printf("failed to unpack label %d\n", l);
if (!dump_opt['q'])
(void) printf("failed to unpack label %d\n", l);
ashift = SPA_MINBLOCKSHIFT;
} else {
nvlist_t *vdev_tree = NULL;
dump_nvlist(config, 4);
if (!dump_opt['q'])
dump_nvlist(config, 4);
if ((nvlist_lookup_nvlist(config,
ZPOOL_CONFIG_VDEV_TREE, &vdev_tree) != 0) ||
(nvlist_lookup_uint64(vdev_tree,
ZPOOL_CONFIG_ASHIFT, &ashift) != 0))
ashift = SPA_MINBLOCKSHIFT;
nvlist_free(config);
label_found = B_TRUE;
}
if (dump_opt['u'])
dump_label_uberblocks(&label, ashift);
}
free(path);
(void) close(fd);
return (label_found ? 0 : 2);
}
static uint64_t dataset_feature_count[SPA_FEATURES];
@ -2245,11 +2454,9 @@ dump_one_dir(const char *dsname, void *arg)
int error;
objset_t *os;
error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, FTAG, &os);
if (error) {
(void) printf("Could not open %s, error %d\n", dsname, error);
error = open_objset(dsname, DMU_OST_ANY, FTAG, &os);
if (error != 0)
return (0);
}
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
if (!dmu_objset_ds(os)->ds_feature_inuse[f])
@ -2260,9 +2467,8 @@ dump_one_dir(const char *dsname, void *arg)
}
dump_dir(os);
dmu_objset_disown(os, FTAG);
close_objset(os, FTAG);
fuid_table_destroy();
sa_loaded = B_FALSE;
return (0);
}
@ -2513,6 +2719,9 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
int sec_remaining =
(zcb->zcb_totalasize - bytes) / 1024 / kb_per_sec;
/* make sure nicenum has enough space */
CTASSERT(sizeof (buf) >= NN_NUMBUF_SZ);
zfs_nicenum(bytes, buf, sizeof (buf));
(void) fprintf(stderr,
"\r%5s completed (%4dMB/s) "
@ -2862,6 +3071,14 @@ dump_block_stats(spa_t *spa)
char avg[32], gang[32];
char *typename;
/* make sure nicenum has enough space */
CTASSERT(sizeof (csize) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (lsize) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (psize) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (asize) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (avg) >= NN_NUMBUF_SZ);
CTASSERT(sizeof (gang) >= NN_NUMBUF_SZ);
if (t < DMU_OT_NUMTYPES)
typename = dmu_ot[t].ot_name;
else
@ -2895,12 +3112,17 @@ dump_block_stats(spa_t *spa)
zcb.zcb_type[ZB_TOTAL][t].zb_asize)
continue;
zdb_nicenum(zb->zb_count, csize);
zdb_nicenum(zb->zb_lsize, lsize);
zdb_nicenum(zb->zb_psize, psize);
zdb_nicenum(zb->zb_asize, asize);
zdb_nicenum(zb->zb_asize / zb->zb_count, avg);
zdb_nicenum(zb->zb_gangs, gang);
zdb_nicenum(zb->zb_count, csize,
sizeof (csize));
zdb_nicenum(zb->zb_lsize, lsize,
sizeof (lsize));
zdb_nicenum(zb->zb_psize, psize,
sizeof (psize));
zdb_nicenum(zb->zb_asize, asize,
sizeof (asize));
zdb_nicenum(zb->zb_asize / zb->zb_count, avg,
sizeof (avg));
zdb_nicenum(zb->zb_gangs, gang, sizeof (gang));
(void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
"\t%5.2f\t%6.2f\t",
@ -3497,6 +3719,33 @@ zdb_read_block(char *thing, spa_t *spa)
free(dup);
}
static void
zdb_embedded_block(char *thing)
{
blkptr_t bp = { 0 };
unsigned long long *words = (void *)&bp;
char buf[SPA_MAXBLOCKSIZE];
int err;
err = sscanf(thing, "%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx:"
"%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx",
words + 0, words + 1, words + 2, words + 3,
words + 4, words + 5, words + 6, words + 7,
words + 8, words + 9, words + 10, words + 11,
words + 12, words + 13, words + 14, words + 15);
if (err != 16) {
(void) printf("invalid input format\n");
exit(1);
}
ASSERT3U(BPE_GET_LSIZE(&bp), <=, SPA_MAXBLOCKSIZE);
err = decode_embedded_bp(&bp, buf, BPE_GET_LSIZE(&bp));
if (err != 0) {
(void) printf("decode failed: %u\n", err);
exit(1);
}
zdb_dump_block_raw(buf, BPE_GET_LSIZE(&bp), 0);
}
static boolean_t
pool_match(nvlist_t *cfg, char *tgt)
{
@ -3595,6 +3844,7 @@ main(int argc, char **argv)
char *target;
nvlist_t *policy = NULL;
uint64_t max_txg = UINT64_MAX;
int flags = ZFS_IMPORT_MISSING_LOG;
int rewind = ZPOOL_NEVER_REWIND;
char *spa_config_path_env;
boolean_t target_is_spa = B_TRUE;
@ -3614,34 +3864,38 @@ main(int argc, char **argv)
spa_config_path = spa_config_path_env;
while ((c = getopt(argc, argv,
"bcdhilmMI:suCDRSAFLXx:evp:t:U:PG")) != -1) {
"AbcCdDeEFGhiI:lLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
switch (c) {
case 'b':
case 'c':
case 'C':
case 'd':
case 'D':
case 'E':
case 'G':
case 'h':
case 'i':
case 'l':
case 'm':
case 's':
case 'u':
case 'C':
case 'D':
case 'M':
case 'O':
case 'R':
case 's':
case 'S':
case 'G':
case 'u':
dump_opt[c]++;
dump_all = 0;
break;
case 'A':
case 'e':
case 'F':
case 'L':
case 'X':
case 'e':
case 'P':
case 'q':
case 'X':
dump_opt[c]++;
break;
/* NB: Sort single match options below. */
case 'I':
max_inflight = strtoull(optarg, NULL, 0);
if (max_inflight == 0) {
@ -3651,6 +3905,11 @@ main(int argc, char **argv)
usage();
}
break;
case 'o':
error = set_global_var(optarg);
if (error != 0)
usage();
break;
case 'p':
if (searchdirs == NULL) {
searchdirs = umem_alloc(sizeof (char *),
@ -3676,10 +3935,19 @@ main(int argc, char **argv)
break;
case 'U':
spa_config_path = optarg;
if (spa_config_path[0] != '/') {
(void) fprintf(stderr,
"cachefile must be an absolute path "
"(i.e. start with a slash)\n");
usage();
}
break;
case 'v':
verbose++;
break;
case 'V':
flags = ZFS_IMPORT_VERBATIM;
break;
case 'x':
vn_dumpdir = optarg;
break;
@ -3721,7 +3989,7 @@ main(int argc, char **argv)
verbose = MAX(verbose, 1);
for (c = 0; c < 256; c++) {
if (dump_all && !strchr("elAFLRSXP", c))
if (dump_all && strchr("AeEFlLOPRSX", c) == NULL)
dump_opt[c] = 1;
if (dump_opt[c])
dump_opt[c] += verbose;
@ -3735,6 +4003,14 @@ main(int argc, char **argv)
if (argc < 2 && dump_opt['R'])
usage();
if (dump_opt['E']) {
if (argc != 1)
usage();
zdb_embedded_block(argv[0]);
return (0);
}
if (argc < 1) {
if (!dump_opt['e'] && dump_opt['C']) {
dump_cachefile(spa_config_path);
@ -3743,9 +4019,14 @@ main(int argc, char **argv)
usage();
}
if (dump_opt['l']) {
dump_label(argv[0]);
return (0);
if (dump_opt['l'])
return (dump_label(argv[0]));
if (dump_opt['O']) {
if (argc != 2)
usage();
dump_opt['v'] = verbose + 3;
return (dump_path(argv[0], argv[1]));
}
if (dump_opt['X'] || dump_opt['F'])
@ -3775,11 +4056,7 @@ main(int argc, char **argv)
fatal("can't open '%s': %s",
target, strerror(ENOMEM));
}
if ((error = spa_import(name, cfg, NULL,
ZFS_IMPORT_MISSING_LOG)) != 0) {
error = spa_import(name, cfg, NULL,
ZFS_IMPORT_VERBATIM);
}
error = spa_import(name, cfg, NULL, flags);
}
}
@ -3822,8 +4099,7 @@ main(int argc, char **argv)
}
}
} else {
error = dmu_objset_own(target, DMU_OST_ANY,
B_TRUE, FTAG, &os);
error = open_objset(target, DMU_OST_ANY, FTAG, &os);
}
}
nvlist_free(policy);
@ -3866,10 +4142,12 @@ main(int argc, char **argv)
zdb_read_block(argv[i], spa);
}
(os != NULL) ? dmu_objset_disown(os, FTAG) : spa_close(spa, FTAG);
if (os != NULL)
close_objset(os, FTAG);
else
spa_close(spa, FTAG);
fuid_table_destroy();
sa_loaded = B_FALSE;
dump_debug_buffer();

View File

@ -0,0 +1,536 @@
.\" This file and its contents are supplied under the terms of the
.\" Common Development and Distribution License ("CDDL"), version 1.0.
.\" You may only use this file in accordance with the terms of version
.\" 1.0 of the CDDL.
.\"
.\" A full copy of the text of the CDDL should have accompanied this
.\" source. A copy of the CDDL is also available via the Internet at
.\" http://www.illumos.org/license/CDDL.
.\"
.\"
.\" Copyright (c) 2016, 2017 by Delphix. All rights reserved.
.\"
.Dd October 02, 2017
.Dt ZFS-PROGRAM 1M
.Os
.Sh NAME
.Nm zfs program
.Nd executes ZFS channel programs
.Sh SYNOPSIS
.Cm zfs program
.Op Fl t Ar instruction-limit
.Op Fl m Ar memory-limit
.Ar pool
.Ar script
.\".Op Ar optional arguments to channel program
.Sh DESCRIPTION
The ZFS channel program interface allows ZFS administrative operations to be
run programmatically as a Lua script.
The entire script is executed atomically, with no other administrative
operations taking effect concurrently.
A library of ZFS calls is made available to channel program scripts.
Channel programs may only be run with root privileges.
.Pp
A modified version of the Lua 5.2 interpreter is used to run channel program
scripts.
The Lua 5.2 manual can be found at:
.Bd -centered -offset indent
.Lk http://www.lua.org/manual/5.2/
.Ed
.Pp
The channel program given by
.Ar script
will be run on
.Ar pool ,
and any attempts to access or modify other pools will cause an error.
.Sh OPTIONS
.Bl -tag -width "-t"
.It Fl t Ar instruction-limit
Execution time limit, in number of Lua instructions to execute.
If a channel program executes more than the specified number of instructions,
it will be stopped and an error will be returned.
The default limit is 10 million instructions, and it can be set to a maximum of
100 million instructions.
.It Fl m Ar memory-limit
Memory limit, in bytes.
If a channel program attempts to allocate more memory than the given limit, it
will be stopped and an error returned.
The default memory limit is 10 MB, and can be set to a maximum of 100 MB.
.El
.Pp
All remaining argument strings will be passed directly to the Lua script as
described in the
.Sx LUA INTERFACE
section below.
.Sh LUA INTERFACE
A channel program can be invoked either from the command line, or via a library
call to
.Fn lzc_channel_program .
.Ss Arguments
Arguments passed to the channel program are converted to a Lua table.
If invoked from the command line, extra arguments to the Lua script will be
accessible as an array stored in the argument table with the key 'argv':
.Bd -literal -offset indent
args = ...
argv = args["argv"]
-- argv == {1="arg1", 2="arg2", ...}
.Ed
.Pp
If invoked from the libZFS interface, an arbitrary argument list can be
passed to the channel program, which is accessible via the same
"..." syntax in Lua:
.Bd -literal -offset indent
args = ...
-- args == {"foo"="bar", "baz"={...}, ...}
.Ed
.Pp
Note that because Lua arrays are 1-indexed, arrays passed to Lua from the
libZFS interface will have their indices incremented by 1.
That is, the element
in
.Va arr[0]
in a C array passed to a channel program will be stored in
.Va arr[1]
when accessed from Lua.
.Ss Return Values
Lua return statements take the form:
.Bd -literal -offset indent
return ret0, ret1, ret2, ...
.Ed
.Pp
Return statements returning multiple values are permitted internally in a
channel program script, but attempting to return more than one value from the
top level of the channel program is not permitted and will throw an error.
However, tables containing multiple values can still be returned.
If invoked from the command line, a return statement:
.Bd -literal -offset indent
a = {foo="bar", baz=2}
return a
.Ed
.Pp
Will be output formatted as:
.Bd -literal -offset indent
Channel program fully executed with return value:
return:
baz: 2
foo: 'bar'
.Ed
.Ss Fatal Errors
If the channel program encounters a fatal error while running, a non-zero exit
status will be returned.
If more information about the error is available, a singleton list will be
returned detailing the error:
.Bd -literal -offset indent
error: "error string, including Lua stack trace"
.Ed
.Pp
If a fatal error is returned, the channel program may have not executed at all,
may have partially executed, or may have fully executed but failed to pass a
return value back to userland.
.Pp
If the channel program exhausts an instruction or memory limit, a fatal error
will be generated and the program will be stopped, leaving the program partially
executed.
No attempt is made to reverse or undo any operations already performed.
Note that because both the instruction count and amount of memory used by a
channel program are deterministic when run against the same inputs and
filesystem state, as long as a channel program has run successfully once, you
can guarantee that it will finish successfully against a similar size system.
.Pp
If a channel program attempts to return too large a value, the program will
fully execute but exit with a nonzero status code and no return value.
.Pp
.Em Note:
ZFS API functions do not generate Fatal Errors when correctly invoked, they
return an error code and the channel program continues executing.
See the
.Sx ZFS API
section below for function-specific details on error return codes.
.Ss Lua to C Value Conversion
When invoking a channel program via the libZFS interface, it is necessary to
translate arguments and return values from Lua values to their C equivalents,
and vice-versa.
.Pp
There is a correspondence between nvlist values in C and Lua tables.
A Lua table which is returned from the channel program will be recursively
converted to an nvlist, with table values converted to their natural
equivalents:
.Bd -literal -offset indent
string -> string
number -> int64
boolean -> boolean_value
nil -> boolean (no value)
table -> nvlist
.Ed
.Pp
Likewise, table keys are replaced by string equivalents as follows:
.Bd -literal -offset indent
string -> no change
number -> signed decimal string ("%lld")
boolean -> "true" | "false"
.Ed
.Pp
Any collision of table key strings (for example, the string "true" and a
true boolean value) will cause a fatal error.
.Pp
Lua numbers are represented internally as signed 64-bit integers.
.Sh LUA STANDARD LIBRARY
The following Lua built-in base library functions are available:
.Bd -literal -offset indent
assert rawlen
collectgarbage rawget
error rawset
getmetatable select
ipairs setmetatable
next tonumber
pairs tostring
rawequal type
.Ed
.Pp
All functions in the
.Em coroutine ,
.Em string ,
and
.Em table
built-in submodules are also available.
A complete list and documentation of these modules is available in the Lua
manual.
.Pp
The following functions base library functions have been disabled and are
not available for use in channel programs:
.Bd -literal -offset indent
dofile
loadfile
load
pcall
print
xpcall
.Ed
.Sh ZFS API
.Ss Function Arguments
Each API function takes a fixed set of required positional arguments and
optional keyword arguments.
For example, the destroy function takes a single positional string argument
(the name of the dataset to destroy) and an optional "defer" keyword boolean
argument.
When using parentheses to specify the arguments to a Lua function, only
positional arguments can be used:
.Bd -literal -offset indent
zfs.sync.destroy("rpool@snap")
.Ed
.Pp
To use keyword arguments, functions must be called with a single argument that
is a Lua table containing entries mapping integers to positional arguments and
strings to keyword arguments:
.Bd -literal -offset indent
zfs.sync.destroy({1="rpool@snap", defer=true})
.Ed
.Pp
The Lua language allows curly braces to be used in place of parenthesis as
syntactic sugar for this calling convention:
.Bd -literal -offset indent
zfs.sync.snapshot{"rpool@snap", defer=true}
.Ed
.Ss Function Return Values
If an API function succeeds, it returns 0.
If it fails, it returns an error code and the channel program continues
executing.
API functions do not generate Fatal Errors except in the case of an
unrecoverable internal file system error.
.Pp
In addition to returning an error code, some functions also return extra
details describing what caused the error.
This extra description is given as a second return value, and will always be a
Lua table, or Nil if no error details were returned.
Different keys will exist in the error details table depending on the function
and error case.
Any such function may be called expecting a single return value:
.Bd -literal -offset indent
errno = zfs.sync.promote(dataset)
.Ed
.Pp
Or, the error details can be retrieved:
.Bd -literal -offset indent
errno, details = zfs.sync.promote(dataset)
if (errno == EEXIST) then
assert(details ~= Nil)
list_of_conflicting_snapshots = details
end
.Ed
.Pp
The following global aliases for API function error return codes are defined
for use in channel programs:
.Bd -literal -offset indent
EPERM ECHILD ENODEV ENOSPC
ENOENT EAGAIN ENOTDIR ESPIPE
ESRCH ENOMEM EISDIR EROFS
EINTR EACCES EINVAL EMLINK
EIO EFAULT ENFILE EPIPE
ENXIO ENOTBLK EMFILE EDOM
E2BIG EBUSY ENOTTY ERANGE
ENOEXEC EEXIST ETXTBSY EDQUOT
EBADF EXDEV EFBIG
.Ed
.Ss API Functions
For detailed descriptions of the exact behavior of any zfs administrative
operations, see the main
.Xr zfs 1
manual page.
.Bl -tag -width "xx"
.It Em zfs.debug(msg)
Record a debug message in the zfs_dbgmsg log.
A log of these messages can be printed via mdb's "::zfs_dbgmsg" command, or
can be monitored live by running:
.Bd -literal -offset indent
dtrace -n 'zfs-dbgmsg{trace(stringof(arg0))}'
.Ed
.Pp
msg (string)
.Bd -ragged -compact -offset "xxxx"
Debug message to be printed.
.Ed
.It Em zfs.exists(dataset)
Returns true if the given dataset exists, or false if it doesn't.
A fatal error will be thrown if the dataset is not in the target pool.
That is, in a channel program running on rpool,
zfs.exists("rpool/nonexistent_fs") returns false, but
zfs.exists("somepool/fs_that_may_exist") will error.
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Dataset to check for existence.
Must be in the target pool.
.Ed
.It Em zfs.get_prop(dataset, property)
Returns two values.
First, a string, number or table containing the property value for the given
dataset.
Second, a string containing the source of the property (i.e. the name of the
dataset in which it was set or nil if it is readonly).
Throws a Lua error if the dataset is invalid or the property doesn't exist.
Note that Lua only supports int64 number types whereas ZFS number properties
are uint64.
This means very large values (like guid) may wrap around and appear negative.
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Filesystem or snapshot path to retrieve properties from.
.Ed
.Pp
property (string)
.Bd -ragged -compact -offset "xxxx"
Name of property to retrieve.
All filesystem, snapshot and volume properties are supported except
for 'mounted' and 'iscsioptions.'
Also supports the 'written@snap' and 'written#bookmark' properties and
the '<user|group><quota|used>@id' properties, though the id must be in numeric
form.
.Ed
.El
.Bl -tag -width "xx"
.It Sy zfs.sync submodule
The sync submodule contains functions that modify the on-disk state.
They are executed in "syncing context".
.Pp
The available sync submodule functions are as follows:
.Bl -tag -width "xx"
.It Em zfs.sync.destroy(dataset, [defer=true|false])
Destroy the given dataset.
Returns 0 on successful destroy, or a nonzero error code if the dataset could
not be destroyed (for example, if the dataset has any active children or
clones).
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Filesystem or snapshot to be destroyed.
.Ed
.Pp
[optional] defer (boolean)
.Bd -ragged -compact -offset "xxxx"
Valid only for destroying snapshots.
If set to true, and the snapshot has holds or clones, allows the snapshot to be
marked for deferred deletion rather than failing.
.Ed
.It Em zfs.sync.promote(dataset)
Promote the given clone to a filesystem.
Returns 0 on successful promotion, or a nonzero error code otherwise.
If EEXIST is returned, the second return value will be an array of the clone's
snapshots whose names collide with snapshots of the parent filesystem.
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Clone to be promoted.
.Ed
.It Em zfs.sync.rollback(filesystem)
Rollback to the previous snapshot for a dataset.
Returns 0 on successful rollback, or a nonzero error code otherwise.
Rollbacks can be performed on filesystems or zvols, but not on snapshots
or mounted datasets.
EBUSY is returned in the case where the filesystem is mounted.
.Pp
filesystem (string)
.Bd -ragged -compact -offset "xxxx"
Filesystem to rollback.
.Ed
.It Em zfs.sync.snapshot(dataset)
Create a snapshot of a filesystem.
Returns 0 if the snapshot was successfully created,
and a nonzero error code otherwise.
.Pp
Note: Taking a snapshot will fail on any pool older than legacy version 27.
To enable taking snapshots from ZCP scripts, the pool must be upgraded.
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Name of snapshot to create.
.Ed
.El
.It Sy zfs.check submodule
For each function in the zfs.sync submodule, there is a corresponding zfs.check
function which performs a "dry run" of the same operation.
Each takes the same arguments as its zfs.sync counterpart and returns 0 if the
operation would succeed, or a non-zero error code if it would fail, along with
any other error details.
That is, each has the same behavior as the corresponding sync function except
for actually executing the requested change.
For example,
.Em zfs.check.destroy("fs")
returns 0 if
.Em zfs.sync.destroy("fs")
would successfully destroy the dataset.
.Pp
The available zfs.check functions are:
.Bl -tag -width "xx"
.It Em zfs.check.destroy(dataset, [defer=true|false])
.It Em zfs.check.promote(dataset)
.It Em zfs.check.rollback(filesystem)
.It Em zfs.check.snapshot(dataset)
.El
.It Sy zfs.list submodule
The zfs.list submodule provides functions for iterating over datasets and
properties.
Rather than returning tables, these functions act as Lua iterators, and are
generally used as follows:
.Bd -literal -offset indent
for child in zfs.list.children("rpool") do
...
end
.Ed
.Pp
The available zfs.list functions are:
.Bl -tag -width "xx"
.It Em zfs.list.clones(snapshot)
Iterate through all clones of the given snapshot.
.Pp
snapshot (string)
.Bd -ragged -compact -offset "xxxx"
Must be a valid snapshot path in the current pool.
.Ed
.It Em zfs.list.snapshots(dataset)
Iterate through all snapshots of the given dataset.
Each snapshot is returned as a string containing the full dataset name, e.g.
"pool/fs@snap".
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Must be a valid filesystem or volume.
.Ed
.It Em zfs.list.children(dataset)
Iterate through all direct children of the given dataset.
Each child is returned as a string containing the full dataset name, e.g.
"pool/fs/child".
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Must be a valid filesystem or volume.
.Ed
.It Em zfs.list.properties(dataset)
Iterate through all user properties for the given dataset.
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Must be a valid filesystem, snapshot, or volume.
.Ed
.It Em zfs.list.system_properties(dataset)
Returns an array of strings, the names of the valid system (non-user defined)
properties for the given dataset.
Throws a Lua error if the dataset is invalid.
.Pp
dataset (string)
.Bd -ragged -compact -offset "xxxx"
Must be a valid filesystem, snapshot or volume.
.Ed
.El
.El
.Sh EXAMPLES
.Ss Example 1
The following channel program recursively destroys a filesystem and all its
snapshots and children in a naive manner.
Note that this does not involve any error handling or reporting.
.Bd -literal -offset indent
function destroy_recursive(root)
for child in zfs.list.children(root) do
destroy_recursive(child)
end
for snap in zfs.list.snapshots(root) do
zfs.sync.destroy(snap)
end
zfs.sync.destroy(root)
end
destroy_recursive("pool/somefs")
.Ed
.Ss Example 2
A more verbose and robust version of the same channel program, which
properly detects and reports errors, and also takes the dataset to destroy
as a command line argument, would be as follows:
.Bd -literal -offset indent
succeeded = {}
failed = {}
function destroy_recursive(root)
for child in zfs.list.children(root) do
destroy_recursive(child)
end
for snap in zfs.list.snapshots(root) do
err = zfs.sync.destroy(snap)
if (err ~= 0) then
failed[snap] = err
else
succeeded[snap] = err
end
end
err = zfs.sync.destroy(root)
if (err ~= 0) then
failed[root] = err
else
succeeded[root] = err
end
end
args = ...
argv = args["argv"]
destroy_recursive(argv[1])
results = {}
results["succeeded"] = succeeded
results["failed"] = failed
return results
.Ed
.Ss Example 3
The following function performs a forced promote operation by attempting to
promote the given clone and destroying any conflicting snapshots.
.Bd -literal -offset indent
function force_promote(ds)
errno, details = zfs.check.promote(ds)
if (errno == EEXIST) then
assert(details ~= Nil)
for i, snap in ipairs(details) do
zfs.sync.destroy(ds .. "@" .. snap)
end
elseif (errno ~= 0) then
return errno
end
return zfs.sync.promote(ds)
end
.Ed

View File

@ -286,6 +286,12 @@
.Ar snapshot
.Op Ar snapshot Ns | Ns Ar filesystem
.Nm
.Cm program
.Op Fl t Ar timeout
.Op Fl m Ar memory_limit
.Ar pool script
.Op Ar arg1 No ...
.Nm
.Cm jail
.Ar jailid Ns | Ns Ar jailname filesystem
.Nm
@ -3287,6 +3293,48 @@ Display the path's inode change time as the first column of output.
.El
.It Xo
.Nm
.Cm program
.Op Fl t Ar timeout
.Op Fl m Ar memory_limit
.Ar pool script
.Op Ar arg1 No ...
.Xc
.Pp
Executes
.Ar script
as a ZFS channel program on
.Ar pool .
The ZFS channel
program interface allows ZFS administrative operations to be run
programmatically via a Lua script.
The entire script is executed atomically, with no other administrative
operations taking effect concurrently.
A library of ZFS calls is made available to channel program scripts.
Channel programs may only be run with root privileges.
.Pp
For full documentation of the ZFS channel program interface, see the manual
page for
.Xr zfs-program 8 .
.Bl -tag -width indent
.It Fl t Ar timeout
Execution time limit, in milliseconds.
If a channel program executes for longer than the provided timeout, it will
be stopped and an error will be returned.
The default timeout is 1000 ms, and can be set to a maximum of 10000 ms.
.It Fl m Ar memory-limit
Memory limit, in bytes.
If a channel program attempts to allocate more memory than the given limit,
it will be stopped and an error returned.
The default memory limit is 10 MB, and can be set to a maximum of 100 MB.
.Pp
All remaining argument strings are passed directly to the channel program as
arguments.
See
.Xr zfs-program 8
for more information.
.El
.It Xo
.Nm
.Cm jail
.Ar jailid filesystem
.Xc

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2011, 2016 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. All rights reserved.
@ -51,6 +51,7 @@
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <sys/debug.h>
#include <sys/list.h>
#include <sys/mntent.h>
#include <sys/mnttab.h>
@ -111,6 +112,7 @@ 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);
static int zfs_do_channel_program(int argc, char **argv);
/*
* Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
@ -160,6 +162,7 @@ typedef enum {
HELP_RELEASE,
HELP_DIFF,
HELP_BOOKMARK,
HELP_CHANNEL_PROGRAM,
} zfs_help_t;
typedef struct zfs_command {
@ -187,6 +190,7 @@ static zfs_command_t command_table[] = {
{ "promote", zfs_do_promote, HELP_PROMOTE },
{ "rename", zfs_do_rename, HELP_RENAME },
{ "bookmark", zfs_do_bookmark, HELP_BOOKMARK },
{ "program", zfs_do_channel_program, HELP_CHANNEL_PROGRAM },
{ NULL },
{ "list", zfs_do_list, HELP_LIST },
{ NULL },
@ -340,6 +344,10 @@ get_usage(zfs_help_t idx)
"[snapshot|filesystem]\n"));
case HELP_BOOKMARK:
return (gettext("\tbookmark <snapshot> <bookmark>\n"));
case HELP_CHANNEL_PROGRAM:
return (gettext("\tprogram [-t <instruction limit>] "
"[-m <memory limit (b)>] <pool> <program file> "
"[lua args...]\n"));
}
abort();
@ -368,6 +376,18 @@ safe_malloc(size_t size)
return (data);
}
void *
safe_realloc(void *data, size_t size)
{
void *newp;
if ((newp = realloc(data, size)) == NULL) {
free(data);
nomem();
}
return (newp);
}
static char *
safe_strdup(char *str)
{
@ -7101,6 +7121,194 @@ zfs_do_bookmark(int argc, char **argv)
return (-1);
}
static int
zfs_do_channel_program(int argc, char **argv)
{
int ret, fd;
char c;
char *progbuf, *filename, *poolname;
size_t progsize, progread;
nvlist_t *outnvl;
uint64_t instrlimit = ZCP_DEFAULT_INSTRLIMIT;
uint64_t memlimit = ZCP_DEFAULT_MEMLIMIT;
zpool_handle_t *zhp;
/* check options */
while (-1 !=
(c = getopt(argc, argv, "t:(instr-limit)m:(memory-limit)"))) {
switch (c) {
case 't':
case 'm': {
uint64_t arg;
char *endp;
errno = 0;
arg = strtoull(optarg, &endp, 0);
if (errno != 0 || *endp != '\0') {
(void) fprintf(stderr, gettext(
"invalid argument "
"'%s': expected integer\n"), optarg);
goto usage;
}
if (c == 't') {
if (arg > ZCP_MAX_INSTRLIMIT || arg == 0) {
(void) fprintf(stderr, gettext(
"Invalid instruction limit: "
"%s\n"), optarg);
return (1);
} else {
instrlimit = arg;
}
} else {
ASSERT3U(c, ==, 'm');
if (arg > ZCP_MAX_MEMLIMIT || arg == 0) {
(void) fprintf(stderr, gettext(
"Invalid memory limit: "
"%s\n"), optarg);
return (1);
} else {
memlimit = arg;
}
}
break;
}
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc < 2) {
(void) fprintf(stderr,
gettext("invalid number of arguments\n"));
goto usage;
}
poolname = argv[0];
filename = argv[1];
if (strcmp(filename, "-") == 0) {
fd = 0;
filename = "standard input";
} else if ((fd = open(filename, O_RDONLY)) < 0) {
(void) fprintf(stderr, gettext("cannot open '%s': %s\n"),
filename, strerror(errno));
return (1);
}
if ((zhp = zpool_open(g_zfs, poolname)) == NULL) {
(void) fprintf(stderr, gettext("cannot open pool '%s'"),
poolname);
return (1);
}
zpool_close(zhp);
/*
* Read in the channel program, expanding the program buffer as
* necessary.
*/
progread = 0;
progsize = 1024;
progbuf = safe_malloc(progsize);
do {
ret = read(fd, progbuf + progread, progsize - progread);
progread += ret;
if (progread == progsize && ret > 0) {
progsize *= 2;
progbuf = safe_realloc(progbuf, progsize);
}
} while (ret > 0);
if (fd != 0)
(void) close(fd);
if (ret < 0) {
free(progbuf);
(void) fprintf(stderr,
gettext("cannot read '%s': %s\n"),
filename, strerror(errno));
return (1);
}
progbuf[progread] = '\0';
/*
* Any remaining arguments are passed as arguments to the lua script as
* a string array:
* {
* "argv" -> [ "arg 1", ... "arg n" ],
* }
*/
nvlist_t *argnvl = fnvlist_alloc();
fnvlist_add_string_array(argnvl, ZCP_ARG_CLIARGV, argv + 2, argc - 2);
ret = lzc_channel_program(poolname, progbuf, instrlimit, memlimit,
argnvl, &outnvl);
if (ret != 0) {
/*
* On error, report the error message handed back by lua if one
* exists. Otherwise, generate an appropriate error message,
* falling back on strerror() for an unexpected return code.
*/
char *errstring = NULL;
if (nvlist_exists(outnvl, ZCP_RET_ERROR)) {
(void) nvlist_lookup_string(outnvl,
ZCP_RET_ERROR, &errstring);
if (errstring == NULL)
errstring = strerror(ret);
} else {
switch (ret) {
case EINVAL:
errstring =
"Invalid instruction or memory limit.";
break;
case ENOMEM:
errstring = "Return value too large.";
break;
case ENOSPC:
errstring = "Memory limit exhausted.";
break;
#ifdef illumos
case ETIME:
#else
case ETIMEDOUT:
#endif
errstring = "Timed out.";
break;
case EPERM:
errstring = "Permission denied. Channel "
"programs must be run as root.";
break;
default:
errstring = strerror(ret);
}
}
(void) fprintf(stderr,
gettext("Channel program execution failed:\n%s\n"),
errstring);
} else {
(void) printf("Channel program fully executed ");
if (nvlist_empty(outnvl)) {
(void) printf("with no return value.\n");
} else {
(void) printf("with return value:\n");
dump_nvlist(outnvl, 4);
}
}
free(progbuf);
fnvlist_free(outnvl);
fnvlist_free(argnvl);
return (ret != 0);
usage:
usage(B_FALSE);
return (-1);
}
int
main(int argc, char **argv)
{

View File

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2011, 2016 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.
@ -705,7 +705,7 @@ zpool_do_labelclear(int argc, char **argv)
return (1);
}
if (zpool_read_label(fd, &config) != 0 || config == NULL) {
if (zpool_read_label(fd, &config) != 0) {
(void) fprintf(stderr,
gettext("failed to read label from %s\n"), vdev);
return (1);
@ -5254,6 +5254,11 @@ get_history_one(zpool_handle_t *zhp, void *data)
dump_nvlist(fnvlist_lookup_nvlist(rec,
ZPOOL_HIST_OUTPUT_NVL), 8);
}
if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
(void) printf(" errno: %lld\n",
fnvlist_lookup_int64(rec,
ZPOOL_HIST_ERRNO));
}
} else {
if (!cb->internal)
continue;

View File

@ -25,6 +25,7 @@
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 Joyent, Inc.
*/
/*
@ -125,6 +126,7 @@
#include <errno.h>
#include <sys/fs/zfs.h>
#include <libnvpair.h>
#include <libcmdutils.h>
static int ztest_fd_data = -1;
static int ztest_fd_rand = -1;
@ -556,12 +558,13 @@ usage(boolean_t requested)
{
const ztest_shared_opts_t *zo = &ztest_opts_defaults;
char nice_vdev_size[10];
char nice_gang_bang[10];
char nice_vdev_size[NN_NUMBUF_SZ];
char nice_gang_bang[NN_NUMBUF_SZ];
FILE *fp = requested ? stdout : stderr;
nicenum(zo->zo_vdev_size, nice_vdev_size);
nicenum(zo->zo_metaslab_gang_bang, nice_gang_bang);
nicenum(zo->zo_vdev_size, nice_vdev_size, sizeof (nice_vdev_size));
nicenum(zo->zo_metaslab_gang_bang, nice_gang_bang,
sizeof (nice_gang_bang));
(void) fprintf(fp, "Usage: %s\n"
"\t[-v vdevs (default: %llu)]\n"
@ -583,6 +586,8 @@ usage(boolean_t requested)
"\t[-F freezeloops (default: %llu)] max loops in spa_freeze()\n"
"\t[-P passtime (default: %llu sec)] time per pass\n"
"\t[-B alt_ztest (default: <none>)] alternate ztest path\n"
"\t[-o variable=value] ... set global variable to an unsigned\n"
"\t 32-bit integer value\n"
"\t[-h] (print help)\n"
"",
zo->zo_pool,
@ -618,7 +623,7 @@ process_options(int argc, char **argv)
bcopy(&ztest_opts_defaults, zo, sizeof (*zo));
while ((opt = getopt(argc, argv,
"v:s:a:m:r:R:d:t:g:i:k:p:f:VET:P:hF:B:")) != EOF) {
"v:s:a:m:r:R:d:t:g:i:k:p:f:VET:P:hF:B:o:")) != EOF) {
value = 0;
switch (opt) {
case 'v':
@ -705,6 +710,10 @@ process_options(int argc, char **argv)
case 'B':
(void) strlcpy(altdir, optarg, sizeof (altdir));
break;
case 'o':
if (set_global_var(optarg) != 0)
usage(B_FALSE);
break;
case 'h':
usage(B_TRUE);
break;
@ -1825,13 +1834,14 @@ ztest_get_done(zgd_t *zgd, int error)
ztest_object_unlock(zd, object);
if (error == 0 && zgd->zgd_bp)
zil_add_block(zgd->zgd_zilog, zgd->zgd_bp);
zil_lwb_add_block(zgd->zgd_lwb, zgd->zgd_bp);
umem_free(zgd, sizeof (*zgd));
}
static int
ztest_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
ztest_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb,
zio_t *zio)
{
ztest_ds_t *zd = arg;
objset_t *os = zd->zd_os;
@ -1845,6 +1855,10 @@ ztest_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
zgd_t *zgd;
int error;
ASSERT3P(lwb, !=, NULL);
ASSERT3P(zio, !=, NULL);
ASSERT3U(size, !=, 0);
ztest_object_lock(zd, object, RL_READER);
error = dmu_bonus_hold(os, object, FTAG, &db);
if (error) {
@ -1865,7 +1879,7 @@ ztest_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
db = NULL;
zgd = umem_zalloc(sizeof (*zgd), UMEM_NOFAIL);
zgd->zgd_zilog = zd->zd_zilog;
zgd->zgd_lwb = lwb;
zgd->zgd_private = zd;
if (buf != NULL) { /* immediate write */
@ -3147,10 +3161,10 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
old_class_space, new_class_space);
if (ztest_opts.zo_verbose >= 5) {
char oldnumbuf[6], newnumbuf[6];
char oldnumbuf[NN_NUMBUF_SZ], newnumbuf[NN_NUMBUF_SZ];
nicenum(old_class_space, oldnumbuf);
nicenum(new_class_space, newnumbuf);
nicenum(old_class_space, oldnumbuf, sizeof (oldnumbuf));
nicenum(new_class_space, newnumbuf, sizeof (newnumbuf));
(void) printf("%s grew from %s to %s\n",
spa->spa_name, oldnumbuf, newnumbuf);
}
@ -6193,7 +6207,7 @@ main(int argc, char **argv)
ztest_info_t *zi;
ztest_shared_callstate_t *zc;
char timebuf[100];
char numbuf[6];
char numbuf[NN_NUMBUF_SZ];
spa_t *spa;
char *cmd;
boolean_t hasalt;
@ -6330,7 +6344,7 @@ main(int argc, char **argv)
now = MIN(now, zs->zs_proc_stop);
print_time(zs->zs_proc_stop - now, timebuf);
nicenum(zs->zs_space, numbuf);
nicenum(zs->zs_space, numbuf, sizeof (numbuf));
(void) printf("Pass %3d, %8s, %3llu ENOSPC, "
"%4.1f%% of %5s used, %3.0f%% done, %8s to go\n",

View File

@ -0,0 +1,130 @@
/*
* 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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2017 Jason king
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/debug.h>
#include "libcmdutils.h"
/* The largest suffix that can fit, aka an exabyte (2^60 / 10^18) */
#define INDEX_MAX (6)
/* Verify INDEX_MAX fits */
CTASSERT(INDEX_MAX * 10 < sizeof (uint64_t) * 8);
void
nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen,
uint32_t flags)
{
uint64_t divamt = 1024;
uint64_t divisor = 1;
int index = 0;
int rc = 0;
char u;
if (units == 0)
units = 1;
if (n > 0) {
n *= units;
if (n < units)
goto overflow;
}
if (flags & NN_DIVISOR_1000)
divamt = 1000;
/*
* This tries to find the suffix S(n) such that
* S(n) <= n < S(n+1), where S(n) = 2^(n*10) | 10^(3*n)
* (i.e. 1024/1000, 1,048,576/1,000,000, etc). Stop once S(n)
* is the largest prefix supported (i.e. don't bother computing
* and checking S(n+1). Since INDEX_MAX should be the largest
* suffix that fits (currently an exabyte), S(INDEX_MAX + 1) is
* never checked as it would overflow.
*/
while (index < INDEX_MAX) {
uint64_t newdiv = divisor * divamt;
/* CTASSERT() guarantee these never trip */
VERIFY3U(newdiv, >=, divamt);
VERIFY3U(newdiv, >=, divisor);
if (n < newdiv)
break;
divisor = newdiv;
index++;
}
u = " KMGTPE"[index];
if (index == 0) {
rc = snprintf(buf, buflen, "%llu", n);
} else if (n % divisor == 0) {
/*
* If this is an even multiple of the base, always display
* without any decimal precision.
*/
rc = snprintf(buf, buflen, "%llu%c", n / divisor, u);
} else {
/*
* We want to choose a precision that reflects the best choice
* for fitting in 5 characters. This can get rather tricky
* when we have numbers that are very close to an order of
* magnitude. For example, when displaying 10239 (which is
* really 9.999K), we want only a single place of precision
* for 10.0K. We could develop some complex heuristics for
* this, but it's much easier just to try each combination
* in turn.
*/
int i;
for (i = 2; i >= 0; i--) {
if ((rc = snprintf(buf, buflen, "%.*f%c", i,
(double)n / divisor, u)) <= 5)
break;
}
}
if (rc + 1 > buflen || rc < 0)
goto overflow;
return;
overflow:
/* prefer a more verbose message if possible */
if (buflen > 10)
(void) strlcpy(buf, "<overflow>", buflen);
else
(void) strlcpy(buf, "??", buflen);
}
void
nicenum(uint64_t num, char *buf, size_t buflen)
{
nicenum_scale(num, 1, buf, buflen, 0);
}

View File

@ -0,0 +1,235 @@
/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2013 RackTop Systems.
*/
/*
* Copyright 2017 Joyent, Inc.
*/
/*
* Declarations for the functions in libcmdutils.
*/
#ifndef _LIBCMDUTILS_H
#define _LIBCMDUTILS_H
#ifdef illumos
#if !defined(_LP64) && \
!((_FILE_OFFSET_BITS == 64) || defined(_LARGEFILE64_SOURCE))
#error "libcmdutils.h can only be used in a largefile compilation environment"
#endif
#endif
/*
* This is a private header file. Applications should not directly include
* this file.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <libintl.h>
#include <string.h>
#include <dirent.h>
#ifdef illumos
#include <attr.h>
#endif
#include <sys/avl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <libnvpair.h>
#ifdef __cplusplus
extern "C" {
#endif
/* extended system attribute support */
#define _NOT_SATTR 0
#define _RO_SATTR 1
#define _RW_SATTR 2
#define MAXMAPSIZE (1024*1024*8) /* map at most 8MB */
#define SMALLFILESIZE (32*1024) /* don't use mmap on little file */
/* Type used for a node containing a device id and inode number */
#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
typedef struct tree_node {
dev_t node_dev;
ino_t node_ino;
avl_node_t avl_link;
} tree_node_t;
#else
typedef struct tree_node {
dev_t node_dev;
ino64_t node_ino;
avl_node_t avl_link;
} tree_node_t;
#endif
/* extended system attribute support */
/* Determine if a file is the name of an extended system attribute file */
extern int sysattr_type(char *);
/* Determine if the underlying file system supports system attributes */
extern int sysattr_support(char *, int);
/* Copies the content of the source file to the target file */
#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
extern int writefile(int, int, char *, char *, char *, char *,
struct stat *, struct stat *);
#else
extern int writefile(int, int, char *, char *, char *, char *,
struct stat64 *, struct stat64 *);
#endif
/* Gets file descriptors of the source and target attribute files */
extern int get_attrdirs(int, int, char *, int *, int *);
/* Move extended attribute and extended system attribute */
extern int mv_xattrs(char *, char *, char *, int, int);
/* Returns non default extended system attribute list */
extern nvlist_t *sysattr_list(char *, int, char *);
/* avltree */
/*
* Used to compare two nodes. We are attempting to match the 1st
* argument (node) against the 2nd argument (a node which
* is already in the search tree).
*/
extern int tnode_compare(const void *, const void *);
/*
* Used to add a single node (containing the input device id and
* inode number) to the specified search tree. The calling
* application must set the tree pointer to NULL before calling
* add_tnode() for the first time.
*/
#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
extern int add_tnode(avl_tree_t **, dev_t, ino_t);
#else
extern int add_tnode(avl_tree_t **, dev_t, ino64_t);
#endif
/*
* Used to destroy a whole tree (all nodes) without rebalancing.
* The calling application is responsible for setting the tree
* pointer to NULL upon return.
*/
extern void destroy_tree(avl_tree_t *);
/* user/group id helpers */
/*
* Used to get the next available user id in given range.
*/
extern int findnextuid(uid_t, uid_t, uid_t *);
/*
* Used to get the next available group id in given range.
*/
extern int findnextgid(gid_t, gid_t, gid_t *);
/* dynamic string utilities */
typedef struct custr custr_t;
/*
* Allocate and free a "custr_t" dynamic string object. Returns 0 on success
* and -1 otherwise.
*/
extern int custr_alloc(custr_t **);
extern void custr_free(custr_t *);
/*
* Allocate a "custr_t" dynamic string object that operates on a fixed external
* buffer.
*/
extern int custr_alloc_buf(custr_t **, void *, size_t);
/*
* Append a single character, or a NUL-terminated string of characters, to a
* dynamic string. Returns 0 on success and -1 otherwise. The dynamic string
* will be unmodified if the function returns -1.
*/
extern int custr_appendc(custr_t *, char);
extern int custr_append(custr_t *, const char *);
/*
* Append a format string and arguments as though the contents were being parsed
* through snprintf. Returns 0 on success and -1 otherwise. The dynamic string
* will be unmodified if the function returns -1.
*/
extern int custr_append_printf(custr_t *, const char *, ...);
extern int custr_append_vprintf(custr_t *, const char *, va_list);
/*
* Determine the length in bytes, not including the NUL terminator, of the
* dynamic string.
*/
extern size_t custr_len(custr_t *);
/*
* Clear the contents of a dynamic string. Does not free the underlying
* memory.
*/
extern void custr_reset(custr_t *);
/*
* Retrieve a const pointer to a NUL-terminated string version of the contents
* of the dynamic string. Storage for this string should not be freed, and
* the pointer will be invalidated by any mutations to the dynamic string.
*/
extern const char *custr_cstr(custr_t *str);
#define NN_DIVISOR_1000 (1U << 0)
/* Minimum size for the output of nicenum, including NULL */
#define NN_NUMBUF_SZ (6)
void nicenum(uint64_t, char *, size_t);
void nicenum_scale(uint64_t, size_t, char *, size_t, uint32_t);
#ifdef __cplusplus
}
#endif
#endif /* _LIBCMDUTILS_H */

View File

@ -39,7 +39,8 @@ data contained in each file has information about the layout and
sizes of C types, including intrinsic types, enumerations, structures,
typedefs, and unions, that are used by the corresponding
.Sy ELF
object. The
object.
The
.Nm
data may also include information about the types of global objects and
the return type and arguments of functions in the symbol table.
@ -51,41 +52,43 @@ file itself, it may also be referred to as a
.Nm
.Sy container .
.Lp
On illumos systems,
On
.Fx
systems,
.Nm
data is consumed by multiple programs. It can be used by the modular
debugger,
.Xr mdb 1 ,
as well as by
.Xr dtrace 1M .
data is consumed by
.Xr dtrace 1 .
Programmatic access to
.Nm
data can be obtained through
.Xr libctf 3LIB .
data can be obtained through libctf.
.Lp
The
.Nm
file format is broken down into seven different sections. The first
section is the
file format is broken down into seven different sections.
The first section is the
.Sy preamble
and
.Sy header ,
which describes the version of the
.Nm
file, links it has to other
file, the links it has to other
.Nm
files, and the sizes of the other sections. The next section is the
files, and the sizes of the other sections.
The next section is the
.Sy label
section,
which provides a way of identifying similar groups of
.Nm
data across multiple files. This is followed by the
data across multiple files.
This is followed by the
.Sy object
information section, which describes the type of global
symbols. The subsequent section is the
information section, which describes the types of global
symbols.
The subsequent section is the
.Sy function
information section, which describes the return
types and arguments of functions. The next section is the
types and arguments of functions.
The next section is the
.Sy type
information section, which describes
the format and layout of the C types themselves, and finally the last
@ -106,29 +109,35 @@ A
file may contain all of the type information that it requires, or it
may optionally refer to another
.Nm
file which holds the remaining types. When a
file which holds the remaining types.
When a
.Nm
file refers to another file, it is called the
.Sy child
and the file it refers to is called the
.Sy parent .
A given file may only refer to one parent. This process is called
A given file may only refer to one parent.
This process is called
.Em uniquification
because it ensures each child only has type information that is
unique to it. A common example of this is that most kernel modules in
illumos are uniquified against the kernel module
unique to it.
A common example of this is that most kernel modules in illumos are uniquified
against the kernel module
.Sy genunix
and the type information that comes from the
.Sy IP
module. This means that a module only has types that are unique to
itself and the most common types in the kernel are not duplicated.
module.
This means that a module only has types that are unique to itself and the most
common types in the kernel are not duplicated.
.Sh FILE FORMAT
This documents version
.Em two
of the
.Nm
file format. All applications and tools currently produce and operate on
this version.
file format.
All applications and tools on
.Fx
currently produce and operate on this version.
.Lp
The file format can be summarized with the following image, the
following sections will cover this in more detail.
@ -235,26 +244,31 @@ This
.Sy preamble
defines the version of the
.Nm
file which defines the format of the rest of the header. While the
header may change in subsequent versions, the preamble will not change
file which defines the format of the rest of the header.
While the header may change in subsequent versions, the preamble will not change
across versions, though the interpretation of its flags may change from
version to version. The
version to version.
The
.Em ctp_magic
member defines the magic number for the
.Nm
file format. This must always be
file format.
This must always be
.Li 0xcff1 .
If another value is encountered, then the file should not be treated as
a
.Nm
file. The
file.
The
.Em ctp_version
member defines the version of the
.Nm
file. The current version is
file.
The current version is
.Li 2 .
It is possible to encounter an unsupported version. In that case,
software should not try to parse the format, as it may have changed.
It is possible to encounter an unsupported version.
In that case, software should not try to parse the format, as it may have
changed.
Finally, the
.Em ctp_flags
member describes aspects of the file which modify its interpretation.
@ -273,9 +287,10 @@ has been compressed through the
.Sy zlib
library and its
.Sy deflate
algorithm. If this flag is not present, then the body has not been
compressed and no special action is needed to interpret it. All offsets
into the data as described by
algorithm.
If this flag is not present, then the body has not been compressed and no
special action is needed to interpret it.
All offsets into the data as described by
.Sy header ,
always refer to the
.Sy uncompressed
@ -285,13 +300,13 @@ In version two of the
.Nm
file format, the
.Sy header
denotes whether whether or not this
denotes whether or not this
.Nm
file is the child of another
.Nm
file and also indicates the size of the remaining sections. The
structure for the
.Sy header ,
file and also indicates the size of the remaining sections.
The structure for the
.Sy header
logically contains a copy of the
.Sy preamble
and the two have a combined size of 36 bytes.
@ -315,37 +330,40 @@ the next two members
.Em cth_parlablel
and
.Em cth_parname ,
are used to identify the parent. The value of both members are offsets
into the
are used to identify the parent.
The value of both members are offsets into the
.Sy string
section which point to the start of a null-terminated string. For more
information on the encoding of strings, see the subsection on
section which point to the start of a null-terminated string.
For more information on the encoding of strings, see the subsection on
.Sx String Identifiers .
If the value of either is zero, then there is no entry for that
member. If the member
member.
If the member
.Em cth_parlabel
is set, then the
.Em ctf_parname
member must be set, otherwise it will not be possible to find the
parent. If
parent.
If
.Em ctf_parname
is set, it is not necessary to define
.Em cth_parlabel ,
as the parent may not have a label. For more information on labels
and their interpretation, see
as the parent may not have a label.
For more information on labels and their interpretation, see
.Sx The Label Section .
.Lp
The remaining members (excepting
.Em cth_strlen )
describe the beginning of the corresponding sections. These offsets are
relative to the end of the
describe the beginning of the corresponding sections.
These offsets are relative to the end of the
.Sy header .
Therefore, something with an offset of 0 is at an offset of thirty-six
bytes relative to the start of the
.Nm
file. The difference between members
indicates the size of the section itself. Different offsets have
different alignment requirements. The start of the
file.
The difference between members indicates the size of the section itself.
Different offsets have different alignment requirements.
The start of the
.Em cth_objotoff
and
.Em cth_funcoff
@ -353,13 +371,14 @@ must be two byte aligned, while the sections
.Em cth_lbloff
and
.Em cth_typeoff
must be four-byte aligned. The section
must be four-byte aligned.
The section
.Em cth_stroff
has no alignment requirements. To calculate the size of a given section,
excepting the
has no alignment requirements.
To calculate the size of a given section, excepting the
.Sy string
section, one should subtract the offset of the section from the following one. For
example, the size of the
section, one should subtract the offset of the section from the following one.
For example, the size of the
.Sy types
section can be calculated by subtracting
.Em cth_stroff
@ -368,8 +387,8 @@ from
.Lp
Finally, the member
.Em cth_strlen
describes the length of the string section itself. From it, you can also
calculate the size of the entire
describes the length of the string section itself.
From it, you can also calculate the size of the entire
.Nm
file by adding together the size of the
.Sy ctf_header_t ,
@ -380,9 +399,11 @@ and the size of the string section in
.Ss Type Identifiers
Through the
.Nm ctf
data, types are referred to by identifiers. A given
data, types are referred to by identifiers.
A given
.Nm
file supports up to 32767 (0x7fff) types. The first valid type identifier is 0x1.
file supports up to 32767 (0x7fff) types.
The first valid type identifier is 0x1.
When a given
.Nm
file is a child, indicated by a non-zero entry for the
@ -403,18 +424,20 @@ Other consumers of
information may use larger or opaque identifiers.
.Ss String Identifiers
String identifiers are always encoded as four byte unsigned integers
which are an offset into a string table. The
which are an offset into a string table.
The
.Nm
format supports two different string tables which have an identifier of
zero or one. This identifier is stored in the high-order bit of the
unsigned four byte offset. Therefore, the maximum supported offset into
one of these tables is 0x7ffffffff.
zero or one.
This identifier is stored in the high-order bit of the unsigned four byte
offset.
Therefore, the maximum supported offset into one of these tables is 0x7ffffffff.
.Lp
Table identifier zero, always refers to the
.Sy string
section in the CTF file itself. String table identifier one refers to an
external string table which is the ELF string table for the ELF symbol
table associated with the
section in the CTF file itself.
String table identifier one refers to an external string table which is the ELF
string table for the ELF symbol table associated with the
.Nm
container.
.Ss Type Encoding
@ -434,8 +457,8 @@ The length of the variable data
.Lp
The 16 bits that make up the encoding are broken down such that you have
five bits for the kind, one bit for indicating whether or not it is a
root type, and 10 bits for the variable length. This is laid out as
follows:
root type, and 10 bits for the variable length.
This is laid out as follows:
.Bd -literal -offset indent
+--------------------+
| kind | root | vlen |
@ -443,12 +466,13 @@ follows:
15 11 10 9 0
.Ed
.Lp
The current version of the file format defines 14 different kinds. The
interpretation of these different kinds will be discussed in the section
The current version of the file format defines 14 different kinds.
The interpretation of these different kinds will be discussed in the section
.Sx The Type Section .
If a kind is encountered that is not listed below, then it is not a valid
.Nm
file. The kinds are defined as follows:
file.
The kinds are defined as follows:
.Bd -literal -offset indent
#define CTF_K_UNKNOWN 0
#define CTF_K_INTEGER 1
@ -467,14 +491,16 @@ file. The kinds are defined as follows:
.Ed
.Lp
Programs directly reference many types; however, other types are referenced
indirectly because they are part of some other structure. These types that are
referenced directly and used are called
indirectly because they are part of some other structure.
These types that are referenced directly and used are called
.Sy root
types. Other types may be used indirectly, for example, a program may reference
a structure directly, but not one of its members which has a type. That type is
not considered a
types.
Other types may be used indirectly, for example, a program may reference
a structure directly, but not one of its members which has a type.
That type is not considered a
.Sy root
type. If a type is a
type.
If a type is a
.Sy root
type, then it will have bit 10 set.
.Lp
@ -499,16 +525,17 @@ When consuming
.Nm
data, it is often useful to know whether two different
.Nm
containers come from the same source base and version. For example, when
building illumos, there are many kernel modules that are built against a
single collection of source code. A label is encoded into the
containers come from the same source base and version.
For example, when building illumos, there are many kernel modules that are built
against a single collection of source code.
A label is encoded into the
.Nm
files that corresponds with the particular build. This ensures that if
files on the system were to become mixed up from multiple releases, that
they are not used together by tools, particularly when a child needs to
refer to a type in the parent. Because they are linked used the type
identifiers, if the wrong parent is used then the wrong type will be
encountered.
files that corresponds with the particular build.
This ensures that if files on the system were to become mixed up from multiple
releases, that they are not used together by tools, particularly when a child
needs to refer to a type in the parent.
Because they are linked using the type identifiers, if the wrong parent is used
then the wrong type will be encountered.
.Lp
Each label is encoded in the file format using the following eight byte
structure:
@ -530,21 +557,22 @@ section.
The type identifier encoded in the member
.Em ctl_typeidx
refers to the last type identifier that a label refers to in the current
file. Labels only refer to types in the current file, if the
file.
Labels only refer to types in the current file, if the
.Nm
file is a child, then it will have the same label as its parent;
however, its label will only refer to its types, not its parents.
however, its label will only refer to its types, not its parent's.
.Lp
It is also possible, though rather uncommon, for a
.Nm
file to have multiple labels. Labels are placed one after another, every
eight bytes. When multiple labels are present, types may only belong to
a single label.
file to have multiple labels.
Labels are placed one after another, every eight bytes.
When multiple labels are present, types may only belong to a single label.
.Ss The Object Section
The object section provides a mapping from ELF symbols of type
.Sy STT_OBJECT
in the symbol table to a type identifier. Every entry in this section is
a
in the symbol table to a type identifier.
Every entry in this section is a
.Sy uint16_t
which contains a type identifier as described in the section
.Sx Type Identifiers .
@ -555,9 +583,10 @@ To walk the object section, you need to have a corresponding
.Sy symbol table
in the ELF object that contains the
.Nm
data. Not every object is included in this section. Specifically, when
walking the symbol table. An entry is skipped if it matches any of the
following conditions:
data.
Not every object is included in this section.
Specifically, when walking the symbol table, an entry is skipped if it matches
any of the following conditions:
.Lp
.Bl -bullet -offset indent -compact
.It
@ -628,40 +657,45 @@ walk_symbols(uint16_t *objtoff, Elf_Data *symdata, Elf_Data *strdata,
The function section of the
.Nm
file encodes the types of both the function's arguments and the function's
return type. Similar to
return value.
Similar to
.Sx The Object Section ,
the function section encodes information for all symbols of type
.Sy STT_FUNCTION ,
excepting those that fit specific criteria. Unlike with objects, because
functions have a variable number of arguments, they start with a type encoding
as defined in
excepting those that fit specific criteria.
Unlike with objects, because functions have a variable number of arguments, they
start with a type encoding as defined in
.Sx Type Encoding ,
which is the size of a
.Sy uint16_t .
For functions which have no type information available, they are encoded as
.Li CTF_TYPE_INFO(CTF_K_UNKNOWN, 0, 0) .
Functions with arguments are encoded differently. Here, the variable length is
turned into the number of arguments in the function. If a function is a
Functions with arguments are encoded differently.
Here, the variable length is turned into the number of arguments in the
function.
If a function is a
.Sy varargs
type function, then the number of arguments is increased by one. Functions with
type information are encoded as:
type function, then the number of arguments is increased by one.
Functions with type information are encoded as:
.Li CTF_TYPE_INFO(CTF_K_FUNCTION, 0, nargs) .
.Lp
For functions that have no type information, nothing else is encoded, and the
next function is encoded. For functions with type information, the next
next function is encoded.
For functions with type information, the next
.Sy uint16_t
is encoded with the type identifier of the return type of the function. It is
followed by each of the type identifiers of the arguments, if any exist, in the
order that they appear in the function. Therefore, argument 0 is the first type
identifier and so on. When a function has a final varargs argument, that is
encoded with the type identifier of zero.
is encoded with the type identifier of the return type of the function.
It is followed by each of the type identifiers of the arguments, if any exist,
in the order that they appear in the function.
Therefore, argument 0 is the first type identifier and so on.
When a function has a final varargs argument, that is encoded with the type
identifier of zero.
.Lp
Like
.Sx The Object Section ,
the function section is encoded in the order of the symbol table. It has
similar, but slightly different considerations from objects. While iterating the
symbol table, if any of the following conditions are true, then the entry is
skipped and no corresponding entry is written:
the function section is encoded in the order of the symbol table.
It has similar, but slightly different considerations from objects.
While iterating the symbol table, if any of the following conditions are true,
then the entry is skipped and no corresponding entry is written:
.Lp
.Bl -bullet -offset indent -compact
.It
@ -683,10 +717,11 @@ ELF.
.Ss The Type Section
The type section is the heart of the
.Nm
data. It encodes all of the information about the types themselves. The base of
the type information comes in two forms, a short form and a long form, each of
which may be followed by a variable number of arguments. The following
definitions describe the short and long forms:
data.
It encodes all of the information about the types themselves.
The base of the type information comes in two forms, a short form and a long
form, each of which may be followed by a variable number of arguments.
The following definitions describe the short and long forms:
.Bd -literal
#define CTF_MAX_SIZE 0xfffe /* max size of a type in bytes */
#define CTF_LSIZE_SENT 0xffff /* sentinel for ctt_size */
@ -720,14 +755,17 @@ Type sizes are stored in
.Sy bytes .
The basic small form uses a
.Sy ushort_t
to store the number of bytes. If the number of bytes in a structure would exceed
0xfffe, then the alternate form, the
to store the number of bytes.
If the number of bytes in a structure would exceed 0xfffe, then the alternate
form, the
.Sy ctf_type_t ,
is used instead. To indicate that the larger form is being used, the member
is used instead.
To indicate that the larger form is being used, the member
.Em ctt_size
is set to value of
.Sy CTF_LSIZE_SENT
(0xffff). In general, when going through the type section, consumers use the
(0xffff).
In general, when going through the type section, consumers use the
.Sy ctf_type_t
structure, but pay attention to the value of the member
.Em ctt_size
@ -739,36 +777,43 @@ Not all kinds of types use
.Sy ctt_size .
Those which do not, will always use the
.Sy ctf_stype_t
structure. The individual sections for each kind have more information.
structure.
The individual sections for each kind have more information.
.Lp
Types are written out in order. Therefore the first entry encountered has a type
id of 0x1, or 0x8000 if a child. The member
Types are written out in order.
Therefore the first entry encountered has a type id of 0x1, or 0x8000 if a
child.
The member
.Em ctt_name
is encoded as described in the section
.Sx String Identifiers .
The string that it points to is the name of the type. If the identifier points
to an empty string (one that consists solely of a null terminator) then the type
does not have a name, this is common with anonymous structures and unions that
only have a typedef to name them, as well as, pointers and qualifiers.
The string that it points to is the name of the type.
If the identifier points to an empty string (one that consists solely of a null
terminator) then the type does not have a name, this is common with anonymous
structures and unions that only have a typedef to name them, as well as
pointers and qualifiers.
.Lp
The next member, the
.Em ctt_info ,
is encoded as described in the section
.Sx Type Encoding .
The types kind tells us how to interpret the remaining data in the
The type's kind tells us how to interpret the remaining data in the
.Sy ctf_type_t
and any variable length data that may exist. The rest of this section will be
broken down into the interpretation of the various kinds.
and any variable length data that may exist.
The rest of this section will be broken down into the interpretation of the
various kinds.
.Ss Encoding of Integers
Integers, which are of type
.Sy CTF_K_INTEGER ,
have no variable length arguments. Instead, they are followed by a four byte
have no variable length arguments.
Instead, they are followed by a four byte
.Sy uint_t
which describes their encoding. All integers must be encoded with a variable
length of zero. The
which describes their encoding.
All integers must be encoded with a variable length of zero.
The
.Em ctt_size
member describes the length of the integer in bytes. In general, integer sizes
will be rounded up to the closest power of two.
member describes the length of the integer in bytes.
In general, integer sizes will be rounded up to the closest power of two.
.Lp
The integer encoding contains three different pieces of information:
.Bl -bullet -offset indent -compact
@ -804,33 +849,37 @@ The following flags are defined for the encoding at this time:
.Lp
By default, an integer is considered to be unsigned, unless it has the
.Sy CTF_INT_SIGNED
flag set. If the flag
flag set.
If the flag
.Sy CTF_INT_CHAR
is set, that indicates that the integer is of a type that stores character
data, for example the intrinsic C type
.Sy char
would have the
.Sy CTF_INT_CHAR
flag set. If the flag
flag set.
If the flag
.Sy CTF_INT_BOOL
is set, that indicates that the integer represents a boolean type. For example,
the intrinsic C type
is set, that indicates that the integer represents a boolean type.
For example, the intrinsic C type
.Sy _Bool
would have the
.Sy CTF_INT_BOOL
flag set. Finally, the flag
flag set.
Finally, the flag
.Sy CTF_INT_VARARGS
indicates that the integer is used as part of a variable number of arguments.
This encoding is rather uncommon.
.Ss Encoding of Floats
Floats, which are of type
.Sy CTF_K_FLOAT ,
are similar to their integer counterparts. They have no variable length
arguments and are followed by a four byte encoding which describes the kind of
float that exists. The
are similar to their integer counterparts.
They have no variable length arguments and are followed by a four byte encoding
which describes the kind of float that exists.
The
.Em ctt_size
member is the size, in bytes, of the float. The float encoding has three
different pieces of information inside of it:
member is the size, in bytes, of the float.
The float encoding has three different pieces of information inside of it:
.Lp
.Bl -bullet -offset indent -compact
.It
@ -855,11 +904,12 @@ This encoding can be expressed through the following macros:
(((encoding) << 24) | ((offset) << 16) | (bits))
.Ed
.Lp
Where as the encoding for integers was a series of flags, the encoding for
floats maps to a specific kind of float. It is not a flag-based value. The kinds of floats
correspond to both their size, and the encoding. This covers all of the basic C
intrinsic floating point types. The following are the different kinds of floats
represented in the encoding:
Where as the encoding for integers is a series of flags, the encoding for
floats maps to a specific kind of float.
It is not a flag-based value.
The kinds of floats correspond to both their size, and the encoding.
This covers all of the basic C intrinsic floating point types.
The following are the different kinds of floats represented in the encoding:
.Bd -literal -offset indent
#define CTF_FP_SINGLE 1 /* IEEE 32-bit float encoding */
#define CTF_FP_DOUBLE 2 /* IEEE 64-bit float encoding */
@ -877,12 +927,14 @@ represented in the encoding:
.Ss Encoding of Arrays
Arrays, which are of type
.Sy CTF_K_ARRAY ,
have no variable length arguments. They are followed by a structure which
describes the number of elements in the array, the type identifier of the
elements in the array, and the type identifier of the index of the array. With
arrays, the
have no variable length arguments.
They are followed by a structure which describes the number of elements in the
array, the type identifier of the elements in the array, and the type identifier
of the index of the array.
With arrays, the
.Em ctt_size
member is set to zero. The structure that follows an array is defined as:
member is set to zero.
The structure that follows an array is defined as:
.Bd -literal
typedef struct ctf_array {
ushort_t cta_contents; /* reference to type of array contents */
@ -901,14 +953,15 @@ are type identifiers which are encoded as per the section
.Sx Type Identifiers .
The member
.Em cta_nelems
is a simple four byte unsigned count of the number of elements. This count may
be zero when encountering C99's flexible array members.
is a simple four byte unsigned count of the number of elements.
This count may be zero when encountering C99's flexible array members.
.Ss Encoding of Functions
Function types, which are of type
.Sy CTF_K_FUNCTION ,
use the variable length list to be the number of arguments in the function. When
the function has a final member which is a varargs, then the argument count is
incremented by one to account for the variable argument. Here, the
use the variable length list to be the number of arguments in the function.
When the function has a final member which is a varargs, then the argument count
is incremented by one to account for the variable argument.
Here, the
.Em ctt_type
member is encoded with the type identifier of the return type of the function.
Note that the
@ -916,31 +969,40 @@ Note that the
member is not used here.
.Lp
The variable argument list contains the type identifiers for the arguments of
the function, if any. Each one is represented by a
the function, if any.
Each one is represented by a
.Sy uint16_t
and encoded according to the
.Sx Type Identifiers
section. If the function's last argument is of type varargs, then it is also
written out, but the type identifier is zero. This is included in the count of
the function's arguments.
section.
If the function's last argument is of type varargs, then it is also written out,
but the type identifier is zero.
This is included in the count of the function's arguments.
An extra type identifier may follow the argument and return type identifiers
in order to maintain four-byte alignment for the following type definition.
Such a type identifier is not included in the argument count and has a value
of zero.
.Ss Encoding of Structures and Unions
Structures and Unions, which are encoded with
.Sy CTF_K_STRUCT
and
.Sy CTF_K_UNION
respectively, are very similar constructs in C. The main difference
between them is the fact that every member of a structure follows one another,
where as in a union, all members share the same memory. They are also very
similar in terms of their encoding in
respectively, are very similar constructs in C.
The main difference between them is the fact that members of a structure
follow one another, where as in a union, all members share the same memory.
They are also very similar in terms of their encoding in
.Nm .
The variable length argument for structures and unions represents the number of
members that they have. The value of the member
members that they have.
The value of the member
.Em ctt_size
is the size of the structure and union. There are two different structures which
are used to encode members in the variable list. When the size of a structure or
union is greater than or equal to the large member threshold, 8192, then a
different structure is used to encode the member, all members are encoded using
the same structure. The structure for members is as follows:
is the size of the structure and union.
There are two different structures which are used to encode members in the
variable list.
When the size of a structure or union is greater than or equal to the large
member threshold, 8192, then a different structure is used to encode the member,
all members are encoded using the same structure.
The structure for members is as follows:
.Bd -literal
typedef struct ctf_member {
uint_t ctm_name; /* reference to name in string table */
@ -961,54 +1023,66 @@ Both the
.Em ctm_name
and
.Em ctlm_name
refer to the name of the member. The name is encoded as an offset into the
string table as described by the section
refer to the name of the member.
The name is encoded as an offset into the string table as described by the
section
.Sx String Identifiers .
The members
.Sy ctm_type
and
.Sy ctlm_type
both refer to the type of the member. They are encoded as per the section
both refer to the type of the member.
They are encoded as per the section
.Sx Type Identifiers .
.Lp
The last piece of information that is present is the offset which describes the
offset in memory that the member begins at. For unions, this value will always
be zero because the start of unions in memory is always zero. For structures,
this is the offset in
offset in memory at which the member begins.
For unions, this value will always be zero because each member of a union has
an offset of zero.
For structures, this is the offset in
.Sy bits
that the member begins at. Note that a compiler may lay out a type with padding.
at which the member begins.
Note that a compiler may lay out a type with padding.
This means that the difference in offset between two consecutive members may be
larger than the size of the member. When the size of the overall structure is
strictly less than 8192 bytes, the normal structure,
larger than the size of the member.
When the size of the overall structure is strictly less than 8192 bytes, the
normal structure,
.Sy ctf_member_t ,
is used and the offset in bits is stored in the member
.Em ctm_offset .
However, when the size of the structure is greater than or equal to 8192 bytes,
then the number of bits is split into two 32-bit quantities. One member,
then the number of bits is split into two 32-bit quantities.
One member,
.Em ctlm_offsethi ,
represents the upper 32 bits of the offset, while the other member,
.Em ctlm_offsetlo ,
represents the lower 32 bits of the offset. These can be joined together to get
a 64-bit sized offset in bits by shifting the member
represents the lower 32 bits of the offset.
These can be joined together to get a 64-bit sized offset in bits by shifting
the member
.Em ctlm_offsethi
to the left by thirty two and then doing a binary or of
.Em ctlm_offsetlo .
.Ss Encoding of Enumerations
Enumerations, noted by the type
.Sy CTF_K_ENUM ,
are similar to structures. Enumerations use the variable list to note the number
of values that the enumeration contains, which we'll term enumerators. In C, an
enumeration is always equivalent to the intrinsic type
are similar to structures.
Enumerations use the variable list to note the number of values that the
enumeration contains, which we'll term enumerators.
In C, an enumeration is always equivalent to the intrinsic type
.Sy int ,
thus the value of the member
.Em ctt_size
is always the size of an integer which is determined based on the current model.
For illumos systems, this will always be 4, as an integer is always defined to
For
.Fx
systems, this will always be 4, as an integer is always defined to
be 4 bytes large in both
.Sy ILP32
and
.Sy LP64 ,
regardless of the architecture.
For further details, see
.Xr arch 7 .
.Lp
The enumerators encoded in an enumeration have the following structure in the
variable list:
@ -1032,25 +1106,27 @@ Forward references, types of kind
.Sy CTF_K_FORWARD ,
in a
.Nm
file refer to types which may not have a definition at all, only a name. If
the
file refer to types which may not have a definition at all, only a name.
If the
.Nm
file is a child, then it may be that the forward is resolved to an
actual type in the parent, otherwise the definition may be in another
.Nm
container or may not be known at all. The only member of the
container or may not be known at all.
The only member of the
.Sy ctf_type_t
that matters for a forward declaration is the
.Em ctt_name
which points to the name of the forward reference in the string table as
described earlier. There is no other information recorded for forward
references.
described earlier.
There is no other information recorded for forward references.
.Ss Encoding of Pointers, Typedefs, Volatile, Const, and Restrict
Pointers, typedefs, volatile, const, and restrict are all similar in
.Nm .
They all refer to another type. In the case of typedefs, they provide an
alternate name, while volatile, const, and restrict change how the type is
interpreted in the C programming language. This covers the
They all refer to another type.
In the case of typedefs, they provide an alternate name, while volatile, const,
and restrict change how the type is interpreted in the C programming language.
This covers the
.Nm
kinds
.Sy CTF_K_POINTER ,
@ -1066,43 +1142,49 @@ to refer to the base type that they modify.
.Ss Encoding of Unknown Types
Types with the kind
.Sy CTF_K_UNKNOWN
are used to indicate gaps in the type identifier space. These entries consume an
identifier, but do not define anything. Nothing should refer to these gap
identifiers.
are used to indicate gaps in the type identifier space.
These entries consume an identifier, but do not define anything.
Nothing should refer to these gap identifiers.
.Ss Dependencies Between Types
C types can be imagined as a directed, cyclic, graph. Structures and unions may
refer to each other in a way that creates a cyclic dependency. In cases such as
these, the entire type section must be read in and processed. Consumers must
not assume that every type can be laid out in dependency order; they
cannot.
C types can be imagined as a directed, cyclic, graph.
Structures and unions may refer to each other in a way that creates a cyclic
dependency.
In cases such as these, the entire type section must be read in and processed.
Consumers must not assume that every type can be laid out in dependency order;
they cannot.
.Ss The String Section
The last section of the
.Nm
file is the
.Sy string
section. This section encodes all of the strings that appear throughout
the other sections. It is laid out as a series of characters followed by
a null terminator. Generally, all names are written out in ASCII, as
most C compilers do not allow and characters to appear in identifiers
outside of a subset of ASCII. However, any extended characters sets
should be written out as a series of UTF-8 bytes.
section.
This section encodes all of the strings that appear throughout the other
sections.
It is laid out as a series of characters followed by a null terminator.
Generally, all names are written out in ASCII, as most C compilers do not allow
any characters to appear in identifiers outside of a subset of ASCII.
However, any extended characters sets should be written out as a series of UTF-8
bytes.
.Lp
The first entry in the section, at offset zero, is a single null
terminator to reference the empty string. Following that, each C string
should be written out, including the null terminator. Offsets that refer
to something in this section should refer to the first byte which begins
a string. Beyond the first byte in the section being the null
terminator, the order of strings is unimportant.
terminator to reference the empty string.
Following that, each C string should be written out, including the null
terminator.
Offsets that refer to something in this section should refer to the first byte
which begins a string.
Beyond the first byte in the section being the null terminator, the order of
strings is unimportant.
.Ss Data Encoding and ELF Considerations
.Nm
data is generally included in ELF objects which specify information to
identify the architecture and endianness of the file. A
identify the architecture and endianness of the file.
A
.Nm
container inside such an object must match the endianness of the ELF
object. Aside from the question of the endian encoding of data, there
should be no other differences between architectures. While many of the
types in this document refer to non-fixed size C integral types, they
are equivalent in the models
container inside such an object must match the endianness of the ELF object.
Aside from the question of the endian encoding of data, there should be no other
differences between architectures.
While many of the types in this document refer to non-fixed size C integral
types, they are equivalent in the models
.Sy ILP32
and
.Sy LP64 .
@ -1118,15 +1200,16 @@ When placing a
container inside of an ELF object, there are certain conventions that are
expected for the purposes of tooling being able to find the
.Nm
data. In particular, a given ELF object should only contain a single
data.
In particular, a given ELF object should only contain a single
.Nm
section. Multiple containers should be merged together into a single
one.
section.
Multiple containers should be merged together into a single one.
.Lp
The
.Nm
file should be included in its own ELF section. The section's name
must be
file should be included in its own ELF section.
The section's name must be
.Ql .SUNW_ctf .
The type of the section must be
.Sy SHT_PROGBITS .
@ -1137,4 +1220,5 @@ alignment must be 4.
.Xr elf 3 ,
.Xr gelf 3 ,
.Xr a.out 5 ,
.Xr elf 5
.Xr elf 5 ,
.Xr arch 7

View File

@ -434,7 +434,7 @@ dt_dis(const dtrace_difo_t *dp, FILE *fp)
ulong_t i = 0;
char type[DT_TYPE_NAMELEN];
(void) fprintf(fp, "\nDIFO 0x%p returns %s\n", (void *)dp,
(void) fprintf(fp, "\nDIFO %p returns %s\n", (void *)dp,
dt_dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
(void) fprintf(fp, "%-3s %-8s %s\n",

View File

@ -229,10 +229,12 @@ prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep)
for (j = 0; j < nrel; j++) {
#if defined(__aarch64__)
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
printf("%s:%s(%d): aarch64 not implemented\n",
__FUNCTION__, __FILE__, __LINE__);
#elif defined(__arm__)
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
printf("%s:%s(%d): arm not implemented\n",
__FUNCTION__, __FILE__, __LINE__);
#elif defined(__i386) || defined(__amd64)
rel->r_offset = s->dofs_offset +
dofr[j].dofr_offset;
@ -240,7 +242,8 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
R_386_PC32);
#elif defined(__mips__)
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
printf("%s:%s(%d): MIPS not implemented\n",
__FUNCTION__, __FILE__, __LINE__);
#elif defined(__powerpc__)
/*
* Add 4 bytes to hit the low half of this 64-bit
@ -252,7 +255,8 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
R_PPC_REL32);
#elif defined(__riscv)
/* XXX */
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
printf("%s:%s(%d): RISC-V not implemented\n",
__FUNCTION__, __FILE__, __LINE__);
#else
#error unknown ISA
#endif
@ -802,7 +806,8 @@ 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__);
printf("%s:%s(%d): aarch64 not implemented\n", __FUNCTION__, __FILE__,
__LINE__);
return (0);
}
#elif defined(__arm__)
@ -811,7 +816,8 @@ 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__);
printf("%s:%s(%d): arm not implemented\n", __FUNCTION__, __FILE__,
__LINE__);
return (0);
}
#elif defined(__mips__)
@ -820,7 +826,8 @@ 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__);
printf("%s:%s(%d): MIPS not implemented\n", __FUNCTION__, __FILE__,
__LINE__);
return (0);
}
#elif defined(__powerpc__)
@ -910,7 +917,8 @@ 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__);
printf("%s:%s(%d): RISC-V implementation required\n", __FUNCTION__,
__FILE__, __LINE__);
return (0);
}
#elif defined(__sparc)

View File

@ -377,7 +377,7 @@ dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
ctf_id_t rtype;
if (ctf_array_info(ctfp, base, &car) == CTF_ERR) {
(void) fprintf(fp, "0x%p", (void *)addr);
(void) fprintf(fp, "%p", (void *)addr);
return;
}

View File

@ -426,7 +426,8 @@ dt_proc_attach(dt_proc_t *dpr, int exec)
static void
dt_proc_waitrun(dt_proc_t *dpr)
{
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
printf("%s:%s(%d): not implemented\n", __FUNCTION__, __FILE__,
__LINE__);
#ifdef DOODAD
struct ps_prochandle *P = dpr->dpr_proc;
const lwpstatus_t *psp = &Pstatus(P)->pr_lwp;

View File

@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright (c) 2013 Martin Matuska. All rights reserved.
@ -2166,6 +2166,7 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
if (zfs_prop_readonly(prop) &&
*source != NULL && (*source)[0] == '\0') {
*source = NULL;
return (-1);
}
break;
@ -2354,6 +2355,74 @@ zfs_get_clones_nvl(zfs_handle_t *zhp)
return (value);
}
/*
* Accepts a property and value and checks that the value
* matches the one found by the channel program. If they are
* not equal, print both of them.
*/
void
zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval,
const char *strval)
{
if (!zhp->zfs_hdl->libzfs_prop_debug)
return;
int error;
char *poolname = zhp->zpool_hdl->zpool_name;
const char *program =
"args = ...\n"
"ds = args['dataset']\n"
"prop = args['property']\n"
"value, setpoint = zfs.get_prop(ds, prop)\n"
"return {value=value, setpoint=setpoint}\n";
nvlist_t *outnvl;
nvlist_t *retnvl;
nvlist_t *argnvl = fnvlist_alloc();
fnvlist_add_string(argnvl, "dataset", zhp->zfs_name);
fnvlist_add_string(argnvl, "property", zfs_prop_to_name(prop));
error = lzc_channel_program(poolname, program,
10 * 1000 * 1000, 10 * 1024 * 1024, argnvl, &outnvl);
if (error == 0) {
retnvl = fnvlist_lookup_nvlist(outnvl, "return");
if (zfs_prop_get_type(prop) == PROP_TYPE_NUMBER) {
int64_t ans;
error = nvlist_lookup_int64(retnvl, "value", &ans);
if (error != 0) {
(void) fprintf(stderr, "zcp check error: %u\n",
error);
return;
}
if (ans != intval) {
(void) fprintf(stderr,
"%s: zfs found %lld, but zcp found %lld\n",
zfs_prop_to_name(prop),
(longlong_t)intval, (longlong_t)ans);
}
} else {
char *str_ans;
error = nvlist_lookup_string(retnvl, "value", &str_ans);
if (error != 0) {
(void) fprintf(stderr, "zcp check error: %u\n",
error);
return;
}
if (strcmp(strval, str_ans) != 0) {
(void) fprintf(stderr,
"%s: zfs found %s, but zcp found %s\n",
zfs_prop_to_name(prop),
strval, str_ans);
}
}
} else {
(void) fprintf(stderr,
"zcp check failed, channel program error: %u\n", error);
}
nvlist_free(argnvl);
nvlist_free(outnvl);
}
/*
* Retrieve a property from the given object. If 'literal' is specified, then
* numbers are left as exact values. Otherwise, numbers are converted to a
@ -2400,6 +2469,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
&t) == 0)
(void) snprintf(propbuf, proplen, "%llu", val);
}
zcp_check(zhp, prop, val, NULL);
break;
case ZFS_PROP_MOUNTPOINT:
@ -2468,7 +2538,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
/* 'legacy' or 'none' */
(void) strlcpy(propbuf, str, proplen);
}
zcp_check(zhp, prop, NULL, propbuf);
break;
case ZFS_PROP_ORIGIN:
@ -2476,6 +2546,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
if (str == NULL)
return (-1);
(void) strlcpy(propbuf, str, proplen);
zcp_check(zhp, prop, NULL, str);
break;
case ZFS_PROP_CLONES:
@ -2490,7 +2561,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
return (-1);
/*
* If quota or reservation is 0, we translate this into 'none'
* (unless literal is set), and indicate that it's the default
@ -2509,6 +2579,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
else
zfs_nicenum(val, propbuf, proplen);
}
zcp_check(zhp, prop, val, NULL);
break;
case ZFS_PROP_FILESYSTEM_LIMIT:
@ -2533,6 +2604,8 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
} else {
zfs_nicenum(val, propbuf, proplen);
}
zcp_check(zhp, prop, val, NULL);
break;
case ZFS_PROP_REFRATIO:
@ -2542,6 +2615,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
(void) snprintf(propbuf, proplen, "%llu.%02llux",
(u_longlong_t)(val / 100),
(u_longlong_t)(val % 100));
zcp_check(zhp, prop, val, NULL);
break;
case ZFS_PROP_TYPE:
@ -2562,6 +2636,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
abort();
}
(void) snprintf(propbuf, proplen, "%s", str);
zcp_check(zhp, prop, NULL, propbuf);
break;
case ZFS_PROP_MOUNTED:
@ -2587,6 +2662,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
* consumers.
*/
(void) strlcpy(propbuf, zhp->zfs_name, proplen);
zcp_check(zhp, prop, NULL, propbuf);
break;
case ZFS_PROP_MLSLABEL:
@ -2640,26 +2716,33 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
return (-1);
(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
zcp_check(zhp, prop, val, NULL);
break;
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
if (get_numeric_property(zhp, prop, src,
&source, &val) != 0)
&source, &val) != 0) {
return (-1);
if (literal)
}
if (literal) {
(void) snprintf(propbuf, proplen, "%llu",
(u_longlong_t)val);
else
} else {
zfs_nicenum(val, propbuf, proplen);
}
zcp_check(zhp, prop, val, NULL);
break;
case PROP_TYPE_STRING:
str = getprop_string(zhp, prop, &source);
if (str == NULL)
return (-1);
(void) strlcpy(propbuf, str, proplen);
zcp_check(zhp, prop, NULL, str);
break;
case PROP_TYPE_INDEX:
@ -2668,7 +2751,9 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
return (-1);
if (zfs_prop_index_to_string(prop, val, &strval) != 0)
return (-1);
(void) strlcpy(propbuf, strval, proplen);
zcp_check(zhp, prop, NULL, strval);
break;
default:

View File

@ -55,15 +55,6 @@
#define ZDIFF_REMOVED '-'
#define ZDIFF_RENAMED 'R'
static boolean_t
do_name_cmp(const char *fpath, const char *tpath)
{
char *fname, *tname;
fname = strrchr(fpath, '/') + 1;
tname = strrchr(tpath, '/') + 1;
return (strcmp(fname, tname) == 0);
}
typedef struct differ_info {
zfs_handle_t *zhp;
char *fromsnap;
@ -262,7 +253,6 @@ static int
write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
{
struct zfs_stat fsb, tsb;
boolean_t same_name;
mode_t fmode, tmode;
char fobjname[MAXPATHLEN], tobjname[MAXPATHLEN];
int fobjerr, tobjerr;
@ -323,7 +313,6 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
if (fmode != tmode && fsb.zs_gen == tsb.zs_gen)
tsb.zs_gen++; /* Force a generational difference */
same_name = do_name_cmp(fobjname, tobjname);
/* Simple modification or no change */
if (fsb.zs_gen == tsb.zs_gen) {
@ -334,7 +323,7 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
if (change) {
print_link_change(fp, di, change,
change > 0 ? fobjname : tobjname, &tsb);
} else if (same_name) {
} else if (strcmp(fobjname, tobjname) == 0) {
print_file(fp, di, ZDIFF_MODIFIED, fobjname, &tsb);
} else {
print_rename(fp, di, fobjname, tobjname, &tsb);

View File

@ -79,6 +79,7 @@ struct libzfs_handle {
libzfs_fru_t **libzfs_fru_hash;
libzfs_fru_t *libzfs_fru_list;
char libzfs_chassis_id[256];
boolean_t libzfs_prop_debug;
};
#define ZFSSHARE_MISS 0x01 /* Didn't find entry in cache */

View File

@ -42,6 +42,7 @@
* using our derived config, and record the results.
*/
#include <aio.h>
#include <ctype.h>
#include <devid.h>
#include <dirent.h>
@ -865,6 +866,7 @@ label_offset(uint64_t size, int l)
/*
* Given a file descriptor, read the label information and return an nvlist
* describing the configuration, if there is one.
* Return 0 on success, or -1 on failure
*/
int
zpool_read_label(int fd, nvlist_t **config)
@ -877,7 +879,7 @@ zpool_read_label(int fd, nvlist_t **config)
*config = NULL;
if (fstat64(fd, &statbuf) == -1)
return (0);
return (-1);
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
if ((label = malloc(sizeof (vdev_label_t))) == NULL)
@ -911,20 +913,24 @@ zpool_read_label(int fd, nvlist_t **config)
free(label);
*config = NULL;
return (0);
return (-1);
}
/*
* Given a file descriptor, read the label information and return an nvlist
* describing the configuration, if there is one.
* returns the number of valid labels found
* If a label is found, returns it via config. The caller is responsible for
* freeing it.
*/
int
zpool_read_all_labels(int fd, nvlist_t **config)
{
struct stat64 statbuf;
struct aiocb aiocbs[VDEV_LABELS];
struct aiocb *aiocbps[VDEV_LABELS];
int l;
vdev_label_t *label;
vdev_phys_t *labels;
uint64_t state, txg, size;
int nlabels = 0;
@ -934,19 +940,40 @@ zpool_read_all_labels(int fd, nvlist_t **config)
return (0);
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
if ((label = malloc(sizeof (vdev_label_t))) == NULL)
if ((labels = calloc(VDEV_LABELS, sizeof (vdev_phys_t))) == NULL)
return (0);
memset(aiocbs, 0, sizeof(aiocbs));
for (l = 0; l < VDEV_LABELS; l++) {
aiocbs[l].aio_fildes = fd;
aiocbs[l].aio_offset = label_offset(size, l) + VDEV_SKIP_SIZE;
aiocbs[l].aio_buf = &labels[l];
aiocbs[l].aio_nbytes = sizeof(vdev_phys_t);
aiocbs[l].aio_lio_opcode = LIO_READ;
aiocbps[l] = &aiocbs[l];
}
if (lio_listio(LIO_WAIT, aiocbps, VDEV_LABELS, NULL) != 0) {
if (errno == EAGAIN || errno == EINTR || errno == EIO) {
for (l = 0; l < VDEV_LABELS; l++) {
errno = 0;
int r = aio_error(&aiocbs[l]);
if (r != EINVAL)
(void)aio_return(&aiocbs[l]);
}
}
free(labels);
return (0);
}
for (l = 0; l < VDEV_LABELS; l++) {
nvlist_t *temp = NULL;
/* TODO: use aio_read so we can read al 4 labels in parallel */
if (pread64(fd, label, sizeof (vdev_label_t),
label_offset(size, l)) != sizeof (vdev_label_t))
if (aio_return(&aiocbs[l]) != sizeof(vdev_phys_t))
continue;
if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
sizeof (label->vl_vdev_phys.vp_nvlist), &temp, 0) != 0)
if (nvlist_unpack(labels[l].vp_nvlist,
sizeof (labels[l].vp_nvlist), &temp, 0) != 0)
continue;
if (nvlist_lookup_uint64(temp, ZPOOL_CONFIG_POOL_STATE,
@ -969,7 +996,7 @@ zpool_read_all_labels(int fd, nvlist_t **config)
nlabels++;
}
free(label);
free(labels);
return (nlabels);
}
@ -1148,7 +1175,7 @@ zpool_open_func(void *arg)
}
#endif /* illumos */
if ((zpool_read_label(fd, &config)) != 0) {
if ((zpool_read_label(fd, &config)) != 0 && errno == ENOMEM) {
(void) close(fd);
(void) no_memory(rn->rn_hdl);
return;
@ -1649,7 +1676,7 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
*inuse = B_FALSE;
if (zpool_read_label(fd, &config) != 0) {
if (zpool_read_label(fd, &config) != 0 && errno == ENOMEM) {
(void) no_memory(hdl);
return (-1);
}

View File

@ -2295,6 +2295,7 @@ vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
return (ret);
}
} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
(is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
nvlist_t **child;

View File

@ -3212,7 +3212,12 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
/*
* Determine the name of the origin snapshot, store in zc_string.
*/
if (drrb->drr_flags & DRR_FLAG_CLONE) {
if (originsnap) {
(void) strncpy(zc.zc_string, originsnap, sizeof (zc.zc_string));
if (flags->verbose)
(void) printf("using provided clone origin %s\n",
zc.zc_string);
} else if (drrb->drr_flags & DRR_FLAG_CLONE) {
if (guid_to_name(hdl, zc.zc_value,
drrb->drr_fromguid, B_FALSE, zc.zc_string) != 0) {
zcmd_free_nvlists(&zc);
@ -3223,11 +3228,6 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
}
if (flags->verbose)
(void) printf("found clone origin %s\n", zc.zc_string);
} else if (originsnap) {
(void) strncpy(zc.zc_string, originsnap, sizeof (zc.zc_string));
if (flags->verbose)
(void) printf("using provided clone origin %s\n",
zc.zc_string);
}
boolean_t resuming = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &

View File

@ -49,6 +49,7 @@
#include <sys/mnttab.h>
#include <sys/mntent.h>
#include <sys/types.h>
#include <libcmdutils.h>
#include <libzfs.h>
#include <libzfs_core.h>
@ -579,42 +580,7 @@ zfs_strdup(libzfs_handle_t *hdl, const char *str)
void
zfs_nicenum(uint64_t num, char *buf, size_t buflen)
{
uint64_t n = num;
int index = 0;
char u;
while (n >= 1024) {
n /= 1024;
index++;
}
u = " KMGTPE"[index];
if (index == 0) {
(void) snprintf(buf, buflen, "%llu", n);
} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
/*
* If this is an even multiple of the base, always display
* without any decimal precision.
*/
(void) snprintf(buf, buflen, "%llu%c", n, u);
} else {
/*
* We want to choose a precision that reflects the best choice
* for fitting in 5 characters. This can get rather tricky when
* we have numbers that are very close to an order of magnitude.
* For example, when displaying 10239 (which is really 9.999K),
* we want only a single place of precision for 10.0K. We could
* develop some complex heuristics for this, but it's much
* easier just to try each combination in turn.
*/
int i;
for (i = 2; i >= 0; i--) {
if (snprintf(buf, buflen, "%.*f%c", i,
(double)num / (1ULL << 10 * index), u) <= 5)
break;
}
}
nicenum(num, buf, buflen);
}
void
@ -678,6 +644,10 @@ libzfs_init(void)
zpool_feature_init();
libzfs_mnttab_init(hdl);
if (getenv("ZFS_PROP_DEBUG") != NULL) {
hdl->libzfs_prop_debug = B_TRUE;
}
return (hdl);
}

View File

@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2012, 2017 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 RackTop Systems.
@ -160,7 +160,12 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
if (resultp != NULL) {
*resultp = NULL;
zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
if (ioc == ZFS_IOC_CHANNEL_PROGRAM) {
zc.zc_nvlist_dst_size = fnvlist_lookup_uint64(source,
ZCP_ARG_MEMLIMIT);
} else {
zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
}
zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
malloc(zc.zc_nvlist_dst_size);
#ifdef illumos
@ -174,7 +179,15 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
}
while (ioctl(g_fd, ioc, &zc) != 0) {
if (errno == ENOMEM && resultp != NULL) {
/*
* If ioctl exited with ENOMEM, we retry the ioctl after
* increasing the size of the destination nvlist.
*
* Channel programs that exit with ENOMEM ran over the
* lua memory sandbox; they should not be retried.
*/
if (errno == ENOMEM && resultp != NULL &&
ioc != ZFS_IOC_CHANNEL_PROGRAM) {
free((void *)(uintptr_t)zc.zc_nvlist_dst);
zc.zc_nvlist_dst_size *= 2;
zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
@ -904,3 +917,54 @@ lzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **errlist)
return (error);
}
/*
* Executes a channel program.
*
* If this function returns 0 the channel program was successfully loaded and
* ran without failing. Note that individual commands the channel program ran
* may have failed and the channel program is responsible for reporting such
* errors through outnvl if they are important.
*
* This method may also return:
*
* EINVAL The program contains syntax errors, or an invalid memory or time
* limit was given. No part of the channel program was executed.
* If caused by syntax errors, 'outnvl' contains information about the
* errors.
*
* EDOM The program was executed, but encountered a runtime error, such as
* calling a function with incorrect arguments, invoking the error()
* function directly, failing an assert() command, etc. Some portion
* of the channel program may have executed and committed changes.
* Information about the failure can be found in 'outnvl'.
*
* ENOMEM The program fully executed, but the output buffer was not large
* enough to store the returned value. No output is returned through
* 'outnvl'.
*
* ENOSPC The program was terminated because it exceeded its memory usage
* limit. Some portion of the channel program may have executed and
* committed changes to disk. No output is returned through 'outnvl'.
*
* ETIMEDOUT The program was terminated because it exceeded its Lua instruction
* limit. Some portion of the channel program may have executed and
* committed changes to disk. No output is returned through 'outnvl'.
*/
int
lzc_channel_program(const char *pool, const char *program, uint64_t instrlimit,
uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
{
int error;
nvlist_t *args;
args = fnvlist_alloc();
fnvlist_add_string(args, ZCP_ARG_PROGRAM, program);
fnvlist_add_nvlist(args, ZCP_ARG_ARGLIST, argnvl);
fnvlist_add_uint64(args, ZCP_ARG_INSTRLIMIT, instrlimit);
fnvlist_add_uint64(args, ZCP_ARG_MEMLIMIT, memlimit);
error = lzc_ioctl(ZFS_IOC_CHANNEL_PROGRAM, pool, args, outnvl);
fnvlist_free(args);
return (error);
}

View File

@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright 2017 RackTop Systems.
*/
@ -86,6 +86,9 @@ boolean_t lzc_exists(const char *);
int lzc_rollback(const char *, char *, int);
int lzc_rollback_to(const char *, const char *);
int lzc_channel_program(const char *, const char *, uint64_t, uint64_t,
nvlist_t *, nvlist_t **);
#ifdef __cplusplus
}
#endif

View File

@ -738,6 +738,7 @@ vpanic(const char *fmt, va_list adx)
char buf[512];
(void) vsnprintf(buf, 512, fmt, adx);
assfail(buf, NULL, 0);
abort(); /* necessary to make vpanic meet noreturn requirements */
}
void

View File

@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
/*
@ -66,6 +66,7 @@ extern "C" {
#include <fsshare.h>
#include <pthread.h>
#include <sched.h>
#include <setjmp.h>
#include <sys/debug.h>
#include <sys/note.h>
#include <sys/types.h>
@ -126,8 +127,8 @@ extern void dprintf_setup(int *argc, char **argv);
extern void cmn_err(int, const char *, ...);
extern void vcmn_err(int, const char *, __va_list);
extern void panic(const char *, ...);
extern void vpanic(const char *, __va_list);
extern void panic(const char *, ...) __NORETURN;
extern void vpanic(const char *, __va_list) __NORETURN;
#define fm_panic panic
@ -349,6 +350,7 @@ extern void cv_broadcast(kcondvar_t *cv);
#define KM_SLEEP UMEM_NOFAIL
#define KM_PUSHPAGE KM_SLEEP
#define KM_NOSLEEP UMEM_DEFAULT
#define KM_NORMALPRI 0 /* not needed with UMEM_DEFAULT */
#define KMC_NODEBUG UMC_NODEBUG
#define KMC_NOTOUCH 0 /* not needed for userland caches */
#define KM_NODEBUG 0
@ -579,8 +581,9 @@ extern void kernel_init(int);
extern void kernel_fini(void);
struct spa;
extern void nicenum(uint64_t num, char *buf);
extern void nicenum(uint64_t num, char *buf, size_t);
extern void show_pool_stats(struct spa *);
extern int set_global_var(char *arg);
typedef struct callb_cpr {
kmutex_t *cc_lockp;

View File

@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
#include <assert.h>
@ -31,38 +32,12 @@
#include <sys/spa.h>
#include <sys/fs/zfs.h>
#include <sys/refcount.h>
#include <dlfcn.h>
/*
* Routines needed by more than one client of libzpool.
*/
void
nicenum(uint64_t num, char *buf)
{
uint64_t n = num;
int index = 0;
char u;
while (n >= 1024) {
n = (n + (1024 / 2)) / 1024; /* Round up or down */
index++;
}
u = " KMGTPE"[index];
if (index == 0) {
(void) sprintf(buf, "%llu", (u_longlong_t)n);
} else if (n < 10 && (num & (num - 1)) != 0) {
(void) sprintf(buf, "%.2f%c",
(double)num / (1ULL << 10 * index), u);
} else if (n < 100 && (num & (num - 1)) != 0) {
(void) sprintf(buf, "%.1f%c",
(double)num / (1ULL << 10 * index), u);
} else {
(void) sprintf(buf, "%llu%c", (u_longlong_t)n, u);
}
}
static void
show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
{
@ -95,15 +70,17 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
sec = MAX(1, vs->vs_timestamp / NANOSEC);
nicenum(vs->vs_alloc, used);
nicenum(vs->vs_space - vs->vs_alloc, avail);
nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops);
nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops);
nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes);
nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes);
nicenum(vs->vs_read_errors, rerr);
nicenum(vs->vs_write_errors, werr);
nicenum(vs->vs_checksum_errors, cerr);
nicenum(vs->vs_alloc, used, sizeof (used));
nicenum(vs->vs_space - vs->vs_alloc, avail, sizeof (avail));
nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops, sizeof (rops));
nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops, sizeof (wops));
nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes,
sizeof (rbytes));
nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes,
sizeof (wbytes));
nicenum(vs->vs_read_errors, rerr, sizeof (rerr));
nicenum(vs->vs_write_errors, werr, sizeof (werr));
nicenum(vs->vs_checksum_errors, cerr, sizeof (cerr));
(void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
indent, "",
@ -153,3 +130,58 @@ show_pool_stats(spa_t *spa)
nvlist_free(config);
}
/*
* Sets given global variable in libzpool to given unsigned 32-bit value.
* arg: "<variable>=<value>"
*/
int
set_global_var(char *arg)
{
void *zpoolhdl;
char *varname = arg, *varval;
u_longlong_t val;
#ifndef _LITTLE_ENDIAN
/*
* On big endian systems changing a 64-bit variable would set the high
* 32 bits instead of the low 32 bits, which could cause unexpected
* results.
*/
fprintf(stderr, "Setting global variables is only supported on "
"little-endian systems\n", varname);
return (ENOTSUP);
#endif
if ((varval = strchr(arg, '=')) != NULL) {
*varval = '\0';
varval++;
val = strtoull(varval, NULL, 0);
if (val > UINT32_MAX) {
fprintf(stderr, "Value for global variable '%s' must "
"be a 32-bit unsigned integer\n", varname);
return (EOVERFLOW);
}
} else {
return (EINVAL);
}
zpoolhdl = dlopen("libzpool.so", RTLD_LAZY);
if (zpoolhdl != NULL) {
uint32_t *var;
var = dlsym(zpoolhdl, varname);
if (var == NULL) {
fprintf(stderr, "Global variable '%s' does not exist "
"in libzpool.so\n", varname);
return (EINVAL);
}
*var = (uint32_t)val;
dlclose(zpoolhdl);
} else {
fprintf(stderr, "Failed to open libzpool.so to set global "
"variable\n");
return (EIO);
}
return (0);
}

View File

@ -3,7 +3,6 @@
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
lib/${CSU_DIR} \
lib/libc \

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